Qt5 CMake 将所有库包含到可执行文件中
Posted
技术标签:
【中文标题】Qt5 CMake 将所有库包含到可执行文件中【英文标题】:Qt5 CMake include all libraries into executable 【发布时间】:2020-03-25 17:48:42 【问题描述】:我正在尝试使用 Qt 5.14 构建一个处于发布模式的应用程序,并且在 Qt Creator 中一切正常,但是当我尝试自行运行可执行文件时,我收到如下错误:
操作系统: Windows 10
Qt: 5.14
Cmake: 3.5
我的尝试:
-
set(CMAKE_EXE_LINKER_FLAGS "-static-libgcc -static-libstdc++ -static")
set(CMAKE_CXX_FLAGS "$CMAKE_CXX_FLAGS -std=c++0x -fPIC")
$ADDITIONAL_LIBRARIES -target_link_libraries 内部的静态
以上方法都不适合我,每当我尝试在不使用 Qt Creator 的情况下自行运行可执行文件时,都会遇到同样的错误。
我的 CMake 文件:
cmake_minimum_required(VERSION 3.5)
project(Scrollable LANGUAGES CXX)
set(CMAKE_INCLUDE_CURRENT_DIR ON)
set(CMAKE_AUTOUIC ON)
set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTORCC ON)
set(CMAKE_EXE_LINKER_FLAGS "-static-libgcc -static-libstdc++ -static")
set(CMAKE_CXX_FLAGS "$CMAKE_CXX_FLAGS -std=c++0x -fPIC")
set(CMAKE_CXX_STANDARD 14)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
find_package(Qt5 REQUIRED Core Widgets Gui Qml Quick Qml)
qt5_add_resources(resource.qrc)
include_directories($CMAKE_CURRENT_SOURCE_DIR)
include_directories("MoviesInterface")
set(SOURCES
main.cpp
MovieInterface/movieinterfaceomdb.cpp
MovieInterface/moviesinterface.cpp
)
set(HEADERS
MovieInterface/movieinterfaceomdb.h
MovieInterface/moviesinterface.h
)
add_executable(Scrollable $SOURCES $HEADERS qml.qrc)
qt5_use_modules(Scrollable Core Network)
target_link_libraries(Scrollable
Qt5::Core
Qt5::Gui
Qt5::Widgets
Qt5::Qml
$ADDITIONAL_LIBRARIES -static
)
【问题讨论】:
其他人已经在本站问过类似的问题,例如this。你试过这些建议吗?通过更新您的Path
或将丢失的 DLL 复制到您的可执行位置,您的问题可能会得到解决。
当然...除了我在 CMake 中的静态链接库和缺少的 DLL 之间没有任何联系,因为我不能只是将该 DLL 复制粘贴到我的构建文件夹中。这表明我没有正确链接库。
您是否重新安装了 Qt5core? ;) 我做了一些测试,在 qt 创建者的 qmake 构建的构建文件夹中成功执行“make all”。然后我更改了所有源文件的路径并将 em 放在 buid 文件夹中 - 工作得非常好,因为所有链接都已由 qmake 完成,并且源代码中的更改通过发出 make all 生效。你可以在 build 文件夹中执行 make all - 它编译吗?
【参考方案1】:
A 你想静态编译。这不适用于 Qt 库和 Mingw 库本身,因为它们也需要静态编译。 但它们仅作为动态链接库分发。
如果您真的想拥有静态可链接的 Qt 库,则需要先静态编译 Qt,然后才能链接它们。有一些关于静态编译 Qt 的描述。但工作量很大。
B为什么找不到Qt5Core.dll:
在 Qt Creator 中,由于编译器/工具链自动检测,您的应用程序的 Qt 库的路径是自动设置的。
但是,当您独立运行应用程序可执行文件时,未设置 Qt 库的路径,并且它们不会驻留在可执行文件旁边的应用程序文件夹中。
为了解决这个问题,我建议使用windeployqt
。
windeployqt 分析您构建的库或可执行文件,并将所需的 Qt 依赖项复制到构建文件夹中。
我倾向于为此使用 cmake 辅助函数。
-
使用以下内容创建
windeployqt.cmake
,并将其放入项目的/cmake
模块文件夹中:
find_package(Qt5Core REQUIRED)
# get absolute path to qmake, then use it to find windeployqt executable
get_target_property(_qmake_executable Qt5::qmake IMPORTED_LOCATION)
get_filename_component(_qt_bin_dir "$_qmake_executable" DIRECTORY)
function(windeployqt target)
# POST_BUILD step
# - after build, we have a bin/lib for analyzing qt dependencies
# - we run windeployqt on target and deploy Qt libs
add_custom_command(TARGET $target POST_BUILD
COMMAND "$_qt_bin_dir/windeployqt.exe"
--verbose 1
--release
--no-svg
--no-angle
--no-opengl
--no-opengl-sw
--no-compiler-runtime
--no-system-d3d-compiler
\"$<TARGET_FILE:$target>\"
COMMENT "Deploying Qt libraries using windeployqt for compilation target '$target' ..."
)
endfunction()
注意 1:--verbose 1
已设置,以便您查看发生了什么。您可以稍后禁用它。
注意 2:请自行处理排除项。我不知道您的应用程序的具体要求,例如如果您需要 OpenGL 或 SVG 支持。
-
然后添加到您的
CMakeLists.txt
:
# Set path to our custom CMAKE scripts
set(CMAKE_MODULE_PATH $CMAKE_MODULE_PATH "$PROJECT_SOURCE_DIR/cmake")
# Include Qt deployment helper function
include(windeployqt)
最后在CMakeLists.txt
末尾添加:
windeployqt(Scrollable)
现在,windeployqt 在您的可执行文件上作为 POST_BUILD 步骤运行,将 qt 库复制到构建文件夹。可执行文件现在将从该文件夹中获取 Qt 依赖项,并且应该能够独立运行(无需设置 Qt 库的路径)。
记住还要复制其他依赖项,例如第三方库或运行时依赖项。
跟进您的 mingw 依赖项:
set(QT_MINGW "/path/to/your/qt/mingw/compiler")
add_custom_command(TARGET Scrollable POST_BUILD
COMMAND $CMAKE_COMMAND -E copy_if_different $QT_MINGW/bin/libgcc_s_dw2-1.dll $<TARGET_FILE_DIR:$TARGET>
COMMAND $CMAKE_COMMAND -E copy_if_different $QT_MINGW/bin/libstdc++-6.dll $<TARGET_FILE_DIR:$TARGET>
COMMAND $CMAKE_COMMAND -E copy_if_different $QT_MINGW/bin/libwinpthread-1.dll $<TARGET_FILE_DIR:$TARGET>
COMMENT "Deploy mingw runtime libraries from $QT_MINGW/bin"
)
【讨论】:
我确实试过了,它几乎可以工作了,只是现在当我构建项目时它失败了,我收到了这个错误消息。Unable to find the platform plugin. mingw32-make.exe[2]: *** [CMakeFiles\Scrollable.dir\build.make:172: Scrollable.exe] Error 1 mingw32-make.exe[2]: *** Deleting file 'Scrollable.exe' mingw32-make.exe[1]: *** [CMakeFiles\Makefile2:76: CMakeFiles/Scrollable.dir/all] Error 2 mingw32-make.exe: *** [Makefile:83: all] Error 2 22:26:33: The process "C:\Qt\Tools\CMake_64\bin\cmake.exe" exited with code 2. Error while building/deploying project Scrollable (kit: Desktop Qt 5.14.1 MinGW 64-bit) When executing step "CMake Build"
好的,好像平台插件没有被复制。它应该在platforms\qwindows.dll
。我也不确定,如果您的应用程序在 exe 文件夹中需要额外的编译器特定(mingw)运行时库。 -- 您可以使用dependencywalker.com 找出您的exe 依赖于什么。然后将这些库复制到文件夹中。
我在 CMakeList.txt 中添加了 target_link_libraries
和 windeployqt(Scrollable)
之间的更新,但无法正常工作,我收到此错误消息:CMake Error at CMakeLists.txt:53 (add_custom_command): Error evaluating generator expression: $<TARGET_FILE_DIR:> Expression syntax not recognized
对不起,我的错:$<TARGET_FILE_DIR:$TARGET
的所有出现都应该是 $<TARGET_FILE_DIR:Scrollable>
【参考方案2】:
跟进您的 mingw 依赖项: ...
如果 Qt 也与 MinGW 一起安装,则只需使用 windeployqt.exe
和 --compiler-runtime
命令行选项,即可避免对 add_custom_command
内的运行时库进行额外的复制操作。
【讨论】:
以上是关于Qt5 CMake 将所有库包含到可执行文件中的主要内容,如果未能解决你的问题,请参考以下文章
使用 CMake 将 Qt DLL 复制到 Windows 上的可执行目录