如何在CMake中检查目标依赖是否已导出?解决导出报错
解决CMake导出目标时依赖未导出的条件判断问题
当你尝试导出依赖其他目标的CMake目标(如示例中的Bar依赖Foo)时,如果依赖目标未被导出,会触发错误:export called with target "Bar" which requires target "Foo" that is not in any export set。要实现仅当Bar的所有依赖目标都已导出时才执行导出,可以通过以下步骤实现:
核心思路
- 收集Bar目标的所有链接依赖(包括PRIVATE、PUBLIC、INTERFACE范围的);
- 过滤出当前项目中的非导入目标(系统库、外部导入目标无需检查);
- 逐个检查这些依赖目标是否已被导出(通过CMake内部属性
_EXPORT_SET判断); - 若所有依赖都已导出,再执行
export命令导出Bar。
具体实现代码
project(sample) add_library(Foo foo.cpp foo.h) add_library(Bar bar.cpp bar.h) target_link_libraries(Bar Foo) # 先导出Foo(模拟依赖已导出的场景) export(TARGETS Foo FILE "${CMAKE_CURRENT_BINARY_DIR}/FooTargets.cmake") # -------------------------- 条件判断逻辑 -------------------------- # 收集Bar的所有链接依赖 set(Bar_DEPENDENCIES "") # 获取PRIVATE/PUBLIC链接库 get_target_property(Bar_PRIV_PUB_LIBS Bar LINK_LIBRARIES) if(Bar_PRIV_PUB_LIBS) list(APPEND Bar_DEPENDENCIES ${Bar_PRIV_PUB_LIBS}) endif() # 获取INTERFACE链接库 get_target_property(Bar_INTERFACE_LIBS Bar INTERFACE_LINK_LIBRARIES) if(Bar_INTERFACE_LIBS) list(APPEND Bar_DEPENDENCIES ${Bar_INTERFACE_LIBS}) endif() # 去重避免重复检查 list(REMOVE_DUPLICATES Bar_DEPENDENCIES) set(ALL_DEPENDENCIES_EXPORTED TRUE) foreach(dep IN LISTS Bar_DEPENDENCIES) # 仅检查当前项目内的非导入目标 if(TARGET ${dep}) get_target_property(dep_is_imported ${dep} IMPORTED) if(NOT dep_is_imported) # 检查目标是否已被导出(_EXPORT_SET是CMake内部属性,导出后会被赋值) get_target_property(dep_export_set ${dep} _EXPORT_SET) if(NOT dep_export_set) set(ALL_DEPENDENCIES_EXPORTED FALSE) break() endif() endif() endif() endforeach() # 所有依赖已导出时,执行Bar的导出 if(ALL_DEPENDENCIES_EXPORTED) export(TARGETS Bar FILE "${CMAKE_CURRENT_BINARY_DIR}/BarTargets.cmake") endif()
关键说明
_EXPORT_SET是CMake的内部属性,当目标通过export或install(EXPORT)命令被导出后,该属性会被设置为对应的导出集合名称,因此可以通过它判断目标是否已完成导出。- 过滤导入目标(
IMPORTED属性为TRUE)和非目标依赖(如系统库),因为这些不需要当前项目负责导出。
内容的提问来源于stack exchange,提问作者user3667089
相关产品推荐
相关产品推荐

