如何按标签而非目标名称自动链接多个对象库?
CMake自动链接带特定标签的对象库
针对对象库频繁变动、不想手动逐个链接的问题,推荐两种更可靠的CMake方案,完全避开全局变量的依赖顺序和出错风险:
方案一:自定义目标属性+批量链接函数
利用CMake的目标属性机制给对象库打标签,再通过自定义函数批量筛选并链接符合条件的目标:
- 定义自定义标签属性
在项目根目录的CMakeLists开头,声明用于标记对象库的自定义属性:
define_property(TARGET PROPERTY OBJECT_LIBRARY_TAG BRIEF_DOCS "Tag for grouping object libraries" FULL_DOCS "Used to mark object libraries that should be automatically linked to certain targets" )
- 给对象库打标签
每个对象库定义时,通过set_target_properties设置标签:
add_library(obj_feature1 OBJECT feature1.cpp) set_target_properties(obj_feature1 PROPERTIES OBJECT_LIBRARY_TAG "core_modules") add_library(obj_feature2 OBJECT feature2.cpp) set_target_properties(obj_feature2 PROPERTIES OBJECT_LIBRARY_TAG "core_modules")
- 编写批量链接函数
写一个可复用的函数,自动收集所有带指定标签的对象库并链接到目标:
function(target_link_tagged_objects target tag) # 获取当前目录下所有已定义的目标 get_property(all_targets DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY BUILDSYSTEM_TARGETS) foreach(tgt IN LISTS all_targets) # 检查目标是否是对象库,且带有指定标签 get_target_property(tgt_type ${tgt} TYPE) if(tgt_type STREQUAL "OBJECT_LIBRARY") get_target_property(tgt_tag ${tgt} OBJECT_LIBRARY_TAG) if(tgt_tag STREQUAL "${tag}") target_link_libraries(${target} PRIVATE ${tgt}) endif() endif() endforeach() endfunction()
- 在静态/动态库中使用
调用函数传入目标和标签,即可自动链接所有匹配的对象库:
add_library(my_static_lib STATIC main.cpp) target_link_tagged_objects(my_static_lib "core_modules")
方案二:INTERFACE聚合库+自定义宏
用INTERFACE库作为带标签对象的聚合容器,通过自定义宏自动将新对象库加入聚合库,静态/动态库只需链接一次聚合库:
- 创建INTERFACE聚合库
定义一个INTERFACE库,用于承载所有带指定标签的对象库:
add_library(core_object_modules INTERFACE)
- 自定义宏添加带标签的对象库
写一个宏替代add_library,自动将新创建的对象库加入聚合库:
macro(add_tagged_object_library name) add_library(${name} OBJECT ${ARGN}) target_link_libraries(core_object_modules INTERFACE ${name}) endmacro()
- 用宏创建对象库
后续新增对象库时,直接用这个宏,无需手动添加到聚合库:
add_tagged_object_library(obj_feature1 feature1.cpp) add_tagged_object_library(obj_feature2 feature2.cpp)
- 链接聚合库到静态/动态库
静态/动态库只需链接一次INTERFACE聚合库,就能自动包含所有关联的对象库:
add_library(my_static_lib STATIC main.cpp) target_link_libraries(my_static_lib PRIVATE core_object_modules)
方案对比
- 方案一更适合已有大量对象库的存量项目,无需修改对象库的创建方式,只需补加标签属性即可;
- 方案二更适合新项目,通过宏统一管理对象库的创建和标签,结构更清晰,维护成本更低。
两种方案都完全避免了全局变量的弊端,依赖CMake自身的目标依赖管理机制,不会出现顺序错误或遗漏问题。
内容的提问来源于stack exchange,提问作者Richard W
相关产品推荐
相关产品推荐

