将 cmake 项目与 Qt5 链接时部署 icu 库

Deploy icu libraries when linking a cmake project with Qt5

我有以下 CMakeLists.txt 用于创建一个小应用程序:

cmake_minimum_required (VERSION 3.5.0)

project (sampleapp)

# Setting project flags
set (CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/build/lib)
set (CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/build/lib)
set (CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/build/bin)
set (CMAKE_INCLUDE_CURRENT_DIR ON)
set (CMAKE_AUTOMOC ON)

# Finding needed packages
find_package (Qt5Widgets REQUIRED)
find_package (Qt5Core REQUIRED)
find_package (Qt5Gui REQUIRED)

# Setting project files
include_directories (${CMAKE_SOURCE_DIR}/src ${CMAKE_CURRENT_SOURCE_DIR})
file (GLOB_RECURSE PROJECT_SRC *.cpp)

# Creating project
add_executable(${PROJECT_NAME} ${PROJECT_SRC})

# Linking dependencies
target_link_libraries (${PROJECT_NAME} somelibrary Qt5::Widgets Qt5::Gui Qt5::Core)
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_command(TARGET ${PROJECT_NAME} POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy_if_different $<TARGET_FILE:Qt5::Gui> $<TARGET_FILE_DIR:${PROJECT_NAME}>)
add_custom_command(TARGET ${PROJECT_NAME} POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy_if_different $<TARGET_FILE:Qt5::Core> $<TARGET_FILE_DIR:${PROJECT_NAME}>)

当我 运行 它然后构建应用程序时,Qt dll 被复制到目标文件夹中。特别是我复制:

当我 运行 应用程序时,它无论如何都不会启动,因为没有复制 Qt 所需的 ICU 库。当我启动应用程序时,Windows 告诉我缺少以下库:

如果我从 Qt 安装文件夹中手动复制这些库,它会起作用(好的,我有一个关于 "platform plugins windows" 丢失的错误,但这是另一回事)。

有没有办法以标准方式复制 icu 库,例如我用于复制库的 post 构建命令?或者如果可能的话,以透明方式复制它们的最佳方法是什么(CMake 可以知道 Qt 的依赖项并将它们复制到需要 Qt 的地方)?

无需手动复制每个 dll,您可以使用 windeployqt 安装所有 Qt 依赖项,该工具随 Qt 一起提供,用于在 Windows 上进行部署。

您可以先将 windeployqt 声明为导入的可执行文件:

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)
    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:foo>"
    )

    install(
        DIRECTORY
        "${CMAKE_CURRENT_BINARY_DIR}/windeployqt/"
        DESTINATION ${FOO_INSTALL_RUNTIME_DESTINATION}
    )
endif()