Qt for Linux/X11 - 部署
本文档讨论Qt for Linux/X11 的具体部署问题。我们将从部署 Qt 源码包中的Plug & Paint示例应用程序的角度来演示相关步骤。
由于 Unix 系统(如商业 Unix、Linux 发行版等)的扩散,Unix 上的部署是一个复杂的话题。在开始之前,请注意为一种 Unix 系统编译的程序很可能无法在另一种 Unix 系统上运行。例如,除非使用交叉编译器,否则无法在 Irix 上编译应用程序,然后在 AIX 上发布。
静态链接
静态链接通常是在 Unix 上发布应用程序的最安全、最简单的方法,因为它可以让您免去发布 Qt 库的任务,并确保它们位于目标系统上库的默认搜索路径中。
静态构建 Qt
要使用这种方法,必须先构建一个 _static_ 版本的 Qt 库。请按照《Qt for Linux/X11 - 从源代码构建》中的步骤进行,但切记在配置时添加-static
参数:
mkdir -p ~/dev/qt-build cd ~/dev/qt-build /tmp/qt-everywhere-src-6.9.0/configure -static
将应用程序链接到静态版 Qt
静态构建 Qt 后,下一步就是重新生成 makefile 并重建应用程序。首先,我们必须进入包含应用程序的目录:
cd /path/to/Qt/examples/widgets/tools/plugandpaint/app
现在运行 qmake 为应用程序创建一个新的 makefile,然后进行一次干净的联编,以创建静态链接的可执行文件:
make clean PATH=/path/to/Qt/bin:$PATH export PATH qmake -config release make
你可能希望与发行版库进行链接,可以在调用qmake
时指定这一点。请注意,我们必须设置刚刚构建的静态 Qt 的路径。
要检查应用程序是否真的与 Qt 进行了静态链接,请运行ldd
工具(可在大多数 Unices 上使用):
ldd ./application
确认输出结果中未提及 Qt 库。
现在,只要一切编译和链接无误,我们就应该有一个可以部署的plugandpaint
文件了。检查应用程序是否真的可以独立运行的一个简单方法是将其复制到一台没有安装 Qt 或任何 Qt 应用程序的机器上,然后在该机器上运行。
请记住,如果您的应用程序依赖于编译器特定的库,这些库必须与您的应用程序一起重新发布。有关详细信息,请参阅 "应用程序依赖性"部分。
Plug & Paint示例由多个组件组成:核心应用程序(Plug & Paint)以及基本工具和额外过滤器插件。由于我们不能使用静态链接方法部署插件,因此我们目前准备的可执行文件并不完整。应用程序可以运行,但由于缺少插件,其功能将被禁用。要部署基于插件的应用程序,我们应该使用共享库方法。
共享库
在使用共享库方法部署plugandpaint
应用程序时,我们面临两个挑战:Qt 运行时必须与应用程序可执行文件一起正确重新分发,插件必须安装在目标系统的正确位置,以便应用程序可以找到它们。
将 Qt 作为共享库构建
我们假定您已将 Qt 作为共享库(安装 Qt 时的默认设置)安装在/path/to/Qt
目录中。
将应用程序链接到作为共享库的 Qt
确保将 Qt 作为共享库构建后,我们就可以构建plugandpaint
应用程序了。首先,我们必须进入包含应用程序的目录:
cd /path/to/Qt/examples/tools/plugandpaint
现在运行 qmake 为应用程序创建一个新的 makefile,然后进行一次干净的编译以创建动态链接的可执行文件:
make clean
qmake -config release
make
这将构建核心应用程序,接下来将构建插件:
cd ../plugandpaint/plugins make clean qmake -config release make
如果一切编译和链接无误,我们将得到plugandpaint
可执行文件以及libpnp_basictools.so
和libpnp_extrafilters.so
插件文件。
创建应用程序软件包
Unix 上没有标准的软件包管理,因此下面介绍的方法是一种通用的解决方案。有关如何创建软件包的信息,请参阅目标系统的文档。
要部署应用程序,我们必须确保将相关 Qt 库(与应用程序中使用的 Qt 模块相对应)、平台插件和可执行文件复制到同一目录树中。请记住,如果您的应用程序依赖于编译器特定的库,这些库也必须与您的应用程序一起重新发布。有关详细信息,请参阅应用程序依赖性部分。
我们很快会介绍插件,但共享库的主要问题是,你必须确保动态链接器能找到 Qt 库。除非另有说明,否则动态链接器不会搜索应用程序所在的目录。解决这个问题的方法有很多:
- 您可以将 Qt XML 库安装在系统库路径之一(如大多数系统中的
/usr/lib
)。 - 在链接应用程序时,可以将预先确定的路径传递给
-rpath
命令行选项。这将告诉动态链接器在启动应用程序时查找该目录。 - 您可以为应用程序编写启动脚本,修改动态链接器配置(例如,将应用程序的目录添加到
LD_LIBRARY_PATH
环境变量中)。注意: 如果您的应用程序将以 "执行时设置用户 ID "的方式运行,并且由 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
目录,要么在插件的项目文件中设置DESTDIR
:
DESTDIR = /path/to/Qt/plugandpaint/plugins
一个包含运行plugandpaint
应用程序所需的所有 Qt 库和所有插件的压缩包必须包括以下文件:
组件 | 文件名 | |
---|---|---|
可执行文件 | plugandpaint | |
运行可执行文件的脚本 | plugandpaint.sh | |
基本工具插件 | plugins\libpnp_basictools.so | |
额外过滤器插件 | plugins\libpnp_extrafilters.so | |
Qt xcb 平台插件 | platforms\libqxcb.so | |
Qt Core 模块 | libQt6Core.so.6 | |
Qt GUI 模块 | libQt6Gui.so.6 | |
Qt Widgets 模块 | libQt6Widgets.so.6 |
在大多数系统中,共享库的扩展名为.so
。HP-UX 是一个明显的例外,它使用.sl
。
请记住,如果您的应用程序依赖于编译器特定的库,这些库必须与您的应用程序一起重新发布。有关详细信息,请参阅应用程序依赖性部分。
要验证现在的应用程序是否可以成功部署,可以在没有安装 Qt XML 也没有安装任何编译器的机器上解压此压缩包,并尝试运行它,即运行plugandpaint.sh
脚本。
除了将插件放在plugins
子目录中外,还可以在使用QApplication::addLibraryPath() 或QApplication::setLibraryPaths() 启动应用程序时添加自定义搜索路径。
QCoreApplication::addLibraryPath("/some/other/path");
应用程序依赖项
附加库
要了解应用程序依赖于哪些库,请运行ldd
工具(大多数 Unices 上都提供):
ldd ./application
该工具将列出应用程序依赖的所有共享库。根据配置,这些库必须与应用程序一起重新发布。特别是,如果使用与系统编译器二进制不兼容的编译器编译应用程序,则必须重新发布标准 C++ 库。在可能的情况下,最安全的解决方案是静态链接这些库。
您可能希望与常规 X11 库进行动态链接,因为某些实现会尝试使用dlopen()
打开其他共享库,如果尝试失败,X11 库可能会导致应用程序崩溃。
值得一提的是,Qt 会查找某些 X11 扩展库,如 Xinerama 和 Xrandr,并可能将它们拉入,包括它们链接的所有库。如果你不能保证某个扩展的存在,最安全的方法是在配置 Qt 时禁用它(如./configure -no-xrandr
)。
FontConfig 和 FreeType 是其他一些并非总是可用或二进制并非总是兼容的库的例子。虽然听起来很奇怪,但一些软件供应商通过在非常老旧的机器上编译他们的软件取得了成功,并且非常谨慎地没有升级在这些机器上运行的任何软件。
在根据静态 Qt 库链接应用程序时,必须明确链接上述依赖库。方法是将它们添加到项目文件中的LIBS
变量。
Qt 插件
所有Qt GUI 应用程序都需要一个在 Qt 中实现Qt 平台抽象(QPA)层的插件。对于 Linux/X11,平台插件的名称是libqxcb.so
。该文件必须位于发行版目录下的特定子目录(默认情况下为platforms
)中。另外,也可以调整 Qt 查找插件的搜索路径,如下所述。
您的应用程序也可能依赖于一个或多个 Qt 插件,例如 JPEG Image Formats 插件或 SQL 驱动程序插件。请务必将您需要的任何 Qt 插件与您的应用程序一起发布。与平台插件类似,每种插件都必须位于分发目录中的特定子目录(如imageformats
或sqldrivers
)中。
Qt 插件的搜索路径(以及其他一些路径)被硬编码到QtCore 库中。默认情况下,第一个插件搜索路径将被硬编码为/path/to/Qt/plugins
。如上所述,使用预定路径有一定的弊端,因此需要检查各种替代路径,以确保找到 Qt 插件:
- 使用
qt.conf
。这是推荐的方法,因为它提供了最大的灵活性。 - 使用QApplication::addLibraryPath() 或QApplication::setLibraryPaths() 。
- 使用第三方安装工具或目标系统的软件包管理器更改QtCore 库中的硬编码路径。
如何创建 Qt 插件》文档概述了为 Qt 应用程序构建和部署插件时需要注意的问题。
© 2025 The Qt Company Ltd. Documentation contributions included herein are the copyrights of their respective owners. The documentation provided herein is licensed under the terms of the GNU Free Documentation License version 1.3 as published by the Free Software Foundation. Qt and respective logos are trademarks of The Qt Company Ltd. in Finland and/or other countries worldwide. All other trademarks are property of their respective owners.