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.arch | amd64 | arm64 |
include后缀 | libayatana-appindicator3-1:amd64等 | 同名库换成:arm64后缀 |
AppImage.arch | x86_64 | arm_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 里同时构建):
| 维度 | AppImage | deb / rpm | Flatpak / 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),仅供参考