我使用以下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的insallation文件夹中手动复制这些库,则它可以正常工作(好的,关于“平台插件窗口”的错误,这是另一个错误)。
有没有一种以标准方式复制icu库的方法,例如我用于复制库的post build命令?或者,如果可能的话,以透明方式复制它们的最佳方法是什么(CMake可以知道Qt的依赖项是什么,并在需要Qt的地方复制它们)?
最佳答案
无需手动复制每个dll,您可以使用Qt附带的用于安装在Windows上的工具windeployqt
安装所有Qt依赖项。
您可以首先将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()