本页内容

Linux 版 Qt - 部署

本文档讨论了Qt for Linux 的具体部署问题。我们将以部署 Qt 源代码包中附带的Plug & Paint示例应用程序为例,演示相关步骤。

由于 Unix 系统(如商用 Unix 或 Linux 发行版)种类繁多,在 Unix 上的部署是一个复杂的话题。 在开始之前,请注意:为某种 Unix 变体编译的程序很可能无法在其他 Unix 系统上运行。例如,除非使用交叉编译器,否则无法在 Irix 上编译应用程序并在 AIX 上分发。

共享库

在使用共享库方法部署plugandpaint 应用程序时,我们面临两个挑战:Qt运行时必须与应用程序可执行文件一起正确地重新分发,并且插件必须安装在目标系统上的正确位置,以便应用程序能够找到它们。

将 Qt 构建为共享库

我们假设您已经将 Qt 作为共享库安装在/path/to/Qt 目录下——这是安装 Qt 时的默认设置。

将应用程序链接到作为共享库的 Qt

在确认 Qt 已作为共享库构建后,我们可以构建plugandpaint 应用程序。首先,我们必须进入包含该应用程序的目录:

cd /path/to/Qt/examples/tools/plugandpaint

现在运行 qmake 为应用程序创建新的 makefile,并执行 clean 构建以生成动态链接的可执行文件:

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 库安装到系统库路径之一(例如,在大多数系统上为/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 子目录中进行搜索。您要么手动将插件复制到plugins 目录中,要么可以在插件的项目文件中设置DESTDIR :

DESTDIR = /path/to/Qt/plugandpaint/plugins

一个用于分发运行plugandpaint 应用程序所需的所有 Qt 库和插件的归档包,必须包含以下文件:

组件文件名
可执行文件plugandpaint
用于运行可执行文件的脚本plugandpaint.sh
Basic Tools 插件plugins\libpnp_basictools.so
ExtraFilters 插件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 和任何编译器的机器上解压此归档文件,并尝试运行它,即运行plugandpaint.sh 脚本。

除了将插件放置在plugins 子目录中,另一种方法是在使用QApplication::addLibraryPath()或QApplication::setLibraryPaths()启动应用程序时,添加自定义搜索路径。

QCoreApplication::addLibraryPath("/some/other/path");

静态链接

在 Unix 上,静态链接通常是分发应用程序最安全、最简单的方法,因为它免除了您分发 Qt 库以及确保它们位于目标系统上库的默认搜索路径中的任务。

静态构建 Qt

要使用此方法,您必须首先构建 Qt 库的_静态_版本。请按照《Qt for Linux - 从源代码构建》中的步骤操作,但请记住向 configure 添加-static 参数:

mkdir -p ~/dev/qt-build
cd ~/dev/qt-build
/tmp/qt-everywhere-src-6.12.0/configure -static

将应用程序链接到静态版本的 Qt

一旦 Qt 以静态方式构建完成,下一步就是重新生成 makefile 并重新构建应用程序。首先,我们必须进入包含应用程序的目录:

cd /path/to/Qt/examples/widgets/tools/plugandpaint/app

现在运行 qmake 为应用程序生成新的 makefile,并执行 clean 构建以生成静态链接的可执行文件:

make clean
PATH=/path/to/Qt/bin:$PATH
export PATH
qmake -config release
make

您可能希望链接到发布版库,可以在调用qmake 时指定此选项。请注意,必须设置为指向我们刚刚构建的静态 Qt 的路径。

要检查应用程序是否确实与 Qt 进行了静态链接,请运行ldd 工具(在大多数 Unix 系统上可用):

ldd ./application

请确认输出中未提及 Qt 库。

现在,只要编译和链接过程均未出现错误,我们就应该得到一个可供部署的plugandpaint 文件。验证应用程序是否确实可以独立运行的一种简单方法是,将其复制到未安装 Qt 或任何 Qt 应用程序的机器上,并在该机器上运行它。

请注意,如果您的应用程序依赖于特定编译器的库,则必须将这些库与应用程序一同分发。有关更多信息,请参阅“应用程序依赖项”一节。

“Plug & Paint”示例由多个组件构成:核心应用程序(Plug & Paint),以及“Basic Tools”和“Extra Filters”插件。由于无法使用静态链接方式部署插件,因此目前我们准备的可执行文件尚不完整。 应用程序虽然可以运行,但由于缺少插件,相关功能将被禁用。要部署基于插件的应用程序,我们应采用共享库方法。

应用程序依赖项

附加库

要查明您的应用程序依赖哪些库,请运行ldd 工具(大多数Unix系统上均可使用):

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 图像格式插件或 SQL 驱动程序插件。请确保将您所需的任何 Qt 插件与应用程序一同分发。与平台插件类似,每种类型的插件都必须位于分发目录下的特定子目录中(例如imageformats 或sqldrivers )。

Qt 插件的搜索路径(以及其他几个路径)被硬编码在QtCore 库中。默认情况下,第一个插件搜索路径将被硬编码为/path/to/Qt/plugins 。如上所述,使用预设路径存在某些弊端,因此您需要考察各种替代方案以确保能够找到 Qt 插件:

《如何创建 Qt 插件》文档概述了在为 Qt 应用程序构建和部署插件时需要注意的问题。

分步指南:创建 DEB 软件包

本节介绍如何利用 Qt 6.5 或更高版本中提供的 CMake 部署 API,在 Linux 上为您的 Qt 应用程序创建 DEB 包。目前没有专用的linuxdeployqt 工具,当前的解决方案仅依赖于 CMake 的内置功能。

示例项目设置

从一个简单的 CMake 项目开始:

cmake_minimum_required(VERSION 3.22)
project(MyApp)

find_package(Qt6 REQUIRED COMPONENTS Widgets)
qt_standard_project_setup()

qt_add_executable(MyApp main.cpp)
target_link_libraries(MyApp PRIVATE Qt::Widgets)

步骤 1:准备安装环境

添加用于安装应用程序和生成部署脚本的命令,以创建一个自包含目录:

# Install the executable to "${CMAKE_INSTALL_PREFIX}/bin".
install(TARGETS MyApp
    BUNDLE  DESTINATION .
    RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
)

# Generate the deployment script for MyApp.
qt_generate_deploy_app_script(
    TARGET MyApp
    FILENAME_VARIABLE deploy_script
    NO_UNSUPPORTED_PLATFORM_ERROR
)

# Run the deployment script during installation (on "cmake --install").
install(SCRIPT ${deploy_script})

构建并安装项目:

qt-cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=/tmp/my-application ..
cmake --build .
cmake --install .

部署脚本:

  • 在可执行文件旁边创建一个 qt.conf 文件,其中包含目录布局的相关信息。运行时需要该文件来查找插件和资源。详情请参阅 qt.conf 文档。
  • 使用 CMake 的内置函数(GET_RUNTIME_DEPENDENCIES)检查可执行文件及所用的 Qt 插件,以确定需要部署哪些 Qt 库。
  • 安装必要的 Qt 插件和 Qt 库。

现在可以将安装目录复制到另一台机器上,应用程序仍应能够正常运行。

步骤 2:创建 DEB 包

安装完成后,使用 CPack 对该目录进行打包。在您的 CMake 项目中添加以下内容:

set(CPACK_PACKAGE_NAME my-app)
set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "My amazing application")
set(CPACK_PACKAGE_VENDOR "My Company")
set(CPACK_PACKAGE_INSTALL_DIRECTORY ${CPACK_PACKAGE_NAME})
set(CPACK_VERBATIM_VARIABLES ON)
set(CPACK_PACKAGING_INSTALL_PREFIX "/opt/myapp")
set(CPACK_DEBIAN_PACKAGE_MAINTAINER "Package Maintainer <maintainer@example.com>")
set(CPACK_DEBIAN_PACKAGE_DEPENDS libc6 libstdc++6 libgcc-s1)
include(CPack)

重新配置项目,导航至构建目录(该目录必须包含CPackConfig.cmake 文件),并运行CPack生成DEB包:

cpack -G DEB

要查看软件包的内容:

dpkg -c my_app-1.0-Linux.deb

要安装该包:

sudo dpkg -i my_app-1.0-Linux.deb

© 2026 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.