初探AppImage打包(Qt程序为例)
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会
- 查找AppDir下的二进制可执行文件及二进制动态库文件,并查出它们的依赖
- 再把需要的依赖(除内置的一黑名单外,为不需要打包的依赖)从Linux主机系统中复制进
AppDir/usr/lib
- 再把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.
打赏作者
写作不易,感谢支持! 扫个码吧~