Windows 的 Qt - 部署
本文档介绍Windows 的部署过程。在整个文档中,我们参考了 "即插即用"示例应用程序来演示部署过程。
注意: 将您的 Qt 构建目录添加到系统上运行的任何防病毒程序的排除目录列表中。
Windows 部署工具
Windows 部署工具windeployqt
设计用于自动创建可部署文件夹,其中包含从该文件夹运行应用程序所需的Qt 相关依赖项(库、QML 导入、插件和翻译)。该工具可为 Windows 桌面应用程序创建安装树,并可轻松将其捆绑到安装包中。
该工具可在QTDIR/bin/windeployqt
中找到。它需要在构建环境中运行才能正常工作。使用Qt Online Installer 时,应使用脚本QTDIR/bin/qtenv2.bat
进行设置。
windeployqt
该脚本将 文件或包含 文件的目录作为参数,并扫描可执行文件以查找依赖关系。如果 参数传递的是目录, 会使用 工具扫描目录内的 QML 文件,查找 QML 导入依赖项。识别出的依赖项将被复制到可执行文件的目录中。.exe
.exe
--qmldir
windeployqt
qmlimportscanner
如果 Qt 在构建时关闭了配置开关-relocatable
,windeployqt
会将 Qt6Core.dll 中硬编码的本地路径替换为相对路径。
对于 Windows 桌面应用程序,编译器所需的运行时文件默认也会复制到可部署文件夹(除非指定了选项--no-compiler-runtime
)。在使用 Microsoft Visual C++ 发布的情况下,这些文件包括 Visual C++ Redistributable Packages,用于应用程序安装程序在目标计算机上的递归安装。否则,将使用编译器运行时的共享库。
应用程序可能需要额外的第三方库(如数据库库),windeployqt 不会考虑这些库。
其他参数在工具的帮助输出中有所说明:
Usage: windeployqt [options] [files] Qt Deploy Tool 6.0.0 The simplest way to use windeployqt is to add the bin directory of your Qt installation (e.g. <QT_DIR\bin>) to the PATH variable and then run: windeployqt <path-to-app-binary> If ICU, etc. are not in the bin directory, they need to be in the PATH variable. If your application uses Qt Quick, run: windeployqt --qmldir <path-to-app-qml-files> <path-to-app-binary> Options: -?, -h, --help Displays help on commandline options. --help-all Displays help including Qt specific options. -v, --version Displays version information. --dir <directory> Use directory instead of binary directory. --qmake <path> Use specified qmake instead of qmake from PATH. --libdir <path> Copy libraries to path. --plugindir <path> Copy plugins to path. --debug Assume debug binaries. --release Assume release binaries. --pdb Deploy .pdb files (MSVC). --force Force updating files. --dry-run Simulation mode. Behave normally, but do not copy/update any files. --no-patchqt Do not patch the Qt6Core library. --ignore-library-errors Ignore errors when libraries cannot be found. --no-plugins Skip plugin deployment. --no-libraries Skip library deployment. --qmldir <directory> Scan for QML-imports starting from directory. --qmlimport <directory> Add the given path to the QML module search locations. --no-quick-import Skip deployment of Qt Quick imports. --translations <languages> A comma-separated list of languages to deploy (de,fi). --no-translations Skip deployment of translations. --no-system-d3d-compiler Skip deployment of the system D3D compiler. --compiler-runtime Deploy compiler runtime (Desktop only). --no-virtualkeyboard Disable deployment of the Virtual Keyboard. --no-compiler-runtime Do not deploy compiler runtime (Desktop only). --json Print to stdout in JSON format. --no-opengl-sw Do not deploy the software rasterizer library. --list <option> Print only the names of the files copied. Available options: source: absolute path of the source files target: absolute path of the target files relative: paths of the target files, relative to the target directory mapping: outputs the source and the relative target, suitable for use within an Appx mapping file --verbose <level> Verbose level (0-2). Qt libraries can be added by passing their name (-xml) or removed by passing the name prepended by --no- (--no-xml). Available libraries: bluetooth concurrent core declarative designer designercomponents gui qthelp multimedia multimediawidgets multimediaquick network nfc opengl openglwidgets positioning printsupport qml qmltooling quick quickparticles quickwidgets script scripttools sensors serialport sql svg svgwidgets test websockets widgets xml webenginecore webengine webenginewidgets 3dcore 3drenderer 3dquick 3dquickrenderer 3dinput 3danimation 3dextras geoservices webchannel serialbus webview Arguments: [files] Binaries or directory containing the binary.
静态链接
要构建静态应用程序,可通过-static
配置 Qt 来静态构建 Qt XML:
cd C:\path\to\Qt configure -static <any other options you need>
如果以后需要从同一位置重新配置和重建 Qt,请确保删除先前配置的所有痕迹,方法是进入构建目录并运行nmake distclean
或mingw32-make distclean
,然后再运行configure
。
将应用程序链接到静态版 Qt
作为示例,本节将静态构建Plug & Paint示例。
一旦 Qt 完成编译,即可构建Plug & Paint应用程序。首先,我们必须进入包含应用程序的目录:
cd examples\tools\plugandpaint
运行qmake
为应用程序创建一个新的 makefile,然后执行一次干净的编译以创建静态链接的可执行文件:
nmake clean
qmake -config release
nmake
您可能希望与发行版库进行链接,可以在调用qmake
时指定这一点。现在,如果一切编译和链接都没有错误,我们就应该有一个可以部署的plugandpaint.exe
文件了。要检查应用程序是否拥有所需的库,可将可执行文件复制到一台未安装 Qt 或任何 Qt 应用程序的机器上,并在该机器上运行。
请记住,如果您的应用程序依赖于编译器特定的库,这些库必须与您的应用程序一起重新发布。您可以使用depends
工具检查应用程序正在链接哪些库。更多信息,请阅读应用程序依赖性部分。
由于我们不能使用静态链接方法部署插件,因此我们准备的应用程序是不完整的。它可以运行,但由于缺少插件,功能将被禁用。要部署基于插件的应用程序,我们应该使用共享库方法。
共享库
在使用共享库方法部署plugandpaint
应用程序时,我们面临两个挑战:Qt 运行时必须与应用程序可执行文件一起正确重新分发,插件必须安装在目标系统的正确位置,以便应用程序可以找到它们。
将 Qt 作为共享库构建
在本例中,我们假定 Qt 作为共享库安装(这是安装 Qt 时的默认设置),安装在C:\path\to\Qt目录中。
将应用程序链接到作为共享库的 Qt
确保将 Qt 作为共享库构建后,我们就可以构建plugandpaint
应用程序了。首先,我们必须进入包含应用程序的目录:
cd examples\tools\plugandpaint
现在运行qmake
为应用程序创建一个新的 makefile,然后进行一次干净的编译以创建动态链接的可执行文件:
nmake clean
qmake -config release
nmake
这将构建核心应用程序,接下来将构建插件:
cd ..\plugandpaint/plugins nmake clean qmake -config release nmake
如果一切编译和链接无误,我们将得到plugandpaint.exe
可执行文件以及pnp_basictools.dll
和pnp_extrafilters.dll
插件文件。
创建应用程序软件包
要部署应用程序,我们必须确保将相关的 Qt DLL(与应用程序中使用的 Qt 模块相对应)和 Windows 平台插件qwindows.dll
以及可执行文件复制到release
子目录下的同一目录树中。
与用户插件不同,Qt 插件必须放在与插件类型相匹配的子目录中。平台插件的正确位置是名为platforms
的子目录。Qt 插件部分有关于插件和 Qt 如何搜索插件的更多信息。
如果使用动态 OpenGL,如果应用程序与之兼容,您可能还需要包含所需的基于软件的 OpenGL 库。
如果 Qt 被配置为针对 ICU 或 OpenSSL 进行链接,则相应的 DLL 也需要添加到release
文件夹中。但 Windows 上的 Qt 二进制软件包确实需要这样做。更多详情,请参阅第三方库。
请记住,如果您的应用程序依赖于编译器特定的库,这些库必须与您的应用程序一起重新发布。您可以使用depends
工具检查应用程序正在链接哪些库。更多信息,请参阅应用程序依赖性部分。
我们很快会介绍插件,但首先要检查应用程序是否能在部署环境中运行:要么将可执行文件和 Qt 动态链接库复制到没有安装 Qt 或任何 Qt 应用程序的机器上,要么如果要在构建机器上进行测试,则确保该机器的环境中没有 Qt。
如果应用程序顺利启动,那么我们就成功制作了plugandpaint
应用程序的动态链接版本。但由于我们尚未部署相关插件,应用程序的功能仍将缺失。
插件的工作方式与普通 DLL 不同,因此我们不能像处理 Qt DLL 那样,将其复制到与应用程序可执行文件相同的目录中。在查找插件时,应用程序会在应用程序可执行文件目录下的plugins
子目录中进行搜索。
因此,为了让我们的应用程序可以使用插件,我们必须创建plugins
子目录,并复制相关的 DLL:
plugins\pnp_basictools.dll plugins\pnp_extrafilters.dll
在运行 "即插即用"应用程序所需的所有 Qt 动态链接库和应用程序特定插件的压缩包中,必须包含以下文件:
组件 | 文件名 | |
---|---|---|
可执行文件 | plugandpaint.exe | |
基本工具插件 | plugins\pnp_basictools.dll | |
额外过滤器插件 | plugins\pnp_extrafilters.dll | |
Qt Windows 平台插件 | platforms\qwindows.dll | |
Qt Windows Vista 风格插件 | styles\qwindowsvistastyle.dll | |
Qt Core 模块 | Qt6Core.dll | |
Qt GUI 模块 | Qt6Gui.dll | |
Qt Widgets 模块 | Qt6Widgets.dll |
根据应用程序使用的功能,可能还需要其他插件 (iconengines
,imageformats
)。
此外,压缩包必须包含以下编译器专用库(假设为 Visual Studio 17 (2022)):
组件 | 文件名 | |
---|---|---|
C 运行时 | vcruntime140.dll | |
C++ 运行时 | msvcp170.dll |
如果使用了动态 OpenGL,那么存档中还可能包含
组件 | 文件名 | |
---|---|---|
OpenGL 软件渲染器库 | opengl32sw.dll |
最后,如果 Qt 被配置为使用 ICU,压缩包必须包含
文件名 | ||
---|---|---|
icudtXX.dll | icuinXX.dll | icuucXX.dll |
要验证应用程序现在是否可以成功部署,可以在没有安装 Qt 也没有安装任何编译器的机器上解压此压缩包,并尝试运行它。
除了将插件放在插件子目录中,还可以在使用QCoreApplication::addLibraryPath() 或QCoreApplication::setLibraryPaths() 启动应用程序时添加自定义搜索路径。
QCoreApplication::addLibraryPath("C:/some/other/path");
使用插件的一个好处是,它们可以很容易地提供给整个应用程序系列。
通常最方便的做法是在应用程序的main()
函数中,即在创建QApplication 对象后添加路径。添加路径后,除了在应用程序自身目录下的plugins
子目录中查找外,应用程序还将在其中搜索插件。可以添加任意数量的附加路径。
任务文件
在部署使用 Visual Studio 编译的应用程序时,需要采取一些额外的步骤。
首先,我们需要复制链接应用程序时创建的清单文件。该清单文件包含应用程序对并行程序集(如运行时库)的依赖信息。
需要将清单文件复制到与应用程序可执行文件相同的文件夹中。您不需要复制共享库 (DLL) 的清单文件,因为它们不会被使用。
如果共享库的依赖关系与使用共享库的应用程序不同,则需要将清单文件嵌入到 DLL 二进制文件中。以下CONFIG
选项可用于嵌入清单:
embed_manifest_dll embed_manifest_exe
这两个选项默认都已启用。要移除embed_manifest_exe
,请添加
CONFIG -= embed_manifest_exe
到 .pro 文件中。
有关清单文件和并行装配体的更多信息,请访问并行装配体文档页面。
在应用程序中包含运行库的正确方法是确保它们已安装到最终用户的系统中。
要在最终用户的系统中安装运行库,需要在应用程序中包含相应的 Visual C++ Redistributable Package (VCRedist) 可执行文件,并确保在用户安装应用程序时执行该文件。
可重新分发包名为vc_redist.x64.exe
(64-bit),可在<Visual Studio install path>/VC/redist/<language-code>
文件夹中找到。
也可从网上下载,例如https://support.microsoft.com/en-us/help/2977003/the-latest-supported-visual-c-downloads。
注意: 您发送的应用程序必须使用完全相同的编译器版本和相同的 C 运行时版本进行编译。这样可以避免因 C 运行时库版本不同而导致的部署错误。
应用程序依赖关系
附加库
根据配置,编译器特定库必须与应用程序一起重新发布。
您可以使用Dependency Walker工具检查应用程序正在链接哪些库。您只需像这样运行该工具即可:
depends <application executable>
它将提供应用程序所依赖的库列表及其他信息。
使用depends
工具查看 Plug & Paint 可执行文件 (plugandpaint.exe
) 的发布版本时,该工具列出了以下非系统库的直接依赖关系:
Qt | Visual Studio 17 (2022) | Mingw-w64 |
---|---|---|
|
|
在查看插件动态链接库时,我们发现其中列出了完全相同的依赖关系。
Qt 插件
所有Qt GUI 应用程序都需要一个在 Qt 中实现Qt 平台抽象(QPA)层的插件。对于 Windows,平台插件的名称是qwindows.dll
。该文件必须位于发布目录下的特定子目录(默认情况下为platforms
)中。另外,也可以调整 Qt 查找插件的搜索路径,如下所述。
您的应用程序也可能依赖于一个或多个 Qt 插件,如打印支持插件、JPEG 图像格式插件或 SQL 驱动程序插件。请务必将您需要的任何 Qt 插件与您的应用程序一起发布。与平台插件类似,每种插件都必须位于分发目录中的特定子目录下(如printsupport
、imageformats
或sqldrivers
)。
除非 Qt 在构建时关闭了配置开关-relocatable
,否则这些库是可重置的。Qt 插件的搜索路径是相对于QtCore 库的位置而言的,在目标计算机上安装应用程序后,无需进一步的步骤来确保找到插件。
使用不可重定位构建时确保找到插件
对于不可定位的构建,必须采取额外步骤,以确保在目标计算机上安装应用程序后找到插件。
在这种情况下,Qt XML 插件的搜索路径被硬编码到QtCore 库中。默认情况下,Qt 安装的插件子目录是第一个插件搜索路径。不过,像默认路径这样的预设路径有一些缺点。例如,目标计算机上可能不存在这些路径。因此,您需要检查各种替代路径,以确保找到 Qt 插件:
- 使用
qt.conf
。如果不同地方的可执行文件共享相同的插件,建议使用这种方法。 - 使用QApplication::addLibraryPath() 或QApplication::setLibraryPaths() 。如果只有一个可执行文件使用该插件,建议使用这种方法。
- 使用第三方安装实用程序更改QtCore 库中的硬编码路径。
如果你使用 QApplication::addLibraryPath 添加自定义路径,它可能看起来像这样:
QCoreApplication::addLibraryPath("C:/customPath/plugins");
然后,QCoreApplication::libraryPaths() 将返回如下内容:
C:/customPath/plugins
C:/Qt/%VERSION%/plugins
E:/myApplication/directory
可执行文件将在这些目录中查找插件,顺序与QCoreApplication::libraryPaths() 返回的QStringList 相同。新添加的路径在QCoreApplication::libraryPaths() 之前,这意味着它将首先被搜索。不过,如果使用QCoreApplication::setLibraryPaths() ,则可以确定搜索的路径和顺序。
如何创建 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.