初探AppImage打包(Qt程序为例)

Share on:

Overview

这是稿件,有待完善

.AppImage文件是什么及如何解包查看

一个.AppImage文件本身是Linux ELF格式的二进制可执行文件。同时其内也含有压缩打包好的一个软件所需要的一堆文件(一般就是可执行二进制+动态库),这一堆文件会在运行此.AppImage文件时以/tmp/.mount_xxxxxxx的路径出现(用了squashfs+FUSE)。软件退出后,/tmp/.mount_xxxxxxxx会消失。

一般来说(如果正确打包了),运行时传递了参数给.AppImage文件,这些参数会传递到其内部的usr/bin/真正的可执行文件上(但也有特例,如解包参数--appimage-extract

查看或解包一.AppImage文件

学习打包前,先了解查看和解包的方法

要解包一.AppImage文件,运行:

1xxxxx.AppImage --appimage-extract

则只会将其内部的文件解包在./squashfs-root/下,不会运行软件

若想只查看.AppImage文件内部的文件列表,可以使用下面说到的appimagetool,它的-l参数是做这个的

初探AppImage打包基本要求和操作

准备一个AppDir目录,里面需要放:

 1├── AppRun                         # 从AppImage官方下载,此文件官方随同appimagetool一起发布(如果没有好像也可以,例如linuxdeploy的qt插件会生成一个shell脚本来充当它)
 2├── appentry.desktop                 # 文件名随便,后缀要.desktop。这里不能有第二个.desktop文件
 3├── logo.png                        #  文件名(去除后缀部分)与appentry.desktop中的icon=一致
 4└── usr
 5    ├── bin                         # appentry.desktop中的"exec="使用的相对路径是相对于这里
 6       ├── 可执行二进制文件            # 文件名与appentry.desktop中的exec=一致
 7    ├── lib                         # 即使是64位,也不需要命名为lib64
 8       └── 自己的软件编译出来的库(若有).so    # 如果有,需要在运行linuxdeploy时要设置LD_BRARY_PATH为这里(打包机器上的绝对路径)
 9    └── share
10        ├── applications
11           └── 软件名.desktop -> ../../../appentry.desktop
12        └── icons
13            └── hicolor
14                └── 512x512
15                    ├── 软件名.png    # (多搞几个重复的png文件没关系)
16                    └── logo.png 

其中的appentry.desktop可按模板:

1[Desktop Entry]
2Version=1.0
3Type=Application
4Categories=Qt
5Name=软件名
6Comment=软件描述
7Exec=可执行二进文件名(这里使用相对路径,相对于AppDir/usr/bin/)
8Icon=logo

下载及运行AppImage相关工具

AppImage相关工具一般不以版本号发布,许多就是发布被称为continuous的版本(或者latest),也就是说他们想要让人们一直使用最新版,然后其二进制内会有个工具编译日期。

他们发布的工具,常常每一种工具是一个.AppImage的文件

linuxdeploy

linuxdeploy会

  1. 查找AppDir下的二进制可执行文件及二进制动态库文件,并查出它们的依赖
  2. 再把需要的依赖(除内置的一黑名单外,为不需要打包的依赖)从Linux主机系统中复制进AppDir/usr/lib
  3. 再把AppDir内的所有ELF文件(包括了所有二进制可执行文件和二进制动态库文件)内容修改(打patch),都改为采用相对路径来查找依赖

linuxdeploy顺便会检查AppDir内容是否合法,有无漏东西

这里的例子是打包Qt程序。Qt程序只对可执行文件用ldd这样的方法查看其依赖是不够的,会漏掉Qt plugins,因此,因此在这里除了linuxdeploy外还需要一个linuxdeploy-plugin-qt。

linuxdeploy的插件机制(非Qt的插件,是linuxdeploy的插件)是把其插件程序像linuxdeploy-plugin-qt这样命名(其后一般还有-x86_64.AppImage),放在与linuxdeploy-x86_64.AppImage同一目录下。运行linuxdeploy时加上参数--plugin qt

另有一个工具叫linuxdeployqt,它们不一样

下载:

1wget https://github.com/linuxdeploy/linuxdeploy/releases/download/continuous/linuxdeploy-x86_64.AppImage
2wget https://github.com/linuxdeploy/linuxdeploy-plugin-qt/releases/download/continuous/linuxdeploy-plugin-qt-x86_64.AppImage
3# (记得`chmod a+x`)

运行:

1export LD_LIBRARY_PATH=打包系统中目前所放位置/AppDir/usr/lib/
2export QMAKE=打包系统中qmake程序路径  # 因此例为Qt程序故有这个 # 若能找到则不需要
3
4./linuxdeploy-x86_64.AppImage --appdir 打包系统中目前所放位置/AppDir --plugin qt [-i logo.png]

appimagetool

这是打包工具。打包这一步即是在准备好以上AppDir里的东西后,类似tarball一样压缩打包(实际上用的是squashfs)。

这个打包工具不对AppDir内容做合法性检查,就只是打包

1wget https://github.com/AppImage/AppImageKit/releases/latest/download/appimagetool-x86_64.AppImage 
2# (记得`chmod a+x`)

(可选)AppRun会被官方随appimagetool一同发布。下载并放AppRun入AppDir:

1wget https://github.com/AppImage/AppImageKit/releases/latest/download/AppRun-x86_64 
2cp AppRun-x86_64 打包系统中目前所放位置/AppDir/AppRun
3# (记得`chmod a+x`)

AppDir/AppRun这个文件就是.AppImage被执行后会第一个执行的入口程序。官方推荐用他们发布的AppRun(一个二进制程序文件)作为入口,但也可以自己写个shell脚本,重命令为AppRun放在这个位置作为入口。

打包:

1appimagetool-x86_64.AppImage  打包系统中目前所放位置/AppDir    输出位置/AppImage文件名.AppImage

这一个文件AppImage文件名.AppImage即可发布出给别人下载运行。

测试打包好的.AppImage文件

打包AppImage的一个原则是,在足够旧的Linux发行版上打包,这样打包出来的AppImage才尽可能兼容大部分人的机子。

一般人都选择用仍在支持周期内的最旧的一个Ubuntu LTS来打包(但不知是否为最佳选择)

appimagelint

appimagelint会连网查询当前最近几个版本的Ubuntu、Debian的glibc等库的版本,然后比较你的.AppImage文件所要求的最低版本,来显示兼容性。

1wget https://github.com/TheAssassin/appimagelint/releases/download/continuous/appimagelint-x86_64.AppImage

appimagelint不做完整的测试,所以,它显示兼容某发行版某版本的,不代表能成功跑起来。

通过容器在其他发行版测试

测试就用容器,没必要用虚拟机或实机(不过,虚拟机+live ISO,因为其带有DE,对新人可能更容易)。

用容器的话,虚拟的X server是少不了了(如果你打包的程序是GUI的)。

要批量测试的话,可以用Github Action、Gitlab CI、Travis CI等。

Gitlab CI和Travis可以直接指定docker image,Github Action可以在Ubuntu的Runner下再使用docker image。用这种CI的话,简单的就只是测试一下运行后有没有正常的界面出现,截个图上传artifacts。

容器测试方法相关的具体内容,在另一篇中写

本博客文章皆属原创(除特别标明外)。 未联系作者获得同意前,不可转载。
All articles are original (except for those specially claimed) and copyrighted. Copying without permission is forbidden.

打赏作者

写作不易,感谢支持! 扫个码吧~