1.发现的问题:
今天发现,linux的编译好的qt程序发布移植,相比windows下的发布移植,多了一些步骤
window下直接用qt携带的windeployqt打包工具,在你要打包的应用程序目录下用命令执行:windeployqt+你要发布的应用程序名,如windployqt game.exe
但是linux下的发布,就没有那么简单了,至少我的是这样子的。 因为linux下的qt没有自带的打包工具。你也可以去下载,有大神写好了,去下安装就行了。不过安装好之后,后续的步骤也蛮麻烦的,我就不用这种方法了。
我直接用linux下的命令打包吧。接下来进入正题:
2.怎么办?linux下的打包发布步骤如下:
先说一下我开发所在的电脑:我现在编译应用程序的环境是:ubantu18.04版本的,开发环境:Qt5.12.0 编译环境:gcc_64
要移植的电脑:ubantu16.04版本 没有开发环境
第一步:打包依赖库
我的编译好的发布目录下没有其他库,只有一个可执行的应用程序,可以执行,因为我有qt的开发环境,他会自动寻找链接所要的库,但是没有qt环境的电脑就不能运行。所以我们要把它运行时所依赖的库全部给他弄到发布包上去,看下一步
在发布目录下 新建一个脚本
内容如下:
#!/usr/bin/sh
exe="UpdateClient" #程序名称
des="/home/yicaibao/Qt5.12.0/qtProject/UpdateClient/bin/fabu-release" #打包文件夹位置
deplist=$(ldd $exe | awk '{if (match($3,"/")){ printf("%s "),$3 } }')
cp $deplist $des
第四行那个,拷贝的命令,解释一下什么意思
ldd $exe | awk '{if (match($3,"/")){ printf("%s "),$3 } }'
这个命令:ldd $exe 就是获取程序所依赖的库,然后通过管道|输入给awk命令处理,获取字符串中匹配有/的字符串,然后通过空格隔开,获取第三列,也就是程序所依赖库的路径
然后将所有的库全部拷贝过去,其实很多库都不需要用到,有的/lib/...开头的路径的库是不需要的,这个是linux系统自带的,全部拷过去,会拷个雷库(如libc.so.6)过去,移植到不同版本的相同linux系统上(如从ubantu16.04移植到ubantu20.04系统),或者移植到其他linux系统上(如从ubantu移植到deepin系统)时,容易导致莫名其妙的问题,需要拷贝的只有Qt目录下的库文件而已, 这个拷贝命令就行优化,这里就不讲了,最后的链接里会有讲到
注意一下:改一下程序名称和你要打包的文件位置,根据你的来
然后在脚本文件所在的文件目录下,命令行执行脚本:sh pack.sh
进入打包的文件夹下,会发现有很多库,这些就是要依赖的库,那这样就完了吗?还不行,还有一些库需要拿进来。
第一个库:进入在qt安装位置下编译环境的plugins目录下
然后把plugins目录下的platforms目录复制到要打包的目录下
执行命令:cp -r platforms/ /home/yicaibao/Qt5.12.0/qtProject/UpdateClient/bin/fabu-release
这是一个目录,不要把目录里面的文件拿出来,放进刚刚打包好的库一起,是不行的
还有两个库:libQt5XcbQpa.so.5.12.0和libQt5DBus.so.5.12.0
在qt安装编译环境目录的lib目录下
把这两个库复制到打包发布目录下
将可执行程序也复制到该目录下
大功告成!
将其打包好,接下来就可以移植到其他电脑上了
第二步:移植到其它电脑,并做好配置
将压缩包拷贝到,要移植的电脑上,解压
我们进入解压目录,直接运行,在命令行运行,发现报错,提示找不到依赖库
可是认真看一下,我们不是打包过来了吗?这些缺少的库,为什么还报错呢?
因为在程序运行时,它默认寻找的库是在系统lib目录下,并不在发布的文件夹下,报错信息中就可以知道
怎么办呢?
我们改一下库依赖路径就行了
在命令行写输入:
export LD_LIBRARY_PATH='你的库路径':$LD_LIBRARY_PATH
export LD_LIBRARY_PATH='/home/valwell/tmp/fabu-release':$LD_LIBRARY_PATH
再次运行,还是报错了
报错信息不是很明确,但是根据提示肯定是少插件了,具体不知道是什么
在命令下执行:export QT_DEBUG_PLUGINS=1
这个命令可以帮我们输出程序运行时,加载插件时的调试信息
执行命令后,再次执行,发现提示,少了libQt5XcbQpa.so.5的库,但是我们把Qt那边的库打包了libQt5XcbQpa.so.5.12.0的库,但是他要的是.so.5后缀的库,怎么办呢?
我们软链接过来就行了,命令行执行:ln -s libQt5XcbQpa.so.5.12.0 libQt5XcbQpa.so.5
再次执行程序,发现这次libQt5DBus.so.5的库找不到,但是qt打包时我们有拿过来了,只是名字不同,我们进行软链接即可,执行命令:ln -s libQt5DBus.so.5.12.0 libQt5DBus.so.5
然后再次执行,发现可以运行啦
上述的命令汇总为如下脚本命令
#!/usr/bin/sh
export QT_DEBUG_PLUGINS=1
export LD_LIBRARY_PATH='/home/valwell/tmp/fabu-release':$LD_LIBRARY_PATH
ln -s libQt5XcbQpa.so.5.12.0 libQt5XcbQpa.so.5
ln -s libQt5DBus.so.5.12.0 libQt5DBus.so.5
./UpdateClient
因为使用export导入的是临时的,所以只是局限于当前命令窗口,关闭后就失效了,写上述的脚本后,下次直接运行脚本就行了。你们在调试运行时,可能少的不止libQt5XcbQpa.so.5和libQt5XcbQpa.so.5这两个库,这时就需要根据这个思路进行寻找问题的根源了。少啥补啥就行了。一般少的东西,在开发环境的机子上肯定有!!!
总结:
为什么写那么多呢?其实这是个思路过程吧,linux下很多时候库是链接不上的,这时候就需要我们思考了,在发布移植时,因为可能另一台电脑没有开发环境,就需要我们的配置了。就像一个开发团队,接了一个外包,他们已经分工开发好了,在他们的电脑运行流程。但是,给客户时,因为客户是没有开发环境的,总不能给客户安装个开发环境吧?这是不现实的,所以需要在交付给客户前,要在另一台没有开发环境的机器或者虚拟机上调试,直到运行没有问题。
好了,下班下班!!
2022-2-24 更新补充:嫌弃上面的打包太麻烦了,还可能出现很多雷区,来看这个我最新写的文章,还能避免各种雷,脚本一键式打包
关于Qt程序打包后运行库依赖的常见问题分析及解决方法_只是个~小不点的博客-CSDN博客
原文链接:https://blog.csdn.net/qq_44667165/article/details/126971223