找回密码
 立即注册
首页 业界区 业界 Linux 通用软件包 AppImage 打包详解

Linux 通用软件包 AppImage 打包详解

戎玉珂 2025-11-25 20:00:04
近水楼台先得月,向阳花木易为春。
导航


  • 格式介绍 - AppImage
  • 手动打包 - appimagetool
  • 自动打包 - linuxdeploy
  • 杂七杂八
格式介绍 - AppImage

AppImage 是 Linux 系统中一种新型的软件包格式,它与 rpm、deb 这些软件包格式相比最大的不同便是:(1)无需安装,即用即删。(2)只需打包一次,便可到处运行。完美的解决了不同 Linux 发行版(Ubuntu/Debian/Fedora/CentOS)之间软件包不统一的问题。
它的工作原理便是将程序运行所需的文件全部打包在一个文件中,待程序运行时再将这些文件提取在 /tmp/.mount_xxxxxxx/ 目录中,然后执行 AppRun 脚本启动程序以进行资源的调用。以下便是一个 AppImage 文件内部包含的目录树结构:
  1. AppDir/
  2. ├── AppRun
  3. ├── 应用图标.png
  4. ├── 程序名.desktop
  5. ├── usr/
  6.      ├── bin/
  7.      ├── lib/
  8.      ├── share/
复制代码
它本质上就是一个 squashfs 文件系统 + runtime 执行器
特别注意:
(1)要实现跨平台运行,待打包的程序最好是在 CentOS 7 系统上进行编译 ,然后再进行打包。【注:编译 C/C++ 程序所使用的系统库 glibc 在 Linux 系统上几乎肯定存在,而该库有着良好的向后兼容性,因此使用旧版本的 glibc 库编译出来的程序几乎可以完美的运行在新版本的 glibc 系统上。而在 CentOS 7 上的 glibc 版本是 2.17,该版本较旧且兼容性较好,因此在其系统上编译出来的 C 程序通常也可以在大部分的 Linux 发行版系统中使用。】
(2)待打包程序依赖的 lib 文件中最好只包含其专属的库文件即可,不要包含类似 glibc 这样的系统库文件。【注:这是因为在 A 系统中的 glibc 文件通常并不可以在 B 系统中使用,因此为了避免 AppImage 程序运行错误,请勿这样去做。再者,glibc 在 Linux 系统中是肯定会存在的,因此也并不需要额外去包含这样的依赖文件。】
手动打包 - appimagetool

appimagetool 是由 AppImage 官方制作的打包工具,在使用它进行打包时,必须要先分析待打包程序的动态库依赖情况,然后再完成对 AppDir 目录的装填,最后才能使用 appimagetool 完成对程序的打包。由于分析程序的依赖情况是个很复杂的问题,因此该工具在使用上体验并不太好。
接下来,我将演示如何对一个简单的 C 程序完成打包过程:
(1)文件准备:hello.c。
  1. // 主文件 hello.c
  2. #include <stdio.h>
  3. int main() {
  4.     printf("Hello Appimage\n");
  5.     return 0;
  6. }
复制代码
(2)编译并打包
  1. #(1)编译及检验运行
  2. gcc -o hello hello.c
  3. ./hello
  4. #(2)制作 AppDir 目录树
  5. mkdir -p AppDir/usr/bin/
  6. cp ./hello AppDir/usr/bin/
  7. wget https://github.com/boolean-world/appimage-resources/blob/master/hello-world-appimage/hello-world-icon.png -O AppDir/hello.png        #任意图片文件即可
  8. nano AppDir/hello.desktop #文件内容见下方
  9. nano AppDir/AppRun #脚本内容见下方
  10. #(3)开始制作 AppImage 程序
  11. /root/appimagetool-x86_64.AppImage AppDir/
复制代码
附注:
hello.desktop 文件如下:
  1. [Desktop Entry]
  2. Name=hello
  3. Exec=hello
  4. Icon=hello
  5. Type=Application
  6. Categories=Utility;
  7. Terminal=true
复制代码
AppRun 脚本如下:
  1. #!/bin/sh
  2. APPDIR="$(dirname "$(readlink -f "$0")")"
  3. # 添加库目录
  4. if [ -d "$APPDIR/lib64" ]; then
  5.     export LD_LIBRARY_PATH="$APPDIR/lib64:$LD_LIBRARY_PATH"
  6. fi
  7. if [ -d "$APPDIR/usr/lib" ]; then
  8.     export LD_LIBRARY_PATH="$APPDIR/usr/lib:$LD_LIBRARY_PATH"
  9. fi
  10. # 启动主程序 //注意:不同应用主程序路径需要修改
  11. exec "$APPDIR/usr/bin/hello" "$@"
复制代码
AppDir 目录树结构如下:
  1. AppDir/
  2. ├── AppRun                //启动程序,可以是简单的脚本,也可以是 ELF,只要保证运行该脚本主程序能被启动即可。
  3. ├── hello.desktop        //注意 EXEC 的值,它对应的是/usr/bin/目录中的程序,而 Icon 对应的是当前目录
  4. ├── hello.png                //也支持 svg 格式
  5. └── usr
  6.     └── bin
  7.         └── hello
复制代码
自动打包 - linuxdeploy

linuxdeploy 是一个由第三方制作的 AppImage 打包工具,与 appimagetool 不同的是,它可以对待打包程序自动进行依赖分析,并自动将所需的依赖及资源文件按照 AppDir 的目录格式给装填完毕,用户只需将模版化的 desktop 文件和 icon 文件准备好即可,使用起来简直美滋滋。
【示例一】:接下来,我将演示如何对一个需要依赖的简单 C 程序完成打包过程:
(1)文件准备:mylib.h、mylib.c、main.c、Makefile。
  1. // 动态库头文件 mylib.h
  2. #ifndef MYLIB_H
  3. #define MYLIB_H
  4. int add(int a, int b);
  5. void hello();
  6. #endif
复制代码
  1. // 动态库源码 mylib.c
  2. #include <stdio.h>
  3. #include "mylib.h"
  4. int add(int a, int b) {
  5.     return a + b;
  6. }
  7. void hello() {
  8.     printf("Hello from my dynamic library!\n");
  9. }
复制代码
  1. // 主程序 main.c
  2. #include <stdio.h>
  3. #include "mylib.h"
  4. int main() {
  5.     hello();
  6.     int result = add(3, 5);
  7.     printf("3 + 5 = %d\n", result);
  8.     return 0;
  9. }
复制代码
  1. # Makefile 文件
  2. CC=gcc
  3. CFLAGS=-fPIC -Wall
  4. LDFLAGS=-shared
  5. TARGET_LIB=libmylib.so
  6. TARGET_MAIN=main
  7. all: $(TARGET_LIB) $(TARGET_MAIN)
  8. $(TARGET_LIB): mylib.o
  9.         $(CC) $(LDFLAGS) -o $(TARGET_LIB) mylib.o
  10. mylib.o: mylib.c mylib.h
  11.         $(CC) $(CFLAGS) -c mylib.c
  12. $(TARGET_MAIN): main.o $(TARGET_LIB)
  13.         $(CC) main.o -L. -lmylib -o $(TARGET_MAIN)
  14. main.o: main.c mylib.h
  15.         $(CC) -c main.c
  16. clean:
  17.         rm -f *.o $(TARGET_MAIN) $(TARGET_LIB)
复制代码
(2)编译并打包
  1. #(1)编译及检验运行
  2. cd myapp
  3. make
  4. mv libmylib.so /lib64/libmylib.so
  5. ./main
  6. #(2)制作的 main.desktop 文件内容
  7. cat main.desktop
  8. [Desktop Entry]
  9. Name=main
  10. Exec=main
  11. Icon=main
  12. Type=Application
  13. Categories=Utility;
  14. Terminal=true
  15. #(3)获取一个 Icon 文件
  16. wget https://github.com/boolean-world/appimage-resources/blob/master/hello-world-appimage/hello-world-icon.png -O main.png
  17. #(4)开始制作 AppImage 程序
  18. /root/linuxdeploy-x86_64.AppImage --appdir /root/myapp --output appimage --icon-file main.png --desktop-file main.desktop -e main
  19. ls -l main*.AppImage
复制代码
【示例二】:最后,我再演示如何对一个系统命令 find 完成打包过程:
  1. #(1)制作的 find.desktop 文件内容
  2. cat find.desktop
  3. [Desktop Entry]
  4. Name=find
  5. Exec=find
  6. Icon=find
  7. Type=Application
  8. Categories=Utility;
  9. Terminal=true
  10. #(2)获取一个 Icon 文件
  11. wget https://github.com/boolean-world/appimage-resources/blob/master/hello-world-appimage/hello-world-icon.png -O find.png
  12. #(3)开始制作 AppImage 程序
  13. cd $(dirname $(which find))
  14. /root/linuxdeploy-x86_64.AppImage --appdir /root/find --output appimage --icon-file find.png --desktop-file find.desktop -e find
  15. ls -l find*.AppImage
复制代码
注意:(1)建议将 icon 和 desktop 文件放置在 find 命令根目录下,这样在打包的时候能够避免很多问题。(2)由于 linuxdeploy 在打包环节调用的是 appimagetool,而 appimagetool 在打包的时候会在 github 上拉取 runtime 文件,因此在使用前建议设置全局代理以确保 github 可访问。
杂七杂八


  • AppImage 参考:官网、参考文档、软件分发
  • linuxdeploy 插件系统:awesome-linuxdeploy,插件 linuxdeploy-plugin-checkrt 在打包较复杂的 C 程序时可能会比较有用。
  • 理想的编译环境:CentOS 7 x64、CentOS 6 x32。【注意:64 位系统打包出的 AppImage 不可在 32 位系统使用。 】
  • pkg2appimage 工具支持将 deb 软件包转换给 AppImage 格式的软件包。【注:理论是美好的,但实际打包时失败率太高且太折腾,不推荐使用,还是老实用 linuxdeploy 吧。】
  • 已打包的 AppImage 软件包,可通过 ./app*.AppImage --appimage-extract 将其包含的文件重新提取出来,以供参考或重复打包。
(*)全局代理设置
  1. export http_proxy=http://192.168.56.1:7890
  2. export https_proxy=http://192.168.56.1:7890
  3. export no_proxy=192.168.56.1,localhost
  4. export HTTP_PROXY=http://192.168.56.1:7890
  5. export HTTPS_PROXY=http://192.168.56.1:7890
  6. export NO_PROXY=192.168.56.1,localhost
复制代码
来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!

相关推荐

您需要登录后才可以回帖 登录 | 立即注册