Ubuntu下QT程序打包(直接拷贝动态库和可执行文件)

系统为Ubuntu16.04LTS,QT版本为5.12.9
QT默认为动态编译,生成的可执行文件需要有依赖库才能运行,因此在打包的时候需要把程序的依赖库一块打包,这样子做会导致打包的程序非常大,因为依赖库也都一块拷贝了,这种方法好处是快捷,不需要额外的工具。

查看程序依赖库

使用ldd命令查看程序依赖库
在这里插入图片描述

拷贝依赖库

在看其它博客的时候,其它人用的是这样一个脚本

#!/bin/sh
exe="ServerDecode"
des="./ServerDecodeLib"
deplist=$(ldd $exe | awk  '{if (match($3,"/")){ printf("%s "),$3 } }')  
echo $deplist
#cp $deplist $des

这个脚本,只能拷贝到依赖第一层的库,例如程序依赖库A,然后库A又连接到了B上或是依赖B,用这个脚本就只能拷贝到库A,那么当程序移植到另外一台机子上,如果另外一台机子上没有库B,或是库B的位置与A连接的位置不同,就会找不到库,程序无法运行。
这里用的是一个笨方法,将用ldd获得的依赖拷贝下来,就像这样

/usr/lib/libCypher4SLP.so.1
/opt/Qt5.12.9/5.12.9/gcc_64/lib/libQt5Charts.so.5
/opt/Qt5.12.9/5.12.9/gcc_64/lib/libQt5Widgets.so.5
/opt/Qt5.12.9/5.12.9/gcc_64/lib/libQt5Gui.so.5
/opt/Qt5.12.9/5.12.9/gcc_64/lib/libQt5Network.so.5
/opt/Qt5.12.9/5.12.9/gcc_64/lib/libQt5Core.so.5
/usr/lib/x86_64-linux-gnu/libstdc++.so.6
/lib/x86_64-linux-gnu/libgcc_s.so.1
/lib/x86_64-linux-gnu/libpthread.so.0
/usr/lib/x86_64-linux-gnu/mesa/libGL.so.1
/lib/x86_64-linux-gnu/libm.so.6
/lib/x86_64-linux-gnu/libz.so.1
/lib/x86_64-linux-gnu/libdl.so.2
/opt/Qt5.12.9/5.12.9/gcc_64/lib/libicui18n.so.56
/opt/Qt5.12.9/5.12.9/gcc_64/lib/libicuuc.so.56
/opt/Qt5.12.9/5.12.9/gcc_64/lib/libicudata.so.56
/usr/lib/x86_64-linux-gnu/libgthread-2.0.so.0
/lib/x86_64-linux-gnu/libglib-2.0.so.0
/lib64/ld-linux-x86-64.so.2
/lib/x86_64-linux-gnu/libexpat.so.1
/usr/lib/x86_64-linux-gnu/libxcb-dri3.so.0
/usr/lib/x86_64-linux-gnu/libxcb-present.so.0
/usr/lib/x86_64-linux-gnu/libxcb-sync.so.1
/usr/lib/x86_64-linux-gnu/libxshmfence.so.1
/usr/lib/x86_64-linux-gnu/libglapi.so.0
/usr/lib/x86_64-linux-gnu/libXext.so.6
/usr/lib/x86_64-linux-gnu/libXdamage.so.1
/usr/lib/x86_64-linux-gnu/libXfixes.so.3
/usr/lib/x86_64-linux-gnu/libX11-xcb.so.1
/usr/lib/x86_64-linux-gnu/libX11.so.6
/usr/lib/x86_64-linux-gnu/libxcb-glx.so.0
/usr/lib/x86_64-linux-gnu/libxcb-dri2.so.0
/usr/lib/x86_64-linux-gnu/libxcb.so.1
/usr/lib/x86_64-linux-gnu/libXxf86vm.so.1
/usr/lib/x86_64-linux-gnu/libdrm.so.2
/lib/x86_64-linux-gnu/libpcre.so.3
/usr/lib/x86_64-linux-gnu/libXau.so.6
/usr/lib/x86_64-linux-gnu/libXdmcp.so.6

然后使用cp将所有动态库拷贝到库文件夹里,由于多层嵌套的依赖库,它们的名字一般只有后缀会不同,就像这样
在这里插入图片描述
因此只需要在依赖库名后面加上通配符*,就可以将所有的依赖库都拷贝过来了,拷贝的时候需要加上-d保留软连接,写一个脚本来一键完成拷贝

#!/bin/sh
cp /usr/lib/libCypher4SLP.so.1*	 ./  -rdf
cp /opt/Qt5.12.9/5.12.9/gcc_64/lib/libQt5Charts.so.5*	./  -rdf
cp /opt/Qt5.12.9/5.12.9/gcc_64/lib/libQt5Widgets.so.5* 	./  -rdf
cp /opt/Qt5.12.9/5.12.9/gcc_64/lib/libQt5Gui.so.5* 	./  -rdf
cp /opt/Qt5.12.9/5.12.9/gcc_64/lib/libQt5Network.so.5* 	./  -rdf
cp /opt/Qt5.12.9/5.12.9/gcc_64/lib/libQt5Core.so.5* 	./  -rdf
cp /usr/lib/x86_64-linux-gnu/libstdc++.so.6* 	./  -rdf
cp /lib/x86_64-linux-gnu/libgcc_s.so.1* 				./  -rdf
cp /lib/x86_64-linux-gnu/libpthread.so.0*               ./  -rdf
cp /usr/lib/x86_64-linux-gnu/mesa/libGL.so.1*           ./  -rdf
cp /lib/x86_64-linux-gnu/libm.so.6*                     ./  -rdf
cp /lib/x86_64-linux-gnu/libz.so.1*                     ./  -rdf
cp /lib/x86_64-linux-gnu/libdl.so.2                     ./  -rdf
cp /opt/Qt5.12.9/5.12.9/gcc_64/lib/libicui18n.so.56*    ./  -rdf
cp /opt/Qt5.12.9/5.12.9/gcc_64/lib/libicuuc.so.56*      ./  -rdf
cp /opt/Qt5.12.9/5.12.9/gcc_64/lib/libicudata.so.56*    ./  -rdf
cp /usr/lib/x86_64-linux-gnu/libgthread-2.0.so.0*       ./  -rdf
cp /lib/x86_64-linux-gnu/libglib-2.0.so.0*              ./  -rdf
cp /lib64/ld-linux-x86-64.so.2*                         ./  -rdf
cp /lib/x86_64-linux-gnu/libexpat.so.1*                 ./  -rdf
cp /usr/lib/x86_64-linux-gnu/libxcb-dri3.so.0*          ./  -rdf
cp /usr/lib/x86_64-linux-gnu/libxcb-present.so.0*       ./  -rdf
cp /usr/lib/x86_64-linux-gnu/libxcb-sync.so.1*          ./  -rdf
cp /usr/lib/x86_64-linux-gnu/libxshmfence.so.1*         ./  -rdf
cp /usr/lib/x86_64-linux-gnu/libglapi.so.0*             ./  -rdf
cp /usr/lib/x86_64-linux-gnu/libXext.so.6*              ./  -rdf
cp /usr/lib/x86_64-linux-gnu/libXdamage.so.1*           ./  -rdf
cp /usr/lib/x86_64-linux-gnu/libXfixes.so.3*            ./  -rdf
cp /usr/lib/x86_64-linux-gnu/libX11-xcb.so.1*           ./  -rdf
cp /usr/lib/x86_64-linux-gnu/libX11.so.6*               ./  -rdf
cp /usr/lib/x86_64-linux-gnu/libxcb-glx.so.0*           ./  -rdf
cp /usr/lib/x86_64-linux-gnu/libxcb-dri2.so.0*          ./  -rdf
cp /usr/lib/x86_64-linux-gnu/libxcb.so.1*               ./  -rdf
cp /usr/lib/x86_64-linux-gnu/libXxf86vm.so.1*           ./  -rdf
cp /usr/lib/x86_64-linux-gnu/libdrm.so.2*               ./  -rdf
cp /lib/x86_64-linux-gnu/libpcre.so.3*                  ./  -rdf
cp /usr/lib/x86_64-linux-gnu/libXau.so.6*               ./  -rdf
cp /usr/lib/x86_64-linux-gnu/libXdmcp.so.6*             ./  -rdf

执行脚本后用ll查看动态库,会看到有一部分动态库的软连接是红色的,这说明这个动态库没有被拷贝过来,这是因为按上面的方式,直接用统配符来统一拷贝依赖库,有时候会因为依赖库的命名并不相同,例如下图的情况
在这里插入图片描述libpthread.so.0连接到libpthread-2.23.so,直接使用通配符是找不到libpthread-2.23.so的,因此需要修改脚本将它们一块拷贝过来
修改后脚本

#!/bin/sh
cp /usr/lib/libCypher4SLP.so.1*	 ./  -rdf
cp /opt/Qt5.12.9/5.12.9/gcc_64/lib/libQt5Charts.so.5*	./  -rdf
cp /opt/Qt5.12.9/5.12.9/gcc_64/lib/libQt5Widgets.so.5* 	./  -rdf
cp /opt/Qt5.12.9/5.12.9/gcc_64/lib/libQt5Gui.so.5* 	./  -rdf
cp /opt/Qt5.12.9/5.12.9/gcc_64/lib/libQt5Network.so.5* 	./  -rdf
cp /opt/Qt5.12.9/5.12.9/gcc_64/lib/libQt5Core.so.5* 	./  -rdf
cp /usr/lib/x86_64-linux-gnu/libstdc++.so.6* 	./  -rdf
cp /lib/x86_64-linux-gnu/libgcc_s.so.1* 				./  -rdf
cp /lib/x86_64-linux-gnu/libpthread.so.0 /lib/x86_64-linux-gnu/libpthread-2.23.so               ./  -rdf
cp /usr/lib/x86_64-linux-gnu/mesa/libGL.so.1*           ./  -rdf
cp /lib/x86_64-linux-gnu/libm.so.6        /lib/x86_64-linux-gnu/libm-2.23.so               ./  -rdf
cp /lib/x86_64-linux-gnu/libz.so.1*                     ./  -rdf
cp /lib/x86_64-linux-gnu/libdl.so.2   /lib/x86_64-linux-gnu/libdl-2.23.so                  ./  -rdf
cp /opt/Qt5.12.9/5.12.9/gcc_64/lib/libicui18n.so.56*    ./  -rdf
cp /opt/Qt5.12.9/5.12.9/gcc_64/lib/libicuuc.so.56*      ./  -rdf
cp /opt/Qt5.12.9/5.12.9/gcc_64/lib/libicudata.so.56*    ./  -rdf
cp /usr/lib/x86_64-linux-gnu/libgthread-2.0.so.0*       ./  -rdf
cp /lib/x86_64-linux-gnu/libglib-2.0.so.0*              ./  -rdf
cp /lib64/ld-linux-x86-64.so.2  /lib/x86_64-linux-gnu/ld-2.23.so                        ./  -rdf
cp /lib/x86_64-linux-gnu/libexpat.so.1*                 ./  -rdf
cp /usr/lib/x86_64-linux-gnu/libxcb-dri3.so.0*          ./  -rdf
cp /usr/lib/x86_64-linux-gnu/libxcb-present.so.0*       ./  -rdf
cp /usr/lib/x86_64-linux-gnu/libxcb-sync.so.1*          ./  -rdf
cp /usr/lib/x86_64-linux-gnu/libxshmfence.so.1*         ./  -rdf
cp /usr/lib/x86_64-linux-gnu/libglapi.so.0*             ./  -rdf
cp /usr/lib/x86_64-linux-gnu/libXext.so.6*              ./  -rdf
cp /usr/lib/x86_64-linux-gnu/libXdamage.so.1*           ./  -rdf
cp /usr/lib/x86_64-linux-gnu/libXfixes.so.3*            ./  -rdf
cp /usr/lib/x86_64-linux-gnu/libX11-xcb.so.1*           ./  -rdf
cp /usr/lib/x86_64-linux-gnu/libX11.so.6*               ./  -rdf
cp /usr/lib/x86_64-linux-gnu/libxcb-glx.so.0*           ./  -rdf
cp /usr/lib/x86_64-linux-gnu/libxcb-dri2.so.0*          ./  -rdf
cp /usr/lib/x86_64-linux-gnu/libxcb.so.1*               ./  -rdf
cp /usr/lib/x86_64-linux-gnu/libXxf86vm.so.1*           ./  -rdf
cp /usr/lib/x86_64-linux-gnu/libdrm.so.2*               ./  -rdf
cp /lib/x86_64-linux-gnu/libpcre.so.3*                  ./  -rdf
cp /usr/lib/x86_64-linux-gnu/libXau.so.6*               ./  -rdf
cp /usr/lib/x86_64-linux-gnu/libXdmcp.so.6*             ./  -rdf

尝试移植、出现的报错及解决方法

拷贝完成后用zip指令将可执行文件、动态连接库压缩在一起,zip压缩默认会破坏掉软连接,因此需要加上-y保留软连接,压缩后在包里查看是看不到软连接的,解压后软连接会再次出现
在这里插入图片描述
将包放到另外一台电脑上,这个时候大概率是无法运行的,会出现一系列的报错

error while loading shared libraries: libQt5Widgets.so.5: cannot open shared object file: No such file or directory

出现这样的报错,有两种情况:这个库没拷贝、拷贝了但是程序任然没有找到这个库。如果没有这个拷贝到库,那就按上文的方法进行拷贝;如果库存在但是程序没有找到库,这种情况,就需要添加环境变量LD_LIBRARY_PATH,添加动态库的查找地址export LD_LIBRARY_PATH=./lib
再打开,一般来讲就能够找到库了。或者是用下面这段脚本来打开可执行文件

#!/bin/sh  
appname=`basename $0 | sed s,\.sh$,,`  
dirname=`dirname $0`  
tmp="${dirname#?}"  
if [ "${dirname%$tmp}" != "/" ]; then  
dirname=$PWD/$dirname  
fi  
LD_LIBRARY_PATH=$dirname  
export LD_LIBRARY_PATH=./lib  
$dirname/$appname "$@"

其实这段脚本最关键的也就是这句话,export LD_LIBRARY_PATH=./lib,设置环境变量LD_LIBRARY_PATH,添加动态连接库地址,确保程序能够找到我们拷贝的库

使用ldd命令可以查看到程序依赖库的状况,如果是not found,或是出现一系列错误,例如:

./platforms/libqxcb.so: /usr/lib/x86_64-linux-gnu/libQt5XcbQpa.so.5: version `Qt_5_PRIVATE_API’ not found (required by ./platforms/libqxcb.so)

这样的错误,大概率也是依赖库不存在或是拷错了,需要重新拷贝一下

This application failed to start because it could not find or load the Qt platform plugin “xcb”.

Reinstalling the application may fix this problem.

Aborted

这个错误的原因是qt5的新特性导致的,最终的解决办法在工程目录创建platforms目录,然后把安装qt5的目录的lib所在目录的同一级目录的plugins/platforms里面的libqxcb.so拷贝到刚才新建的platforms目录,但是拷贝后,也可能会出现后续的问题

qt.qpa.plugin: Could not load the Qt platform plugin “xcb” in “” even though it was found.

This application failed to start because no Qt platform plugin could be initialized. Reinstalling the application may fix this problem.

Available platform plugins are: xcb.

Aborted (core dumped)

这个问题,其实也是依赖库出问题导致的,ldd查看platforms/libqxcb.so,缺少什么依赖库就把什么拷贝过来

总结

最终程序包内容如下
在这里插入图片描述

移植的过程中,出现了很多奇怪的问题,在网络上的各种解决方法,有时候能解决问题,有时候解决不了,可能解决了,但是新的问题又冒出来了。但是这些问题,本质上都是程序的依赖库出了问题,用ldd查看是哪个依赖库出现问题,将库都拷贝过去就能解决了
需要注意,此方法仅适用与ubuntu至ubuntu的QT程序移植,如果要把ubuntu下的qt程序拷贝到centos下,这个方法是不行的,两个系统的库不兼容

  • 16
    点赞
  • 56
    收藏
    觉得还不错? 一键收藏
  • 6
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值