Qt5.4文档翻译:针对Linux/X11 的Qt——部署,Qt for Linux/X11 - Deployment
这个文档说明的是 ,与 针对Linux/X11 的 Qt 相关的部署问题。我们将在部署Qt 的示例目录中提供的 即 插 即 画 程序的同时演示这个过程。
由于Unix 系统的变种繁多(商业Unices、Linux发行版,等等),在 Unix 上部署程序是一个复杂的事情。在我们开始之前,先告诉你,为某个Unix 变种系统编译的程序不一定能在另一个Unix 系统上运行。例如,除非你使用交叉编译器,否则你无法在 Irix 上编译你的程序再将它发布到AIX 上。
静态链接通常是在 Unix 上发布程序的最安全、最简单的方法,因为它让你免去了这些工作:发布Qt 库,并确保它们位于目标系统上查找库的默认路径中。
要使用这种方法,你必须先安装Qt 库的静态版本:
cd /到/Qt/的路径
./configure -static -prefix /到/Qt/的路径 <其它参数>
make sub-src
我们指定了前缀 ,这样我们就不会覆盖掉已安装的Qt 了。上面的例子仅仅构建Qt 库 ,也就是说 ,示例 以及 Qt Designer 都不会被构建。当 make 完成之后 ,你将在 /到/Qt/的路径/lib 目录中找到Qt 库。
当你将程序与Qt 库静态链接时 ,注意 ,你可能需要向你的项目文件中的 LIBS 行中添加更多的库 。要了解更多信息,就去看 程序依赖 小节 。
当Qt 的静态构建完成时,下一步就是重新生成makefile、重新构建程序。首先,我们必须进入包含了这个程序的目录:
cd /到/Qt/的路径/examples/tools/plugandpaint
现在运行qmake 为程序创建一个新的makefile,再进行一次重新构建,以创建静态链接的可执行程序:
make clean
PATH=/到/Qt/的路径/bin:$PATH
export PATH
qmake -config release
make
你可能想要与发布 (release)版的库链接起来,可以在执行 qmake 的时候指定这个 。注意你必须将路径设置成我们刚刚构建的静态Qt 的路径 。
要检查以确认这个程序真的与Qt 静态链接在一起 ,那就运行 ldd 工具(在大多数Uni x 上 都有 ):
ldd ./application
检查确认,在输出里面没有提到Qt 库。
现在 ,在确定所有的东西 都正确地编译和链接了之后,我们应当有了一个可以部署的 plugandpaint 文件了 。一个简单的检查这个程序是否能独自运行的方法就是 , 将它复制到一个没有Qt 以及任何的Qt 程序的机器上 ,再运行它 。
记住,如果你的程序依赖了编译器的一些库 ,那么这些库仍然需要与你的程序一起重新发布 。要了解更多信息,就去看 程序依赖 小节 。
即 插 即 画 示例由多个组件构成 :核心程序 ( 即 插 即 画 )、 以及 基本工具 和 扩充过滤器 插件 。由于我们无法将插件用静态链接的方法来部署,所以我们准备好的可执行程序到现在还是不完整的 。程序能够运行,但是那些功能 都会被禁用,因为找不到插件。要部署基于插件的程序 ,我们应当使用共享库的方式。
当我们使用共享库的方式来部署 即 插 即 画 程序时 ,面临着两个挑战:Qt 运行时库必须与程序一起正确地发布 ,而插件必须安装到目标系统上正确的位置 ,这样程序才能找到它们。
我们假设你已经将Qt 作为一个共享库安装了 ,因为那是安装Qt 时的默认方式,并且你安装到了 /到/Qt/的路径 目录。
在确定Qt 是以共享库的方式构建的之后 ,我们可以构建 即 插 即 画 程序了 。首先 ,我们必须进入到包含了这个程序的目录:
cd /到/Qt/的路径/examples/tools/plugandpaint
现在运行qmake,为程序创建一个新的makefile,再进行一次重新构建,以创建动态链接的可执行程序:
make clean
qmake -config release
make
这就构建了核心程序,然后以下面的操作来构建插件:
cd ../plugandpaintplugins
make clean
qmake -config release
make
如果所有的东西 都正确地编译和链接了,我们就会得到一个 plugandpaint 可执行程序以及 libpnp_basictools.so 和 libpnp_extrafilters.so 插件文件。
在 Unix 上没有标准的包管理系统,所以我们在下面展示的是一个通用解决方法。查看你的目标系统的文档,看看该怎么创建一个软件包。
要部署这个程序 ,我们必须确保将相关的Qt 库 (对应于在程序中用到的Qt 模块) 、 平台插件 和可执行程序都复制到同一个目录 树 中。记住,如果你的程序依赖于编译器提供的库 ,那么那些库也应当与你的程序一起发布 。要了解更多信息,就去看 程序依赖 小节 。
我们稍后再说插件,现在主要的问题是,在使用共享库的情况下,你必须确保动态链接程序能够找到Qt 库。除非是你告诉了它,否则动态链接程序不会在你的程序所在的目录里查找。有很多方法可以解决这个问题:
• 你可以将Qt 库安装到系统的某个库路径里 (例如 ,在大多数系统上是 /usr/lib )。
• 你可以在链接程序的时候将一个预先确定的路径传递给 -rpath 命令行选项。这将导致动态链接程序在启动你的程序时在这个指定的目录里面查找库 。
• 你可以为你的程序写一个启动脚本 ,在那里面修改动态链接程序的配置(例如 ,将你的程序的目录添加到 LD_LIBRARY_PATH 环境变量中 。 注意 : 如果你的程序将会以"指定用户"的方式运行,并且指定的用户是root ,那么在某些平台上 LD_LIBRARY_PATH 会 被忽略。在这种情况下 ,使用 LD_LIBRARY_PATH的方法 无效 )。
第一 种方法的缺点是,用户必须拥有超级用户权限 。第二 种方法的缺点是 ,用户可能没有将库安装到预定义的路径的权限。在这 两种情况下,用户都不能将程序安装到他/她们的家目录中。我们建议使用第三 种方法,因为它最灵活。例如 , plugandpaint.sh 脚本可以写成这样 :
#!/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
$dirname/$appname "$@"
通过运行这个脚本,而不是直接运行那个可执行程序,你可以确保动态链接程序能够找到Qt 库。注意,当你在其它程序中使用这个脚本时,你仅仅需要将脚本改个名字。
当查找插件时 ,程序会在自己所在的目录中的plugins子目录里查找 。你或者需要手动地将插件复制到 plugins 目录 ,或者可以在插件的项目文件里设置 DESTDIR :
DESTDIR = /到/Qt/的路径/plugandpaint/plugins
一个用于发布在运行 即插即画 程序的时候所需的所有Qt 库 、所有插件的软件包,将会包含以下文件:
|
组件 |
文件名 |
|
可执行程序 |
plugandpaint |
|
用来运行可执行程序的脚本 |
plugandpaint.sh |
|
基本工具插件 |
plugins\libpnp_basictools.so |
|
扩展过滤器插件 |
plugins\libpnp_extrafilters.so |
|
Qt xcb平台插件 |
platforms\libqxcb.so |
|
Qt核心模块 |
libQtCore.so.4 |
|
Qt图形界面模块 |
libQtGui.so.4 |
|
Qt图形部件模块 |
libQt5Widgets.so.5 |
在大多数系统上 ,共享库的扩展名是 .so 。一个值得注意的例外是HP-UX ,它使用 .sl 。
记住,如果你的程序依赖编译器提供的一些库 ,那么它们也应当与你的程序一起发布 。要了解更多信息 ,就去看 程序依赖 小节。
要验证这个程序现在可以成功部署,你可以将这个软件包在一个没有Qt 和任何编译器的机器上解压 ,再尝试运行它,实际上,就是运行 plugandpaint.sh 脚本。
除了将插件放到 plugins 子目录中这种方法之外 ,另外一种方法就是在你的程序启动的时候使用 QApplication::addLibraryPath ()或者 QApplication::setLibraryPaths ()来添加一个自定义的查找路径 。
qApp->addLibraryPath("/其它/的/路径");
要找出你的程序依赖哪个库 ,就运行 ldd 工具(在大多数Uni x 上都有):
ldd ./application
这将列出你的程序依赖的所有共享库。依据配置情况,这些库都必须随你的程序重新发布。特别地,如果你使用的编译器与系统的编译器是二进制不兼容的,那么还需要发布标准C++库。在可能的时候,最安全的解决方法就是将程序与这些库静态链接。
你可能要将程序与常规X11 库动态链接 , 因为在某些库中 会尝试使用 dlopen() 来打开其它共享库 ,而如果那个操作失败了 ,那么X11 库可能引起你的程序崩溃。
还有一个值得提醒的事情 , Qt可能会寻找某些X11 扩展 ,例如Xinerama 和Xrandr,并且可能会将它们引用进来,这还包括它们链接到的其它库 。如果你不能确保某个扩展的存在性 ,那么最安全的办法就是在配置Qt 的时候禁用它(例如 , ./configure -no-xrandr ) 。
FontConfig和 FreeType 是另外两个不一定存在或者不一定有二进制兼容性的库的例子。可能听起来很奇怪 ,某些软件厂商通过在非常旧的机器上编译他/她们的软件并且仔细地确保不要升级它们系统上的任何软件来取得成功 。
当你将程序与Qt 库静态链接时 ,你必须显式地与上面提到的依赖库链接 。将它们添加到你的项目文件中的 LIBS 变量 ,以实现这一点。
在 Qt 5 中,所有的 Qt图形界面程序 都依赖 一个实现了 Qt平台抽象 (QPA)层的插件。对于 Linux/X11 , 这个平台插件的名字是 libqxcb.so 。 这个文字,必须位于妳的布目录中的某个特定 子目录 (默认 是 platforms ) 中。或者 , 也可以对Qt 用来查找插件的路径进行调整,下面会说明如何做到这一点。
你的程序还可能依赖一些Qt 插件 ,比如JPEG 图片格式插件或者SQL 驱动插件。确保将你的程序需要的全部Qt 插件 都发布了 。与平台插件类似 ,每种插件 都应当放置到你的发布目录中的一个特定子目录中(例如 imageformats 或者 sqldrivers )。
注意 : 如果你在部署一个使用 QtWebKit 来显示互联网上的网页的程序 ,你应当包含全部的文字编码插件以支持尽可能多的网页编码 。
查找Qt 插件 的路径(还有其它的一些路径)是硬编码到 QtCore 库中的 。默认地 ,第一个插件查找路径将会硬编码为 /到/Qt/的路径/plugins 。就像上面提到的那样 ,使用 预定义的路径有一些缺点,所以你需要尝试多种变通方法以确保可以找到Qt 插件 :
• 使用 QApplication::addLibraryPath ()或者 QApplication::setLibraryPaths () 。
• 使用一个第三方的安装工具或者是目标系统的包管理器来改变 QtCore 库中的硬编码路径 。
如何创建Qt插件 文档说明了你在为Qt 程序构建和部署插件时应当注意的事情 。
未知美人
未知美人
Your opinionsHxLauncher: Launch Android applications by voice commands