在Windows上部署Qt 5应用程序

38

我已经用Qt 5 的 QML 写了几个应用程序。在之前的一个问题中 (https://softwareengineering.stackexchange.com/questions/213698/deploying-qt-based-app-on-mac-os-x),我找到了在 OS X 上部署应用程序的解决方案 (使用 macdeployqt 工具)。

在 Windows 上部署 Qt4 应用程序很容易:

  1. 您以发布模式编译它。
  2. 复制必要的库文件 (DLLs)。
  3. 测试并且它能够工作。

不幸的是,这种方法在 Qt5 中不起作用 (我甚至包含了带有 qwindows.dll 文件的 platforms 文件夹也无效)。尝试了几天后,我放弃了并编译了 Qt5 的静态版本。

然而,它仍然没有起作用。该应用程序在安装了 Qt 的 PC 上可以工作,但在“干净”的 PC 上会崩溃。顺便说一下,在 Windows 8/8.1 系统中没有警告或消息通知我应用程序崩溃了。但在 Windows 7 中会有消息通知我应用程序崩溃了。

我尝试了运行 Dependency Walker (depends.exe),静态构建的应用程序中的所有库都好像没问题。

在 Windows 8 中,我没有收到任何错误。但是在使用 depends.exe 对应用程序进行分析后,我得到了一个源自 QtGui.dll 的访问冲突 (access violation)。确切的错误信息是:

Second chance exception 0xC0000005 (Access Violation) occurred in "QT5GUI.DLL" at address 0x61C2C000.

我是否漏掉了什么东西 (比如额外的 DLL 或配置文件)?

应用程序信息:

  • 使用 Qt 5.2.1 编写和编译
  • 使用 Quick / QML。
  • 使用网络模块。
  • 使用 WebKit 模块。
  • 使用蓝牙模块。
  • QML 文件是用 Quick 2.2 编写的。

具体的错误是什么?你是否遇到了崩溃转储(crash dump)?你是否尝试过以某种方式分析该转储? - Michael Kohne
1
确切的错误是“Second chance exception 0xC0000005 (Access Violation) occurred in "QT5GUI.DLL" at address 0x61C2C000.” - Alex Spataru
2
说实话,这真的很糟糕。为什么他们不能只做一个部署按钮就行了呢? - GeneCode
1
它绝对可以,@GeneCode。这就是为什么OP称其为“简单”,因为“必要的DLL文件”任何三岁的孩子都能告诉你一切;-) - dotbit
2
五年过去了,在2020年,部署一款微不足道的Qt应用程序成为了一个更糟糕的噩梦。 - dotbit
显示剩余4条评论
2个回答

40

从Qt 5.2开始,有一个名为windeployqt的工具可用。只需在命令行中运行它即可获取帮助。但是基本用法是,将.exe文件提供给它,它将复制与之相应的Qt依赖项。

您需要使用--qmldir选项让工具知道您的QML文件所在位置,以便它可以找到所需的QML依赖项。

关于测试的说明:为确保您拥有一切内容,请在没有Qt SDK的计算机上进行测试,或者将Qt目录暂时重命名。否则,应用程序可能会从那里找到缺少的文件...


3
我使用了这个工具来部署我的动态应用程序,正如你所说,它在处理QML文件夹时出现了问题。为了解决这个问题,我只需将文件夹复制到<qt-path>/5.2.1/qml中。这样部署的应用程序可以在没有安装Qt SDK的系统上运行。 - Alex Spataru
6
我的 windeployqt.exe v5.7.0 为我生成的32位二进制文件缺少了三个依赖项:libgcc_s_dw2-1.dlllibstdc++-6.dlllibwinpthread-1.dll,我不得不手动从 \Qt\5.7\mingw53_32\bin 中添加它们。 - Neurotransmitter
"windeployqt" 并没有像宣传的那样有效,甚至根本无法使用。也许人们应该坚持使用 Linux 以保持软件正常运行。 - dotbit
@dotbit windeployqt 是一个辅助工具,但你仍然需要知道自己在做什么。在“Linux”上部署肯定不会更容易,你仍然需要知道自己在做什么(特别是如果你需要支持多个不同的发行版)。 - hyde
@dotbit 制作 Windows 安装程序的基本工具(包括可压缩和解压的文件夹)有 Dependency Walker(用于显式静态定义的 DLL 依赖项)和 Process Explorer(用于插件等)。如果您不熟悉它们,请查找相关信息。 - hyde
1
示例,其中mapviewer是我的根目录源代码:windeployqt --qmldir C:\Users\ADMIN\Documents\workspace\map\mapviewer qml_location_mapviewer.exe - nobjta_9x_tq

22

在Qt论坛上翻了几个小时之后,我发现我需要将“qml”文件夹(通常位于C:/Qt/5.2.1/qml)复制到应用程序的根目录中。这样做之后,我的应用程序的动态和静态版本都可以在原始系统上运行。


程序目录(MinGW 4.8 32位,动态):

hyde所说,请使用windeployqt工具(<qt path>\<version>\bin\windeployqt.exe)将必要的文件复制到应用程序文件夹中。之后,从<qt path>\<version>\qml\复制所需的QML组件到您的应用程序文件夹中。最终的文件夹应该类似于:

  • 平台 (文件夹)
  • QtQuick (文件夹)
  • QtQuick.2 (文件夹)
  • 任何其他你需要的 QML 组件
  • app.exe
  • icudt51.dll
  • icuin51.dll
  • icuuc51.dll
  • libgcc_s_dw2-1.dll
  • libstdc++-6.dll
  • libwindthread-1.dll
  • Qt5Core.dll
  • Qt5Gui.dll
  • Qt5Qml.dll
  • Qt5Quick.dll
  • Qt5Network.dll
  • Qt5Widgets.dll

程序目录(静态)

静态编译应用程序,然后将所需的QML组件从 <qt path>\<version>\qml\ 复制到应用程序的文件夹中。生成的文件夹应该类似于:

  • QtQuick(文件夹)
  • QtQuick.2(文件夹)
  • 任何其他你需要的 QML 组件
  • app.exe

我认为崩溃的原因是Qt5Gui.dll(动态和静态)在运行时“尝试”加载QtQuick*文件夹,但找不到它们(因此在加载期间导致应用程序崩溃)。

1
对于静态版本:将所需的 QML 文件包含在 .exe 文件中不是可能的吗? - bobbaluba
我还需要复制C:\Windows\System32\msvcr110d.dll和C:\Windows\System32\msvcp110d.dll,以使调试版本的部署工作正常。(对于发布版本不是必需的,但是添加此注释以防任何人在尝试将调试版本部署到未安装调试运行时的系统时遇到问题。) - wrdieter
2
我发现我需要复制“qml”文件夹。你尝试过使用--qmldir选项吗? - Ilya
新版本如Qt5.7,qml路径类似于<QTDIR>\5.7\msvc2013\qml - zhm
简而言之:由于部署是一门黑魔法,可能会因为月相的原因而起作用或崩溃,即使是一个微不足道的“Hello World”应用程序,至少需要48小时才能完成。 - dotbit

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接