【问题标题】:How to copy Qt runtime DLLs to project output如何将 Qt 运行时 DLL 复制到项目输出
【发布时间】:2012-01-13 14:03:44
【问题描述】:

我在 Qt Creator 中创建了一个简单的项目(使用 Qt SDK 1.1.4 安装)。它在 Qt Creator 中运行得很好,但是如果我随后浏览到 Windows 中的输出目录并双击 EXE,我会收到如下错误:

The program can't start because QtCored4.dll is missing from your computer.
Try reinstalling the program to fix this problem.

这显然是因为 Qt 不在我的 PATH 中(而且我不希望它在我的计算机上,以防我的计算机上有多个版本的 Qt),并且 Qt Creator / qmake 没有将 Qt DLL 复制到项目输出。

我想做的是使用 qmake 将必要的 Qt 文件复制到项目输出目录 - 无论它在哪里。我该怎么做?

(我尝试在 qmake 中创建自定义目标,但我并没有走得太远......)

2016 年 7 月 19 日更新: 澄清一下,上面的帖子是关于 Qt4 的。在 Qt5 上,您应该考虑调用 windeployqt。这个 Qt5 工具将读取您的二进制文件,确定您需要哪些 Qt5 运行时文件,并将它们复制到您的二进制目录中。另请注意,它将修复 Qt5::Core 库中特定于您的 PC 的绝对路径 - 因此,除非您想自己提供 qt.conf 文件,否则基本上必须使用此工具。

【问题讨论】:

  • 天哪,我现在正在努力寻找解决方案
  • Ali Foroughi 类似问题:stackoverflow.com/questions/8391924/…
  • @AlessandroPezzato:我们想要的是让 qmake 自动复制这些 DLL 来构建输出,所以我们不必手动完成。
  • 复制调试 dll 并没有多大用处 :)
  • 为什么要在 IDE 之外运行调试版本?

标签: c++ qt qt4 qt-creator qmake


【解决方案1】:

好的,这是一个丑陋的 hack:

# Copy required DLLs to output directory
CONFIG(debug, debug|release) {
    QtCored4.commands = copy /Y %QTDIR%\\bin\\QtCored4.dll debug
    QtCored4.target = debug/QtCored4.dll
    QtGuid4.commands = copy /Y %QTDIR%\\bin\\QtGuid4.dll debug
    QtGuid4.target = debug/QtGuid4.dll

    QMAKE_EXTRA_TARGETS += QtCored4 QtGuid4
    PRE_TARGETDEPS += debug/QtCored4.dll debug/QtGuid4.dll
} else:CONFIG(release, debug|release) {
    QtCore4.commands = copy /Y %QTDIR%\\bin\\QtCore4.dll release
    QtCore4.target = release/QtCore4.dll
    QtGui4.commands = copy /Y %QTDIR%\\bin\\QtGui4.dll release
    QtGui4.target = release/QtGui4.dll

    QMAKE_EXTRA_TARGETS += QtCore4 QtGui4
    PRE_TARGETDEPS += release/QtCore4.dll release/QtGui4.dll
} else {
    error(Unknown set of dependencies.)
}

以下是我不喜欢的一些地方:

  • 使用 %QTDIR% 环境变量;在实际运行复制命令之前,不会评估此变量。看起来像QMAKE_LIBS_QT_DLL 这样的东西会更合适,但由于某种原因我无法让它工作。
  • 硬编码的“调试”和“发布”名称;似乎应该有某种变量可以用于此。
  • 使用“复制”命令调用环境。

如果有人可以很好地解决这个问题,我会接受另一个答案,例如通过缩短它和/或解决我的一些问题,或者只是找到一个更好的方法。

【讨论】:

  • $$QMAKE_LIBDIR_QT 似乎是 %QTDIR%\\bin 的正确替代品。
  • 更新:$$QMAKE_LIBDIR_QT 不适用于我们的一位开发人员。我们切换到 $$[QT_INSTALL_BINS],由“qmake -query”指向。
  • 另外,使用 $$QMAKE_COPY、$$QMAKE_DIR_SEP 和 $$QMAKE_EXTENSION_SHLIB 可以使这个跨平台。
  • 我发现有时我需要重新启动才能修复偶尔发生的一些奇怪的 qmake 错误。错误发生在 100% 的时间?别管它,回来,现在它可以工作了-_- ...
  • 您可以随时参考相关 mkespec 目录中的配置文件。只是不要忘记查看common/ 文件夹:)
【解决方案2】:

一种更简洁的方法,但它需要在make 之后执行make install。它可以在 Windows 上运行,但需要针对其他平台进行调整。

debug { DESTDIR = debug }
release { DESTDIR = release }
debug_and_release { DESTDIR = bin }

myqtlibs.path = $$DESTDIR
myqtlibs.files = $$QMAKE_LIBDIR_QT/*.dll junk.txt fred.out
myqtlibs.CONFIG = no_check_exist

INSTALLS += myqtlibs

如果 qmake 只是为了调试而运行,所有输出都将进入 ./debug 。如果仅用于发布,则所有输出都进入 ./release 。如果两者都有,则进入 ./bin 。

我确实注意到在 QtCreator 中启用影子构建会导致可执行文件不会最终出现在 DESTDIR 中。我不太清楚为什么。

【讨论】:

    【解决方案3】:

    使用 windeployqt 复制依赖项

    # Deployment - Automatically Detect and Copy Dependencies to Build Folder
    
    TARGET_CUSTOM_EXT = .exe
    DEPLOY_COMMAND = windeployqt
    
    DEPLOY_OPTIONS = "--no-svg --no-system-d3d-compiler --no-opengl --no-angle --no-opengl-sw"
    
    CONFIG( debug, debug|release ) {
        # debug
        DEPLOY_TARGET = $$shell_quote($$shell_path($${OUT_PWD}/debug/$${TARGET}$${TARGET_CUSTOM_EXT}))
        DEPLOY_OPTIONS += "--debug"
    } else {
        # release
        DEPLOY_TARGET = $$shell_quote($$shell_path($${OUT_PWD}/release/$${TARGET}$${TARGET_CUSTOM_EXT}))
        DEPLOY_OPTIONS += "--release"
    }
    
    # Uncomment the following line to help debug the deploy command when running qmake
    #message($${DEPLOY_COMMAND} $${DEPLOY_OPTIONS} $${DEPLOY_TARGET})
    
    QMAKE_POST_LINK = $${DEPLOY_COMMAND} $${DEPLOY_OPTIONS} $${DEPLOY_TARGET}
    

    手动复制依赖项

    # Deployment - Copy Dependencies to Build Folder
    
    dlls.path  =  $${DESTDIR}
    dlls.files += $$[QT_INSTALL_BINS]/icudt51.dll
    dlls.files += $$[QT_INSTALL_BINS]/icuin51.dll
    dlls.files += $$[QT_INSTALL_BINS]/icuuc51.dll
    dlls.files += $$[QT_INSTALL_BINS]/libgcc_s_dw2-1.dll
    dlls.files += $$[QT_INSTALL_BINS]/libstdc++-6.dll
    dlls.files += $$[QT_INSTALL_BINS]/libwinpthread-1.dll
    dlls.files += $$[QT_INSTALL_BINS]/Qt5Core.dll
    dlls.files += $$[QT_INSTALL_BINS]/Qt5Network.dll
    dlls.files += $$[QT_INSTALL_BINS]/Qt5Gui.dll
    dlls.files += $$[QT_INSTALL_BINS]/Qt5Widgets.dll
    dllA.path   += $${DESTDIR}/platforms
    dllA.files  += $$[QT_INSTALL_PLUGINS]/platforms/qwindows.dll
    dllB.path   += $${DESTDIR}/plugins/imageformats/
    dllB.files  += $$[QT_INSTALL_PLUGINS]/imageformats/qico.dll
    dllB.files  += $$[QT_INSTALL_PLUGINS]/imageformats/qwbmp.dll
    INSTALLS   += dlls dllA dllB
    

    参考:http://doc.qt.io/qt-5/qmake-variable-reference.html#deployment


    如果您需要确定跨平台的先决条件/依赖项,请查看 CMake 的 getPrerequisites()。它使用dumpbinobjbinlddotool来识别依赖关系。

    参考:https://cmake.org/cmake/help/v3.0/module/GetPrerequisites.html

    【讨论】:

    • 在为多个平台制作时,是否有通用/占位符方式可以做到这一点?比如DEPLOY_COMMAND = *deploy,还是这些都需要单独/明确指定?
    • 不适用于 Qt 板载工具。但例如使用 CMake,您可以使用 getPrerequisites()。它使用dumpbinobjbinlddotool(跨平台)来识别依赖关系。见cmake.org/cmake/help/v3.0/module/GetPrerequisites.html
    • 不错!谢谢@Jens A. Koch!
    【解决方案4】:

    我遇到了同样的问题,jwernerny's solution 帮了我很多忙。但是,我在 Window 7 上使用 Shadow Build,它需要更多的调整。

    我还需要根据当前配置设置DESTDIR

    就我而言,我想复制 *.qml 文件,这就是我实现它的方法:

    CONFIG(release, debug|release): DESTDIR = $$OUT_PWD/release
    CONFIG(debug, debug|release): DESTDIR = $$OUT_PWD/debug
    
    QmlFiles.path = $$DESTDIR/Qml
    QmlFiles.files += $$files(Qml/*.qml)
    
    INSTALLS += QmlFiles
    

    编辑:

    由于我使用 Shadow Build,我需要使用 $$OUT_PWD 来获取输出文件夹。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-05-13
      • 1970-01-01
      • 2017-05-04
      • 2021-11-07
      • 1970-01-01
      • 2010-12-19
      相关资源
      最近更新 更多