将 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 被复制到目标文件夹中。特别是我复制:
Qt5Core.dll
Qt5Gui.dll
Qt5Widgets.dll
当我 运行 应用程序时,它无论如何都不会启动,因为没有复制 Qt 所需的 ICU 库。当我启动应用程序时,Windows 告诉我缺少以下库:
icuin53.dll
icuuc53.dll
如果我从 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()
我有以下 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 被复制到目标文件夹中。特别是我复制:
Qt5Core.dll
Qt5Gui.dll
Qt5Widgets.dll
当我 运行 应用程序时,它无论如何都不会启动,因为没有复制 Qt 所需的 ICU 库。当我启动应用程序时,Windows 告诉我缺少以下库:
icuin53.dll
icuuc53.dll
如果我从 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()