如何用同一CMake目标适配Scheme S7库的两种不同配置场景?
CMake适配Scheme S7两种使用场景的方案
不需要创建两个完全独立的目标,更合理的做法是基于基础配置派生不同的子目标,既复用公共设置,又能满足各自的编译需求。下面是具体实现:
推荐方案:基础目标+派生配置目标
先定义一个仅提供头文件路径的基础目标,作为两个场景的公共依赖:
# 基础目标:仅包含头文件路径,无额外编译配置 add_library(third_party_scheme_base INTERFACE) add_library(third_party::scheme_base ALIAS third_party_scheme_base) target_include_directories(third_party_scheme_base INTERFACE "${CMAKE_CURRENT_SOURCE_DIR}/scheme" )
基于这个基础目标,分别创建适配两种场景的子目标:
场景1:包含源文件+特定编译宏
add_library(third_party_scheme_with_src INTERFACE) add_library(third_party::scheme_with_src ALIAS third_party_scheme_with_src) # 继承基础目标的头文件配置 target_link_libraries(third_party_scheme_with_src INTERFACE third_party::scheme_base ) # 添加S7源文件和对应编译宏 target_sources(third_party_scheme_with_src INTERFACE "${CMAKE_CURRENT_SOURCE_DIR}/scheme/s7.c" ) target_compile_definitions(third_party_scheme_with_src INTERFACE S7_EXPORT_LIB S7_OUTPUT_FUNCTION_FULL_STRING )
场景2:仅头文件+另一组编译宏
add_library(third_party_scheme_header_only INTERFACE) add_library(third_party::scheme_header_only ALIAS third_party_scheme_header_only) # 继承基础目标的头文件配置 target_link_libraries(third_party_scheme_header_only INTERFACE third_party::scheme_base ) # 添加专属编译宏(替换成你的第二组宏即可) target_compile_definitions(third_party_scheme_header_only INTERFACE S7_STATIC_LIB S7_NO_OUTPUT_REDIRECT )
之后两个自研库直接依赖对应的目标就行:
- 需要编译S7源文件的库:
target_link_libraries(your_lib1 PRIVATE third_party::scheme_with_src) - 仅用头文件的库:
target_link_libraries(your_lib2 PRIVATE third_party::scheme_header_only)
备选方案:单目标通过条件控制(不推荐)
如果硬要使用单个目标,可以通过CMake的生成器表达式实现条件配置,但会让目标逻辑变得复杂,可读性差:
add_library(third_party_scheme INTERFACE) add_library(third_party::scheme ALIAS third_party_scheme) target_include_directories(third_party_scheme INTERFACE "${CMAKE_CURRENT_SOURCE_DIR}/scheme" ) # 通过依赖方的目标属性控制是否包含源文件 target_sources(third_party_scheme INTERFACE $<$<BOOL:$<TARGET_PROPERTY:USE_S7_SRC>>:"${CMAKE_CURRENT_SOURCE_DIR}/scheme/s7.c"> ) # 按属性切换编译宏 target_compile_definitions(third_party_scheme INTERFACE $<$<BOOL:$<TARGET_PROPERTY:USE_S7_SRC>>:S7_EXPORT_LIB;S7_OUTPUT_FUNCTION_FULL_STRING> $<$<BOOL:$<TARGET_PROPERTY:USE_S7_HEADER_ONLY>>:S7_STATIC_LIB;S7_NO_OUTPUT_REDIRECT> )
依赖时需要给自研库设置属性:
# 场景1的库 add_library(your_lib1 STATIC ...) set_target_properties(your_lib1 PROPERTIES USE_S7_SRC ON) target_link_libraries(your_lib1 PRIVATE third_party::scheme) # 场景2的库 add_library(your_lib2 STATIC ...) set_target_properties(your_lib2 PROPERTIES USE_S7_HEADER_ONLY ON) target_link_libraries(your_lib2 PRIVATE third_party::scheme)
总结
优先选择基础目标+派生子目标的方案,每个目标职责明确,依赖方可以直接选择对应配置,避免逻辑混乱和编译冲突。
内容的提问来源于stack exchange,提问作者Dess
相关产品推荐
相关产品推荐

