在构建时部署所有Qt依赖项

Jep*_*sen 7 windows deployment qt 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}>)
Run Code Online (Sandbox Code Playgroud)

项目构建并将文件add_custom_command复制Qt5Widgets.dll到输出目录.但是当我尝试运行该程序时,我收到以下错误:

此应用程序无法启动,因为它无法在""中找到或加载Qt平台插件"windows".

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

我怎么能在我的CMakeLists.txt文件中这样做?

was*_*ful 10

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
Run Code Online (Sandbox Code Playgroud)

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()
Run Code Online (Sandbox Code Playgroud)

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

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()
Run Code Online (Sandbox Code Playgroud)

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


请注意,GLOBCMake的文档中不建议使用收集源文件:

我们不建议使用GLOB从源树中收集源文件列表.如果在添加或删除源时没有更改CMakeLists.txt文件,则生成的构建系统无法知道何时请求CMake重新生成.


如果您使用的是Visual C++,您可能还希望通过在CMakeLists.txt文件末尾添加以下代码来安装可视的可再发行组件:

set(CMAKE_INSTALL_SYSTEM_RUNTIME_LIBS_SKIP TRUE)

include(InstallRequiredSystemLibraries)

install(
    PROGRAMS ${CMAKE_INSTALL_SYSTEM_RUNTIME_LIBS}
    DESTINATION ${FOO_INSTALL_RUNTIME_DESTINATION}
)
Run Code Online (Sandbox Code Playgroud)

您可以查看我的一个名为Softbloks的项目,以便完整且有效地集成windeployqtInstallRequiredSystemLibraries.