在cmake中直接配置windeploy.exe拷贝qt的动态库,可能会遇到有些模块在find_package配置了,而当前模块并没有使用的问题。那么用windeploy.exe拷贝的时候,会遗漏需要的qt库。
解决方法:
# qt_helper.cmake
# 根据find_package拷贝所需要的qt库(目标文件未依赖的)
# 根据组件名获取库文件的目标
function(get_qt_library_target component_name target_var)
if (TARGET Qt5::${component_name})
set(${target_var} Qt5::${component_name} PARENT_SCOPE)
elseif (TARGET Qt6::${component_name})
set(${target_var} Qt6::${component_name} PARENT_SCOPE)
else()
message(FATAL_ERROR "Unknown Qt component: ${component_name}")
endif()
endfunction()
# 项目使用
function(deployqt_qt_runtime arg_target)
get_target_property(qt_qmake_executable Qt5::qmake IMPORTED_LOCATION)
get_filename_component(qt_bin_directory "${qt_qmake_executable}" DIRECTORY)
find_program(qt_deployqt_executable NAMES windeployqt macdeployqt HINTS "${qt_bin_directory}")
if (NOT EXISTS "${qt_deployqt_executable}")
message("can not find the deployqt tools")
return()
endif ()
# 获取组件参数列表
# ${ARGN}是一个内置变量,表示传递给函数或宏的所有未命名参数
set(qt_components ${ARGN})
if (WIN32)
add_custom_command(TARGET ${arg_target} POST_BUILD COMMAND
"${qt_deployqt_executable}"
--libdir "$<TARGET_FILE_DIR:${arg_target}>"
--plugindir "$<TARGET_FILE_DIR:${arg_target}>"
--no-translations
--no-compiler-runtime
--no-system-d3d-compiler
--no-opengl-sw
--no-angle
--no-webkit2
$<$<CONFIG:Debug>:--pdb>
"$<TARGET_FILE:${arg_target}>"
)
# 根据find_package后面的component拷贝需要的动态库(防止遗漏)
foreach (component IN LISTS qt_components)
get_qt_library_target(${component} qt_component_target)
add_custom_command(TARGET ${arg_target} POST_BUILD COMMAND
${CMAKE_COMMAND} -E copy_if_different
"$<TARGET_FILE:${qt_component_target}>"
"$<TARGET_FILE_DIR:${arg_target}>"
)
endforeach()
endif ()
endfunction()
使用:
- 项目根目录的CMakeLists.txt:
cmake_minimum_required(VERSION 3.21)
project(XXXX)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTORCC ON)
set(CMAKE_AUTOUIC ON)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
set(Qt5_DIR /opt/homebrew/Cellar/qt@5/5.15.8_2/lib/cmake/Qt5)
if(MSVC)
add_compile_options("/utf-8")
add_definitions(-DUNICODE -D_UNICODE)
add_compile_options(/MP)
endif ()
set(qt_required_components Core Widgets Gui OpenGL Svg Xml Sql Network Charts)
find_package(Qt5 COMPONENTS ${qt_required_components} LinguistTools REQUIRED)
# 添加自己创建的cmake函数
include(qt_helper.cmake)
- 子模块(需要
add_library
或者add_execute
的地方):
add_library(${PROJECT_NAME} SHARED
XXXX.h
)
target_link_libraries(${PROJECT_NAME}
Qt5::Core Qt5::Widgets Qt5::Network
)
# 直接在文件最后加上这行就行
deployqt_qt_runtime(${PROJECT_NAME} ${qt_required_components})
cmake ${ARGN}
内置函数说明:
在CMake中,${ARGN}
是一个内置变量,表示传递给函数或宏的所有未命名参数。这些参数以列表的形式存储在变量中,可以用于循环、字符串操作等。要使用 ${ARGN}
处理传递给函数的参数,请参考以下示例:
function(example_function)
# 获取未命名参数
set(extra_args ${ARGN})
# 使用未命名参数
foreach(arg IN LISTS extra_args)
message("Argument: ${arg}")
endforeach()
endfunction()
# 调用 example_function
example_function(arg1 arg2 arg3)
在这个示例中,example_function()
函数使用 ${ARGN}
变量获取所有传递给它的未命名参数。然后,它遍历这些参数并打印出它们。在这种情况下,输出将是:
Argument: arg1
Argument: arg2
Argument: arg3
您可以在自己的CMake函数中使用类似的方法处理 ${ARGN}
中的参数。