Windows 版 Qt - 部署
本文档介绍了Windows 平台的部署流程。在整个文档中,我们将以“Plug & Paint”示例应用程序为例,演示部署流程。
注意:请将 您的 Qt 构建目录添加 到系统上运行的任何防病毒软件的“排除目录”列表中。
Windows 部署工具
在 Windows 上部署 Qt 应用程序的推荐且最简单的方法是使用 windeployqt 工具,该工具会自动将所有必需的 Qt 库、插件、QML 模块和运行时依赖项收集到一个可直接运行的部署文件夹中。
它会为 Windows 桌面应用程序创建一个安装树,该安装树可轻松打包成安装包。
注意:应用程序 可能还需要其他第三方库(例如数据库库),而 windeployqt 不会将这些库纳入考虑范围。
设置构建环境
如果您是通过Qt Online Installer 安装的 Qt,则在运行 windeployqt 之前必须先设置好构建环境。为此,请执行以下命令:
<qt-installation-folder>/bin/qtenv2.bat用法
windeployqt 位于<qt-installation-folder>/bin/ 目录下,它接受一个名为.exe 的文件或包含.exe 文件的目录作为参数,并扫描可执行文件的依赖项。
请注意以下几点:
- 如果通过
--qmldir参数传入一个目录,windeployqt 将使用 qmlimportscanner 工具扫描该目录中的 QML 文件,以查找 QML 导入依赖项。随后,识别出的依赖项将被复制到可执行文件的目录中。 - 如果 Qt 在构建时关闭了 `
-relocatable` 配置选项,windeployqt 会将 `Qt6Core.dll` 中硬编码的本地路径替换为相对路径。 - 对于 Windows 桌面应用程序,除非指定了
--no-compiler-runtime,否则 windeployqt 会默认复制所需的编译器运行时文件。对于使用 Microsoft Visual C++ 的发布版本构建,这意味着该工具期望应用程序安装程序包含官方的 Visual C++ 可再分发包。如果无法获得再分发包,windeployqt 可能会回退到使用开发人员机器上找到的编译器的共享运行时 DLL。这些单独的 DLL并非旨在或被许可用于再分发,因此不应直接随应用程序发布。 在最终用户系统上进行部署时,应仅使用官方的 Microsoft 再分发安装程序。
常见用例
部署标准的Qt Widgets 应用程序
windeployqt.exe .\build\MyApp.exe部署包含 QML 源文件的Qt Quick 应用程序
windeployqt.exe --qmldir .\qml .\build\MyApp.exe生成用于打包的 appx 清单文件
当您准备将应用程序打包为 Windows appx 包时,请使用此方法。
--appx 选项将生成AppxManifest.xml 文件,而--appx-certificate 则指定要嵌入到清单中的证书。
windeployqt.exe --appx --appx-certificate MyCompany.cer .\build\MyApp.exe执行模拟运行
干运行会模拟部署过程,但不会复制或更新任何内容。
windeployqt.exe --dry-run MyApp.exe选项
常规
| 选项 | 描述 |
|---|---|
-?,-h,--help | 显示命令行选项的帮助。 |
--help-all | 显示包含通用 Qt 选项在内的完整 Qt Help。 |
-v,--version | 显示版本信息。 |
输入和输出控制
| 选项 | 描述 |
|---|---|
--dir <path> | 将此目录用作部署目标,而不是二进制目录。 |
--libdir <path> | 将 Qt 库复制到此目录。 |
--plugindir <path> | 将 Qt 插件复制到此目录。 |
--qml-deploy-dir <path> | 将 QML 文件复制到此目录。 |
--translationdir <path> | 将翻译文件复制到此目录中。 |
Qt 路径解析
| 选项 | 说明 |
|---|---|
--qtpaths <path> | 使用特定的qtpaths.exe 文件来解析Qt Location。 |
构建配置
| 选项 | 描述 |
|---|---|
--debug | 假设为调试二进制文件。 |
--release | 假定为发布二进制文件。 |
--pdb | 部署 MSVC 的.pdb 文件。 |
部署行为
| 选项 | 描述 |
|---|---|
--force | 覆盖现有文件。 |
--dry-run | 模拟部署,不复制或更新任何内容。 |
--ignore-library-errors | 即使缺少某些库,仍继续执行。 |
--json | 以 JSON 格式输出部署信息。 |
--appx | 为 Windows 应用商店创建一个 `AppxManifest.xml ` 文件。 |
--nopatchqt | 跳过对QtCore 库的修补。 |
--no-libraries | 跳过库部署。 |
--verbose <level> | 详细程度级别(0–2)。 |
插件
| 选项 | 描述 |
|---|---|
--no-plugins | 跳过插件部署。 |
--include-soft-plugins | 根据软依赖关系包含所有相关插件。 |
--skip-plugin-types <types> | 一个以逗号分隔的列表,列出不添加到部署中的特定插件类别。 |
--add-plugin-types <types> | 要添加到部署中的插件类型的逗号分隔列表。 |
--include-plugins <plugins> | 要添加到部署中的特定插件(按名称)的逗号分隔列表。 |
--exclude-plugins <plugins> | 不添加到部署中的特定插件(按名称)的以逗号分隔的列表。 |
QML
| 选项 | 描述 |
|---|---|
--qmldir <directory> | 从该目录开始扫描 QML 导入项。 |
--qmlimporttimeout <ms> | 设置qmlimportscanner 运行的超时时间(单位为毫秒)。默认值为30000毫秒。如果qmlimportscanner 在处理大型或复杂的QML代码库时发生超时,请增加此值。 |
--qmlimport <directory> | 额外的 QML 模块搜索路径。 |
--no-quick-import | 跳过Qt Quick 导入项的部署。 |
翻译
| 选项 | 描述 |
|---|---|
--translations <languages> | 要部署翻译的语言列表(以逗号分隔)。 |
--no-translations | 跳过翻译。 |
系统和运行时组件
| 选项 | 描述 |
|---|---|
--no-system-d3d-compiler | 跳过系统 D3D 编译器。 |
--no-system-dxc-compiler | 跳过系统 DXC 编译器。 |
--compiler-runtime | 部署运行时编译器(仅限桌面版)。 |
--no-compiler-runtime | 不部署运行时编译器(仅限桌面版)。 |
--no-opengl-sw | 跳过软件 OpenGL 渲染器。 |
--no-ffmpeg | 跳过 FFmpeg 库。 |
--force-openssl | 部署 OpenSSL 插件,但忽略库依赖关系。 |
--openssl-root <directory> | 包含 OpenSSL 库的目录。 |
--appx-certificate <.cer file> | 用于签署 appx 包的 appx 证书路径。 |
文件列表输出
| 选项 | 说明 |
|---|---|
--list <option> | 仅将文件名打印到标准输出。 选项:
|
静态链接
要构建静态应用程序,请使用-static 配置 Qt 并以静态方式构建 Qt:
cd C:\path\to\Qt
configure -static <any other options you need>如果您稍后需要从同一位置重新配置并重新构建 Qt,请确保已清除所有先前配置的痕迹。
将应用程序链接到静态版本的 Qt
作为示例,本节将使用静态构建的 Qt 来构建Plug & Paint示例。
\path\to\static\Qt首先,我们必须进入包含该应用程序的目录:
cd examples\tools\plugandpaint现在,我们创建一个构建目录,并调用qt-cmake 来生成构建系统文件。
md build_static
cd build_static
C:\path\to\static\Qt\bin\qt-cmake .. -DCMAKE_BUILD_TYPE=Release -GNinja
ninja您可能希望链接到发布版库,我们已通过CMAKE_BUILD_TYPE 变量指定了这一点。现在,只要编译和链接过程均未出现任何错误,我们就应该得到一个已准备好部署的plugandpaint.exe 文件。 要检查应用程序是否包含所需的库,请将可执行文件复制到未安装 Qt 或任何 Qt 应用程序的机器上,并在该机器上运行它。
请注意,如果您的应用程序依赖于特定编译器的库,则必须将这些库与应用程序一并分发。您可以使用depends 工具检查应用程序链接了哪些库。有关更多信息,请阅读“应用程序依赖项”一节。
由于无法使用静态链接方式部署插件,我们准备的应用程序尚不完整。它虽然可以运行,但由于缺少插件,相关功能将被禁用。要部署基于插件的应用程序,应采用共享库方式。
共享库
在使用共享库方法部署plugandpaint 应用程序时,我们面临两个挑战:必须将Qt运行时与应用程序可执行文件一起正确地重新分发,并且必须将插件安装在目标系统上的正确位置,以便应用程序能够找到它们。
将 Qt 构建为共享库
在本示例中,我们假设 Qt 已作为共享库安装(这是安装 Qt 时的默认设置),安装路径为C:\path\to \Qt 目录。
将应用程序链接到作为共享库的 Qt
在确认 Qt 已作为共享库构建后,我们可以构建plugandpaint 应用程序。首先,我们必须进入包含该应用程序的目录:
cd examples\tools\plugandpaint现在创建一个专用的构建目录,并运行qt-cmake 来生成构建系统文件:
md build_shared
cd build_shared
C:\path\to\Qt\bin\qt-cmake .. -DCMAKE_BUILD_TYPE=Release -GNinja
ninja如果编译和链接过程均未出现任何错误,我们将获得一个名为 `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 的二进制软件包并不需要这样做。 如果您在配置 Qt 时指定了特定版本的 ICU 或 OpenSSL,只要这些库的 DLL 文件位于 Qt 的 `[bin] ` 目录中,windeployqt 就会自动识别并使用它们。更多详细信息,请参阅“第三方库”。
请注意,如果您的应用程序依赖于特定编译器的库,则必须随应用程序一起分发这些库。您可以使用depends 工具检查应用程序链接了哪些库。有关更多信息,请参阅“应用程序依赖项”部分。
我们稍后将介绍插件,但首先需要验证应用程序在部署环境中能否正常运行: 将可执行文件和 Qt DLL 文件复制到未安装 Qt 或任何 Qt 应用程序的计算机上;或者,如果您想在构建机器上进行测试,请确保该机器的环境中没有 Qt。
如果应用程序能够正常启动,则说明我们已成功制作了plugandpaint 应用程序的动态链接版本。但由于尚未部署相关的插件,因此应用程序的功能仍不完整。
插件的工作方式与普通 DLL 不同,因此我们不能像处理 Qt DLL 那样,直接将其复制到应用程序可执行文件的同一目录下。在查找插件时,应用程序会在应用程序可执行文件所在目录下的一个名为plugins 的子目录中进行搜索。
因此,为了使应用程序能够使用这些插件,我们必须创建plugins 子目录,并将相关的DLL文件复制到该目录中:
plugins\pnp_basictools.dll
plugins\pnp_extrafilters.dll一个包含运行Plug & Paint应用程序所需的所有 Qt DLL 文件和应用程序专用插件的压缩包,必须包含以下文件:
| 组件 | 文件名 | |
|---|---|---|
| 可执行文件 | plugandpaint.exe | |
| 基本工具插件 | plugins\pnp_basictools.dll | |
| ExtraFilters 插件 | 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 且未安装任何编译器的计算机上解压此存档,并尝试运行它。
除了将插件放置在“plugins”子目录中,另一种方法是在使用QCoreApplication::addLibraryPath() 或QCoreApplication::setLibraryPaths() 启动应用程序时,添加自定义搜索路径。
QCoreApplication::addLibraryPath("C:/some/other/path");使用插件的一个好处是,可以轻松地将其提供给整个应用程序系列使用。
通常最方便的做法是在应用程序的main() 函数中,紧接在创建QApplication 对象之后添加该路径。一旦添加了该路径,应用程序在搜索plugins 子目录(位于应用程序自身目录中)之外,还会在此路径中搜索插件。可以添加任意数量的额外路径。
Windows 应用程序清单生成
在 Windows 上构建时,Qt 会自动为可执行目标生成并嵌入应用程序清单。
生成的清单文件:
- 声明兼容 Windows 10 和 Windows 11
- 启用长路径支持
- 设置应用程序版本(来自
PROJECT_VERSION) - 定义项目标识符
- 配置所需的执行级别
- 禁用默认由链接器生成的清单(
/MANIFEST:NO)
如果目标源文件中已提供自定义的.manifest 文件,Qt 不会覆盖该文件。
声明 Windows 10/11 兼容性将启用现代 Windows 行为,包括:
- 选择启用现代窗口管理器行为
- 支持子窗口的
WS_EX_LAYERED(自 Windows 8 起支持,但受兼容性检测机制限制) - 支持长路径(> 260 个字符)
- 显式执行级别配置
如果没有适当的兼容性声明,Windows 可能会对应用程序应用旧版行为。
默认清单内容
应用程序标识
清单包含一个assemblyIdentity 元素:
<assemblyIdentity
type="win32"
name="com.yourcompany.myapp"
version="1.0.0.0"
processorArchitecture="*" />name— 项目标识符version— 规范化为四部分组成的 Windows 版本号
默认情况下,标识符为:
com.yourcompany.<target_name>可以通过QT_WINDOWS_APP_PROJECT_IDENTIFIER 属性针对每个目标进行覆盖:
set_target_properties(myapp PROPERTIES
QT_WINDOWS_APP_PROJECT_IDENTIFIER "org.example.myapp"
)Windows 应用程序清单要求使用由四部分组成的版本号:
Major.Minor.Build.Revision每个部分必须是 0 到 65535 之间的整数。
该值源自PROJECT_VERSION ,并按以下方式进行标准化:
- 若缺失 → 默认值为
1.0.0.0 - 少于四个分段 → 用零补足
- 分段数超过四个 → 截断
- 值 < 0 → 限制为 0
- 值 > 65535 → 限制为 65535(并发出警告)
示例:
2.3 -> 2.3.0.0
1.2.3.4.5 -> 1.2.3.4
70000.1 -> 65535.1.0.0Windows 兼容性
清单声明支持 Windows 10 和 Windows 11。
<supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}" />{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a} 该 GUID 对应以下操作系统:Windows 10、Windows 11、Windows Server 2016、Windows Server 2019 和 Windows Server 2022。
更多信息请参阅:Microsoft 应用程序清单。
长路径感知
<ws2:longPathAware>true</ws2:longPathAware>在操作系统支持的情况下,允许使用长度超过 260 个字符的文件路径。
执行级别
<requestedExecutionLevel level="asInvoker" uiAccess="false" />默认级别为asInvoker 。
要设置执行级别,请使用QT_WINDOWS_APP_PROJECT_EXECUTION_LEVEL 属性。
有效值:
asInvoker(默认)highestAvailablerequireAdministrator
示例:
set_target_properties(myapp PROPERTIES
QT_WINDOWS_APP_PROJECT_EXECUTION_LEVEL "requireAdministrator"
)如果提供了无效的值,系统将发出警告,并调用asInvoker 。
提供自定义清单
如果可执行文件的源代码中已包含.manifest 文件,Qt 会检测到该清单文件并跳过自动生成:
add_executable(myapp
main.cpp
myapp.manifest
)完整示例
以下示例演示了一个 Windows 可执行文件,该文件使用了自动生成的清单,并自定义了标识符和执行级别:
cmake_minimum_required(VERSION 3.21)
project(MyApp VERSION 2.5.1)
find_package(Qt6 REQUIRED COMPONENTS Core Widgets)
qt_add_executable(MyApp
main.cpp
)
set_target_properties(MyApp PROPERTIES
QT_WINDOWS_APP_PROJECT_IDENTIFIER "org.example.myapp"
QT_WINDOWS_APP_PROJECT_EXECUTION_LEVEL "highestAvailable"
)在此示例中,生成的清单版本将为:
2.5.1.0使用 qmake 生成的清单文件
在部署使用 Visual Studio 编译的应用程序时,需要执行一些额外步骤。
首先,我们需要复制在链接应用程序时生成的清单文件。该清单文件包含有关应用程序对并行组件(如运行时库)依赖关系的信息。
该清单文件需要复制到与应用程序可执行文件相同的文件夹中。共享库(DLL)的清单文件无需复制,因为它们不会被使用。
如果共享库的依赖项与使用它的应用程序不同,则需要将清单文件嵌入到 DLL 二进制文件中。CONFIG 提供了以下选项用于嵌入清单:
embed_manifest_dll
embed_manifest_exe这两个选项默认均已启用。若要移除embed_manifest_exe ,请添加
CONFIG -= embed_manifest_exe到您的 .pro 文件中。
您可以在“并行程序集”文档页面上找到有关清单文件和并行程序集的更多信息。
将运行时库包含在应用程序中的正确方法是确保它们已安装在最终用户的系统上。
要在最终用户的系统上安装运行时库,您需要将相应的 Visual C++ 再分发包 (VCRedist) 可执行文件包含在应用程序中,并确保在用户安装应用程序时执行该文件。
该再分发包名为“vc_redist.x64.exe (64 位)”,位于<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 |
|---|---|---|
|
|
查看插件 DLL 时,列出的依赖项完全相同。
Qt 插件
所有Qt GUI 应用程序都需要一个实现Qt中Qt平台抽象(QPA)层的插件。对于Windows系统,该平台插件的名称为qwindows.dll 。该文件必须位于发行版目录下的特定子目录中(默认位置为platforms )。 此外,也可以按照下文所述,调整 Qt 用于查找插件的搜索路径。
您的应用程序可能还依赖于一个或多个 Qt 插件,例如 Qt Print Support、JPEG 图像格式插件或 Qt SQL 驱动程序插件。 请确保随应用程序一起分发您所需的任何 Qt 插件。与平台插件类似,每种类型的插件都必须位于分发目录下的特定子目录(例如printsupport 、imageformats 或sqldrivers )中。
除非在构建 Qt 时关闭了 `-relocatable ` 配置选项,否则这些库是可重定位的。Qt 插件的搜索路径以 `QtCore ` 库的位置为基准,因此在目标机器上安装应用程序后,无需采取额外步骤即可确保找到插件。
确保在使用非可重定位构建时能找到插件
对于不可重定位的构建,必须采取额外措施,以确保应用程序在目标机器上安装后能够找到插件。
在这种情况下,Qt 插件的搜索路径被硬编码到了QtCore 库中。默认情况下,Qt 安装目录下的 plugins 子目录是第一个插件搜索路径。然而,像默认路径这样的预设路径存在某些弊端。 例如,这些路径在目标机器上可能并不存在。因此,您需要探索各种替代方案,以确保能够找到 Qt 插件:
- 使用 `
qt.conf`。若您有位于不同位置但共享相同插件的可执行文件,建议采用此方法。 - 使用 `QApplication::addLibraryPath()` 或 `QApplication::setLibraryPaths()`。如果您只有一个将使用该插件的可执行文件,则建议采用此方法。
- 使用第三方安装工具来修改QtCore 库中的硬编码路径。
如果您使用 QApplication::addLibraryPath 添加自定义路径,代码可能如下所示:
QCoreApplication::addLibraryPath("C:/customPath/plugins");此时,QCoreApplication::libraryPaths() 函数将返回类似以下的结果:
C:/customPath/pluginsC:/Qt/%VERSION%/pluginsE:/myApplication/directory
可执行文件将按照QCoreApplication::libraryPaths() 返回的QStringList 中的顺序,在这些目录中查找插件。新添加的路径会被添加到QCoreApplication::libraryPaths() 的开头,这意味着该路径将被优先搜索。不过,如果你使用QCoreApplication::setLibraryPaths(),就可以自行决定搜索哪些路径以及它们的搜索顺序。
《如何创建 Qt 插件》文档概述了在为 Qt 应用程序构建和部署插件时需要注意的问题。
© 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.