前言
最近研究ubuntu上的Qt打包遇到了很多问题,虽然有个LinuxDeployQt,但是这货有个很大的缺点,那就是它打包的程序在运行的时候会把自己释放到一个临时目录运行,这样就导致了我们的程序设置当前运行目录有误,导致相对路径之类的东西全部扑街。所以我们需要一个新的办法。在调查了一段时间后,最终找到解决方案,并学会了deb安装包的制作
环境
系统:ubuntu 16.04
Qt程序:TestQt
Qt版本:5.12.4
分析
要实现我们最终的目的,需要解决下面几个问题:
- 让Qt程序运行时加载自己指定目录下的动态库,而不是系统默认的,避免和系统已有的Qt库发生冲突
- 自动提取所需要的依赖包到我们指定的目录,这个可以借助ldd
- Qt程序指定
plugins
加载路径,这个需要用到qt.conf
配置文件 - 如果制作deb包,这个设计到deb工程的目录结构和dpkg打包指令,还涉及到 linux的 desktop 文件格式(类似windows快捷方式)
方案
问题 1
我们需要指定一个LFLAGS的参数,这里是指定程序所在目录下的lib目录
-Wl,-rpath,'$$ORIGIN/lib'
这个参数就可以指定程序运行时候的优先加载路径,如果用的是QtCreator,那么我们修改pro工程文件
QMAKE_LFLAGS += -Wl,-rpath,\'\$$ORIGIN/lib\'
注意:这里一定要用 \
转义,不然 QMAKE_LFLAGS
设置无效,另外两边的单引号是必须的,双$也是必须的
问题 2
这个只需要使用ldd来查找依赖,并自动拷贝到我们app下的lib目录即可,在程序目录建了一个脚本 copylib.sh
内容如下:
#!/bin/bash
LibDir=$PWD"/lib"
Target=$1
lib_array=($(ldd $Target | grep -o "/.*" | grep -o "/.*/[^[:space:]]*"))
$(mkdir $LibDir)
for Variable in ${lib_array[@]}
do
cp "$Variable" $LibDir
done
假设我们的Qt程序为 TestQt
,这样我们使用 copylib.sh ./TestQt
就直接拷贝依赖到 lib目录下了
注意:如果是打包Qt,那么要注意xcb的问题,我们需要额外拷贝两个Qt库进来,libQt5XcbQpa
和 libQt5DBus
这两个都属于 plugins/platforms
里面 libqxcb.so
所依赖的库。另外我们需要拷贝plugins目录下的 bearer
,platforms
,imageformats
。还要注意一点,那就是Qt库要带着符号链接一起拷贝过去,不然依旧会报错
问题 3
这个就是使用qt.conf文件了,内容如下:
[Paths]
Prefix=./
Libraries=lib
Plugins=plugins
问题 4
目录说明
首先我们需要建立一个目录结构,这里拿TestQt的举例,不含文件
TestQt-Package/
└── project
├── DEBIAN
└── usr
├── local
│ └── TestQt
| ├── lib
│ ├── plugins
│ │ ├── bearer
│ │ ├── imageformats
│ │ ├── platforms
└── share
├── applications
└── icons
└── hicolor
└── 64x64
└── apps
这里的project就是我们要打包成 deb 包的工程文件夹,内容主要是 usr
和 DEBIAN
两个文件夹,usr目录结构和系统保持一致。然后我们简单说明一下
DEBIAN:这个文件夹是 deb 配置信息文件夹
applications:这里是放置程序的快捷方式的,用来在 ubuntu 程序菜单中显示你的程序
icon:这里放置你的程序图标,png格式,这里是64x64的分辨率,请根据自身图标大小挑选对应分辨率文件夹放置
我们的程序位于 /usr/local/TestQt 下面,当然,你也可以放到其他地方,参考上面的目录结构即可
文件说明
首先我们了解一下 linux的快捷方式文件,linux的快捷方式 是 desktop 格式,类似windows的 lnk,示例文件(TestQt.desktop)如下
[Desktop Entry]
Categories=Utility;
Comment=a test
Exec=/usr/local/TestQt/TestQt
GenericName=TestQT project
Icon=TestQt.png
Name=TestQt
Name[zh_CN]=TestQt测试程序
Type=Application
Version=1.0.0
这里做个简单的说明
Exec:这个字段是执行路径,如果你的程序直接放到/usr/bin之类的地方,那么你可以直接写 TestQt,而不需要完整路径
Icon:这个是图标路径,默认会从 /usr/share/icons下面去找,如果你按照上面目录结构放入了 TestQt.png ,那么就可以直接写图标名字。如果没有,比如你放到了程序目录,那么就需要写上完整路径
Name:这个可以加上locale来支持多语言
接着我们熟悉一下 DEBIAN
目录下的配置文件 ,配置文件固定名字为 control , 内容如下
package: TestQt
version: 1.0.0
architecture: amd64
maintainer: magicdmer
description: a test project
都放好后,我们就在 TestQt-Package 目录下运行下面的命令打包
dpkg -b project/ TestQt_ubuntu_amd64.deb
终于完毕