windows - 构建时部署所有 Qt 依赖项

标签 windows qt deployment cmake qt5

我创建了一个 CMakeLists.txt 用于创建一个简单的 Qt 应用程序(实际上它只有一个文件 main.cpp 显示一个空的主窗口):

cmake_minimum_required (VERSION 3.7.0)

project(guitest)

set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib)
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
set(CMAKE_INCLUDE_CURRENT_DIR ON)
set(CMAKE_AUTOMOC ON)

find_package(Qt5Widgets REQUIRED)
include_directories (${CMAKE_SOURCE_DIR}/src ${CMAKE_CURRENT_SOURCE_DIR})
file (GLOB_RECURSE WSIMGUI_SRC *.cpp)

add_executable(${PROJECT_NAME} ${WSIMGUI_SRC})
target_link_libraries(${PROJECT_NAME} Qt5::Widgets)
add_custom_command(TARGET ${PROJECT_NAME} POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy_if_different $<TARGET_FILE:Qt5::Widgets> $<TARGET_FILE_DIR:${PROJECT_NAME}>)

项目构建和 add_custom_commandQt5Widgets.dll 文件复制到输出目录。但是当我尝试运行该程序时,出现以下错误:

This application failed to start because it could not find or load the Qt platform plugin "windows" in "".

我一直在寻找这个问题,我注意到我还必须从我的 Qt 安装中复制 platform 文件夹。

如何在我的 CMakeLists.txt 文件中执行此操作?

最佳答案

Qt 提供了在 Windows 上部署依赖项的实用程序:windeployqt .

鉴于您的 Qt 安装位于 <qt_install_prefix> ,您应该使用以下命令:

set PATH=%PATH%;<qt_install_prefix>/bin
windeployqt --dir /path/to/deployment/dir /path/to/qt/application.exe

灵活的使用方式windeployqt使用CMake是先声明一个导入的目标:

find_package(Qt5 ...)

if(Qt5_FOUND AND WIN32 AND TARGET Qt5::qmake AND NOT TARGET Qt5::windeployqt)
    get_target_property(_qt5_qmake_location Qt5::qmake IMPORTED_LOCATION)

    execute_process(
        COMMAND "${_qt5_qmake_location}" -query QT_INSTALL_PREFIX
        RESULT_VARIABLE return_code
        OUTPUT_VARIABLE qt5_install_prefix
        OUTPUT_STRIP_TRAILING_WHITESPACE
    )

    set(imported_location "${qt5_install_prefix}/bin/windeployqt.exe")

    if(EXISTS ${imported_location})
        add_executable(Qt5::windeployqt IMPORTED)

        set_target_properties(Qt5::windeployqt PROPERTIES
            IMPORTED_LOCATION ${imported_location}
        )
    endif()
endif()

然后您可以按如下方式使用它:

add_executable(foo ...)

if(TARGET Qt5::windeployqt)
    # execute windeployqt in a tmp directory after build
    add_custom_command(TARGET foo
        POST_BUILD
        COMMAND ${CMAKE_COMMAND} -E remove_directory "${CMAKE_CURRENT_BINARY_DIR}/windeployqt"
        COMMAND set PATH=%PATH%$<SEMICOLON>${qt5_install_prefix}/bin
        COMMAND Qt5::windeployqt --dir "${CMAKE_CURRENT_BINARY_DIR}/windeployqt" "$<TARGET_FILE_DIR:foo>/$<TARGET_FILE_NAME:foo>"
    )

    # copy deployment directory during installation
    install(
        DIRECTORY
        "${CMAKE_CURRENT_BINARY_DIR}/windeployqt/"
        DESTINATION ${FOO_INSTALL_RUNTIME_DESTINATION}
    )
endif()

这可以(应该?)嵌入到 cmake 函数中。


请注意,使用 GLOB CMake's doc 不鼓励收集源文件:

We do not recommend using GLOB to collect a list of source files from your source tree. If no CMakeLists.txt file changes when a source is added or removed then the generated build system cannot know when to ask CMake to regenerate.


如果您使用的是 Visual C++,您可能还想通过在 CMakeLists.txt 的末尾添加以下代码来安装 visual redistributable文件:

set(CMAKE_INSTALL_SYSTEM_RUNTIME_LIBS_SKIP TRUE)

include(InstallRequiredSystemLibraries)

install(
    PROGRAMS ${CMAKE_INSTALL_SYSTEM_RUNTIME_LIBS}
    DESTINATION ${FOO_INSTALL_RUNTIME_DESTINATION}
)

你可以看看我的一个项目,名为Softbloks , 用于 windeployqt 的完整和有效集成和 InstallRequiredSystemLibraries .

关于windows - 构建时部署所有 Qt 依赖项,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41193584/

相关文章:

c# - 无法从命令行或调试器启动服务

c++ - 解析文件路径的最佳方法是什么?

ruby - Windows 7 上 Ruby 和 Rails 的最佳环境?

java - 计划任务不会在夜间的特定时间运行

ruby - 使用 Passenger 部署轨道

reactjs - 尝试将 React 应用程序部署到 heroku 时出现错误

c++ - Qt 和 openGL 的 gluPerspective 等价物

c++ - 在 C++ 中显示 FEM 数据

c++ - 如何从 qml 访问 qabstractlistmodel 派生类对象作为另一个类的属性?

azure - 无法让机器人在 Azure 中从 vs 发布中工作