c++ 如何将Qt运行时DLL复制到项目输出

ohtdti5x  于 2023-04-08  发布在  其他
关注(0)|答案(5)|浏览(208)

我在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日:**只是为了澄清,上面的帖子是关于Qt 4的。在Qt 5上,你应该考虑调用windeployqt。这个Qt 5工具将读取你的二进制文件,确定你需要哪些Qt 5运行时文件,并将它们复制到你的二进制目录。还要注意的是,它将修复特定于你的PC的Qt 5::Core库中的绝对路径-所以除非你想自己提供一个qt.conf文件,否则基本上必须使用这个工具。

wtlkbnrh

wtlkbnrh1#

好吧,这里有一个丑陋的黑客:

# 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之类的东西会更合适,但由于某种原因我不能让它工作。
  • 硬编码的“调试”和“发布”名称;似乎应该有某种变量来实现。
  • 使用“copy”命令调用环境。

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

k4emjkb1

k4emjkb12#

一个更干净的方法,但它需要在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中结束。

mf98qq94

mf98qq943#

使用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

mec1mxoz

mec1mxoz4#

我遇到了同样的问题,jwernerny's solution帮了我很大的忙。但是,我在Window 7上使用的是Shadow Build,它需要更多的tweeking。
我还需要根据当前配置设置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来获取输出文件夹。

ukdjmx9f

ukdjmx9f5#

一个冗长但清晰的例子:

find_package(Qt5 CONFIG COMPONENTS Widgets REQUIRED)
if (WIN32)
    MESSAGE("Copying dlls...")
    set(QtBin ${Qt5Core_DIR}/../../../bin)
    if (${CMAKE_BUILD_TYPE} STREQUAL Debug)
        file(COPY ${QtBin}/Qt5Cored.dll DESTINATION ${CMAKE_BINARY_DIR})
        file(COPY ${QtBin}/Qt5Widgetsd.dll DESTINATION ${CMAKE_BINARY_DIR})
        file(COPY ${QtBin}/Qt5Guid.dll DESTINATION ${CMAKE_BINARY_DIR})
    else ()
        file(COPY ${QtBin}/Qt5Core.dll DESTINATION ${CMAKE_BINARY_DIR})
        file(COPY ${QtBin}/Qt5Widgets.dll DESTINATION ${CMAKE_BINARY_DIR})
        file(COPY ${QtBin}/Qt5Gui.dll DESTINATION ${CMAKE_BINARY_DIR})
    endif ()
endif ()

相关问题