☰
LocalSend 的 AppImage 打包拆解:两份 YAML 让一次构建跑遍 Ubuntu、Fedora、Arch
2026/10/7 2:30:01 网站建设 项目流程

LocalSend 的 AppImage 打包拆解:两份 YAML 让一次构建跑遍 Ubuntu、Fedora、Arch

【免费下载链接】localsendAn open-source cross-platform alternative to AirDrop项目地址: https://gitcode.com/GitHub_Trending/lo/localsend

为什么在 Fedora 上双击就能跑

把 release 页里的LocalSend-x86_64.AppImage拷到一台 Fedora 机器上,chmod +x双击,系统托盘图标直接出来,不用挨个装 GTK、不用装 libayatana。这就是 LocalSend 的 AppImage 形态的卖点:运行时依赖被塞进一个文件里,同一份构建在 Ubuntu、Fedora、Arch 上直接跑。但问题不止于此——系统托盘依赖的库很多发行版默认根本没装,必须带进包里;包体积又得压住。LocalSend 的答案简单得超出预期:两份 YAML 加一个 shell 脚本。

桌面版 AppImage 与手机在同一局域网互相发现,设备名和指纹直接对上

构建脚本里哪几行是关键?

入口是 support/scripts/compile_linux_appimage.sh,核心就这几行:

git submodule update --init # Flutter SDK 以子模块形式锁进仓库 alias flutter='submodules/flutter/bin/flutter' # flutter 命令指向仓库内的 SDK flutter clean flutter pub get flutter pub run build_runner build -d # 代码生成:i18n 字符串、riverpod 绑定等 flutter build linux cp -r build/linux/x64/release/bundle/* AppDir # 构建产物整个拷进 AppDir

设计意图是可复现:本地脚本用 git 子模块锁 Flutter 版本,CI 则用FLUTTER_VERSION: "3.41.9"钉死(见 build_linux_appimage_x64.yml),两边不会用到不同编译器。产物不是单个二进制,而是整个bundle/目录——AppImage 打包就是这个目录再塞几个 apt 库,一起压进 squashfs。

appimage-builder 配方里到底带了哪些库

support/build/appimage/AppImageBuilder_x86_64.yml 全文不到 70 行,核心是apt段,整个仓库只带两个库:

apt: arch: [amd64] allow_unauthenticated: true # 跳过 gpg 校验,CI 里省事 sources: - sourceline: deb http://archive.ubuntu.com/ubuntu/ jammy main restricted # ... 还有 jammy-updates、jammy-security 等,共 9 条源 include: - libayatana-appindicator3-1:amd64 # 系统托盘:tray_manager 插件走 AppIndicator 协议 - librsvg2-common:amd64 # GTK 渲染 SVG 图标 exclude: - adwaita-icon-theme:* # 把整包主题图标排除掉

libayatana-appindicator3-1是托盘图标的关键。app/pubspec.yaml里声明了tray_manager: 0.5.3,这个插件在 Linux 上靠 AppIndicator 协议画托盘图标,没有这个库,应用能启动但托盘直接消失。librsvg2-common负责 SVG 图标渲染。两个库都从 Ubuntu 22.04(jammy)的源里拉,main/universe/multiverse 的源全部显式列出了。

这里就是 AppImage 跨发行版的根因:运行时只依赖宿主机内核和 FUSE,宿主机装没装 GTK、装的什么版本,都不重要——需要的库全在镜像里。依赖基线就是"jammy 上能跑的版本",而 jammy 是 LTS,版本稳定不会漂移。

exclude: adwaita-icon-theme:*也别忽略:apt 装某些库会连带拉进整套 Adwaita 主题图标,好几个 MB,显式排掉。

包里排除了哪些文件

同一个 YAML 的files.exclude是第二个减重点,排掉 apt 包自带的 man 页和文档:

files: exclude: - usr/share/man - usr/share/doc/*/README.* - usr/share/doc/*/changelog.* - usr/share/doc/*/NEWS.* - usr/share/doc/*/TODO.*

这些都是没人会读的文件,排掉不影响任何功能。配合上一节的exclude,最终包体积大致等于"Flutter 构建 bundle + 两个库",没有多余的东西。

托盘图标和图标是怎么进 AppDir 的

app_info里写着icon: localsend,引用一个叫 localsend 的图标,但 Flutter 构建产物里没有它。CI 里有一步 "Copy logo to AppDir",专门把三档 logo 拷进标准 hicolor 图标目录:

cp app/assets/img/logo-32.png AppDir/usr/share/icons/hicolor/32x32/apps/localsend.png cp app/assets/img/logo-128.png AppDir/usr/share/icons/hicolor/128x128/apps/localsend.png cp app/assets/img/logo-256.png AppDir/usr/share/icons/hicolor/256x256/apps/localsend.png

这一步漏掉,菜单栏和桌面菜单就没有图标。

配方里还有两行管运行时行为:

app_info: exec: localsend_app exec_args: $@ # 命令行参数原样传给应用 runtime: env: XDG_DATA_DIRS: '/usr/local/share/:/usr/share/:${XDG_DATA_DIRS}'
  • exec_args: $@把命令行参数透传给应用,外部用 URL 唤起时应用能收到。
  • XDG_DATA_DIRS把 AppImage 内部的/usr/share放在最前面,镜像内的图标和 desktop 文件能被找到,末尾保留宿主机的原值兜底。

两个架构的配置差在哪

x86_64 和 ARM64 是两份几乎一样的 YAML(AppImageBuilder_x86_64.yml/AppImageBuilder_arm_64.yml,都在support/build/appimage/下),只有三处不同:

项x86_64 配置ARM64 配置
apt.archamd64arm64
include后缀libayatana-appindicator3-1:amd64等同名库换成:arm64后缀
AppImage.archx86_64arm_64

同样的 jammy 源、同样的两个库、同样的排除规则,依赖管理不用维护两套。本地脚本只处理 x86_64,ARM64 走 CI 工作流build_linux_appimage_arm64.yml。

动手试一下:从双击到传输

免安装,两步看到效果:

chmod +x LocalSend-x86_64.AppImage ./LocalSend-x86_64.AppImage

启动后托盘出现 LocalSend 图标;打开主界面切到 Send 页签,添加文件,局域网内的设备几秒内出现在列表里。前提是同一网段,且防火墙放行 53317 端口(tcp 和 udp 都要)——仓库 README 直接给了 ufw 和 firewalld 的现成命令,照抄即可。Arch 用户如果不想手动跑 AppImage,AUR 里有localsend-bin可用。

Send 页签添加 4 个文件后,附近设备列表里出现目标手机,带设备名和指纹编号

选中设备点发送,进度窗口里能看到实时速度:

发送进度窗口显示文件级状态和 4.9 MB/s 的实时速度

横向对比一下 Linux 上几种分发形态(仓库本身 AppImage、deb、rpm 都在 CI 里同时构建):

维度AppImagedeb / rpmFlatpak / Snap
跨发行版同一文件直接跑要分别维护两种包格式需先装运行时,底座大
托盘图标自带 libayatana,直接可用依赖系统库,老系统上可能缺失受沙箱权限配置影响
更新方式换文件包管理器升级商店推送
形态免安装,用完删装进系统目录隔离安装

这些坑先知道 ⚠️

  • allow_unauthenticated: true意味着 apt 拉库时跳过 gpg 校验。拿这份 YAML 给别的项目打包时别照抄,签名校验该开要开。
  • YAML 里version: 1.18.2是硬编码的,要和app/pubspec.yaml的1.18.2+64同步改,发版时漏改,桌面菜单里显示的就是旧版本。
  • 运行 AppImage 依赖 FUSE,构建脚本头部注释明确要求装libfuse2。双击没反应先查/dev/fuse在不在。
  • YAML 尾部注释掉了一组测试用例(fedora-30、debian-stable、archlinux-latest 等),标注原因是在 GitHub Actions 里跑不通——所以没有自动化的跨发行版启动测试,兼容性实际是靠 jammy LTS 源这个选择兜底的。
  • 配方里update-information: guess只是启用 AppImageKit 的更新探测,仓库内没有应用内自更新,升级还是自己下载新文件替换。

你该不该用

  • 适合:想在任何 Linux 机器上零配置跑 LocalSend 的用户;需要把同一份文件统一下发到一批机器的团队。
  • 不适合:希望系统包管理器接管升级和回滚、或需要严格沙箱隔离的场景——那用仓库同样提供的 deb/rpm 更合适。
  • 判断条件:目标机器是普通桌面发行版、不想装任何东西,选 AppImage 最省事;机器要靠包管理器统一管理,选 deb/rpm。

核心关键词:LocalSend AppImage、跨发行版部署长尾关键词:Flutter Linux 打包、appimage-builder 配置、LocalSend Linux 安装、AppImage 托盘图标、开源跨平台文件传输

【免费下载链接】localsendAn open-source cross-platform alternative to AirDrop项目地址: https://gitcode.com/GitHub_Trending/lo/localsend

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询