CMake如何在安装时将生成产物放置在目标文件旁?
解决CMake中随目标同步安装自定义生成文件的问题
核心问题分析
构建阶段用$<TARGET_FILE_DIR:${target}>能拿到目标文件的构建路径,但安装时需要的是目标最终被部署的目录,直接复用构建路径会导致安装路径错误。关键在于动态获取目标的安装目录属性,而非依赖构建时的路径。
实现方案
通过CMake生成器表达式(Generator Expression)延迟解析目标的安装目录,配合install(FILES)命令实现自定义产物与目标的同步安装。以下是完整的make_artifact函数实现:
function(make_artifact target) # 1. 构建阶段生成.artifact文件到目标的构建目录 add_custom_command( TARGET ${target} POST_BUILD COMMAND ${CMAKE_COMMAND} -E touch "$<TARGET_FILE_DIR:${target}>/${target}.artifact" COMMENT "Generating ${target}.artifact" VERBATIM ) # 2. 根据目标类型匹配对应的安装目录属性 get_target_property(target_type ${target} TYPE) if(target_type STREQUAL "EXECUTABLE") set(destination_property RUNTIME_DESTINATION) elseif(target_type MATCHES "^(SHARED|MODULE)_LIBRARY$") set(destination_property LIBRARY_DESTINATION) elseif(target_type STREQUAL "STATIC_LIBRARY") set(destination_property ARCHIVE_DESTINATION) else() # 未知类型默认沿用可执行文件的安装属性规则 set(destination_property RUNTIME_DESTINATION) endif() # 3. 安装.artifact文件到与目标相同的目录 # 用生成器表达式延迟解析,确保能获取后续设置的安装路径 install( FILES "$<TARGET_FILE_DIR:${target}>/${target}.artifact" DESTINATION "$<IF:$<TARGET_PROPERTY:${target},${destination_property}>, $<TARGET_PROPERTY:${target},${destination_property}>, $<IF:$<STREQUAL:${target_type},EXECUTABLE>, bin, lib>>" COMPONENT $<TARGET_PROPERTY:${target},INSTALL_COMPONENT> OPTIONAL ) endfunction()
关键细节说明
- 生成器表达式的优势:
$<TARGET_PROPERTY:${target},${destination_property}>会在CMake生成构建系统(如Makefile、VS项目)时才解析,即使你在调用make_artifact之后才执行install(TARGETS)设置安装目录,也能正确获取目标的最终安装路径。 - 目标类型适配:不同类型的目标(可执行文件、共享库、静态库)对应不同的安装目录属性,确保安装路径和CMake的默认安装规则一致。
- 默认目录兜底:如果用户未显式设置目标的安装目录,会自动根据目标类型使用
bin(可执行文件)或lib(库文件)作为默认安装目录。 - 组件同步:
COMPONENT参数同步使用目标的安装组件,确保分组件安装时,.artifact文件和目标属于同一组件。
使用示例
# 定义可执行目标 add_executable(my_app main.cpp) # 生成对应的.artifact文件 make_artifact(my_app) # 设置目标的安装目录 install(TARGETS my_app DESTINATION bin)
执行make install后,my_app.artifact会和my_app一起被安装到${CMAKE_INSTALL_PREFIX}/bin目录下。
内容的提问来源于stack exchange,提问作者Jacob Faib
相关产品推荐
相关产品推荐

