linux下qt程序的打包发布超详细
功能:
- 在linux下对开发的Qt应用,进行拷贝依赖文件so等,并打成deb安装包;
- 实现可安装、卸载,安装完毕自动在开始菜单下和桌面添加快捷方式;
- 卸载后自动删除快捷方式,以及删除应用生成的log文件。
测试环境:ubuntu18.04 Qt 5.14.2
一、使用linuxdeployqt拷贝依赖文件
win系统里面有个qt自带的依赖拷贝的工具windeployqt,linux系统下也有个类似的工具——linuxdeployqt,是一样的功能
-
下载linuxdeployqt依赖拷贝工具
下载地址:
https://github.com/probonopd/linuxdeployqt/releases
如果该网址进不去,也可使用如下网址
linux打包工具 -
安装linuxdeployqt
为了方便使用,这里进行重命名一下(可以改成自己想要的名字)
mv linuxdeployqt-continuous-x86_64.AppImage linuxdeployqt
修改下载的文件的可执行权限
sudo chmod 777 linuxdeployqt
然后把这个可执行文件移动到
/usr/local/bin
目录里面,这样就可以在其他目录进行访问了sudo mv linuxdeployqt /usr/local/bin
测试是否安装成功
linuxdeployqt --version
输出版本信息则表示安装成功
-
Qt库路径设置到环境变量
工具会根据生成的可执行文件,自动搜索依赖,所以我们需要确保Qt库的相关路径设置到环境变量中,这样工具在搜索时才能找到,并拷贝它们。
另外拷贝文件,对环境变量的使用,不想要重启系统那么麻烦,所以我们修改
.bashrc
文件,仅对当前用户永久有效。vim ~/.bashrc
在
.bashrc
文件末尾,将Qt里面的相关环境路径添加进去(每个人的qt版本和路径不一样,具体路径需要自己进行查看):#add qt env export PATH=/opt/Qt5.14.2/5.14.2/gcc_64/bin:$PATH export LIB_PATH=/opt/Qt5.14.2/5.14.2/gcc_64/lib:$LIB_PATH export PLUGIN_PATH=/opt/Qt5.14.2/5.14.2/gcc_64/plugins:$PLUGIN_PATH export QML2_PATH=/opt/Qt5.14.2/5.14.2/gcc_64/qml:$QML2_PATH
其中,
/opt/5.14.2/gcc_64/
是本次测试环境Qt安装目录,大家根据自己的情况替换。然后,使用
source
命令让文件立即生效source ~/.bashrc
然后,测试环境变量是否设置正确。如下:
qmake -v
看到qmake的版本号,则表示设置成功。
提示:
根据linuxdeployqt在线帮助文档介绍,其实上述最重要的环境变量就是PATH这条,其他的并没有说,或许其他不要也没啥问题。
-
拷贝依赖文件
拷贝前,确认生成的是
Release
版本的程序,这个是常识。我们在根目录下建立
AppSetup
目录,用于放置打包相关的文件;并在
AppSetup
下继续建个App
目录,用来装App
应用及拷贝文件。mkdir AppSetup cd AppSetup mkdir App
把我们的应用App和调用到的外部库(如果没有调用就不用管)一起拷贝到Test目录下
使用命令执行依赖拷贝
linuxdeployqt App -appimage
报错如下:
不用管他,是关于桌面文件的,后面可以直接编辑拷贝完毕后,依赖都在/AppSetup/App/目录下
我们可以看到创建了很多目录。需要说明的是,在执行
linuxdeployqt App -appimage
命令时,其实除了拷贝依赖文件外,还对目标文件App
进行了修改,在App
中插入了一些库路径信息。经过本人对前后2个文件内容的对比测试,至少是添加了lib目录的,其他没试过。
所以,你只需要把程序依赖的
so
文件放入lib
目录下,无论是显式、隐式加载的so
,都是可以搜索到的。若你的应用中还有其他,如配置文件等资源,那么手动拷贝到你自己代码指定的目录下。
重要提示:
- 因为
linuxdeployqt
将在内部使用ldd
命令,来确定从何处将库复制到包中。ldd
命令本身只能查找隐式加载的so
,故若程序中代码使用显式加载的so,它是找不到的,这时需要开发者自己去保证显式加载so
的路径可被搜索。 - 举个例子:若存在程序A显式加载
B.so
,B.so
隐式加载C.so
,则对程序A
使用linuxdeployqt
拷贝依赖时,程序A的间接依赖文件C.so
,将不会被拷贝。当程序跑起来加载B.so
时,就会报找不到C.so
的错误。这一点尤其需要注意。此时我们需要再对B.so
使用一次linuxdeployqt
拷贝依赖。这样程序A
加载B.so
,B.so
加载C.so
,就都可以找到了。
- 因为
-
配置共享库搜索路径(可选)
如果你的应用中,调用了其他的库,又想要放在某个指定目录下,那么可以在应用同目录下,添加
qt.conf
文件,指定库搜索路径。这块知识,就自行百度吧,反正最终目的,能正常启动应用就行。 -
测试应用能否正常运行
此时,一个完整的运行环境已经具备了,我们测试一下。
重新开一个终端,在该终端的环境变量中去掉
Qt
库相关的路径,修改后的环境变量只对该终端生效,然后我们执行应用,看能否运行。操作过程:先用
export
查看有哪些环境变量设置了Qt
路径。export
如果本教程之前没有配置过
qt
环境变量,那么结果应该和.bashrc
文件我们追加的内容一致的。然后把这些环境变量中
Qt
路径去掉:export PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin export LIB_PATH= export PLUGIN_PATH= export QML2_PATH=
测试启动应用
./App
此时如果不出意外,应该可以正常启动。
如果有意外,那就根据实际情况,先把问题解决,再继续。
二、打包成deb包
-
deb包安装路径原理简述
下面举个例子进行说明,我们先来看打包目录与安装后目录结构对比。
打包目录,
DEBIAN
下面为deb
包控制文件,应用与依赖文件位于source/opt/App/
,如下:source ├── DEBIAN │ └── control │ └── postinst │ └── postrm ├── opt └── App ├── App └── xxx
若按照此打包目录生成
deb
,安装后,其目录如下:/ ├── opt └── App ├── App └── xxx
小结:
DEBIAN目录下主要存放一些控制文件和脚本,具体后面使用到时,再细说。
DEBIAN目录固定放置于打包目录顶层。
deb包安装时,默认将内部文件,释放至根目录下(/),故我们需要在打包时,将安装目录层次创建好,以达到想要的安装路径效果。 -
规划安装路径
我们希望将App
应用安装到/opt/App/
下,下面开始创建目录层次。在
/AppSetup/
下创建output
目录,用于存放生成的deb
包;创建
source
目录,用于存放打包文件,如下:
在source
目录下,创建DEBIAN
目录、创建安装路径层次opt
目录以及opt/App
目录,如下:
然后将前面我们拷贝的依赖文件,全部移动到/AppSetup/source/opt/App/
目录下,如下: -
配置*.desktop桌面快捷方式文件
还记得前面,拷贝依赖文件时报错吗,就是这个桌面文件。
直接把它扔到桌面文件夹(~/Desktop/
),它就可以变成一个带图标的快捷方式,类似win
。我们把位于
/AppSetup/source/opt/App/default.desktop
改为App.desktop
;
它有如下内容,需要编辑:[Desktop Entry] Version=1.0.0 #版本信息 Name=App #英文名,必选 Name[zh_CN]=测试案例 #中文名,可选 Exec=/opt/App/App #应用的可执行文件路径(绝对路径) Icon=/opt/App/App.png #应用的图标路径(绝对路径) Comment=This is my App #说明信息 Terminal=true #是否允许在终端启动 Type=Application #应用类别
我们按照上述内容进行编辑,其中图标,自己去找一个
.png
放到/TestSetup/source/opt/App/App.png
即可。注意:
Test.desktop文件需要有执行权限,该文件才能变成图标,否则只是显示一个普通文件。
Test.desktop中的路径需要填写deb包的安装路径,非打包路径。
Terminal=true时,启动程序时,会附带启动终端界面,即会出现2个界面。
Terminal=false时,启动程序时,没有终端界面,仅显示程序这一个界面。 -
创建deb包之control文件
control
文件主要描述软件包的名称(Package
),版本(Version
),Installed-Size
(大小),Maintainer
(打包人和联系方式)以及描述(Description
)等,是deb包必须具备的描述性文件,以便于软件的安装管理和索引。我们在
DEBIAN
目录下创建名为control
的文件,内容如下:Package: myApp Version: 1.0.0 Section: utils Priority: optional Architecture:arm64 Depends: Installed-Size: 1024 Maintainer: 127001@163.com Description: my App package
含义:
Package:包名。记住,后面卸载时候需要包名。
Version:应用版本。
Architecture:架构,我这里是arm64。
Maintainer:维护人员联系方式,看着办。
Description:软件包描述。
其他的,这里没用到,就不写了,自己百度吧。 -
创建deb包之postinst文件
负责安装完成时的配置工作,软件安装完后,执行该Shell
脚本,一般用来配置软件执行环境,必须以"#!/bin/sh
"为首行。我们在
DEBIAN
目录下创建名为postinst
的文件,内容如下:#!/bin/sh chmod 777 /opt/App/App.desktop cp /opt/App/App.desktop /usr/share/applications/ cp /opt/App/App.desktop ~/Desktop/
主要将
App.desktop
拷贝至2个目录,Desktop
目录下,自动生成桌面快捷方式。applications
目录下,生成开始菜单中,other
菜单下子项。最终效果,查看文章末尾处效果图。
-
创建deb包之postrm文件
软件卸载后,执行该
Shell
脚本,一般作为清理收尾工作,必须以"#!/bin/sh
"为首行。我们在
DEBIAN
目录下创建名为postrm
的文件,内容如下:#!/bin/sh rm /usr/share/applications/App.desktop rm ~/Desktop/App.desktop
主要工作就是删除
postinst
创建的2个文件。 -
使用dpkg命令构建deb包
对source目录下所有文件打包,在output目录下生成deb包。
cd /AppSetup/source dpkg -b . /AppSetup/output/test_amd64_0.1.0.deb
打包结果:
三、deb包的安装与卸载
-
安装
安装deb
包命令如下:cd /AppSetup/output sudo dpkg -i App_amd64_1.0.0.deb
安装完成,桌面效果:
开始菜单效果:
安装路径效果:
-
卸载
卸载时,使用control文件中的包名。sudo apt-get remove myapp
卸载之后,安装路径下文件全部删除,自动删除桌面快捷方式和菜单项。
若应用生成一些log文件,因不在打包文件中,故不会自动删除,
则需要在postrm文件中添加删除命令。
参考链接:
《Linux下通过.desktop文件创建桌面程序图标(快捷方式)及文件编写》
《Ubuntu下的deb打包、安装与卸载》