如何为多目标关联的依赖库设置互斥编译定义?
实现不同目标链接带互斥编译定义的库变体
当然可以实现这个需求!你提到的通过函数创建多个带不同编译定义的库目标是非常合理的思路,CMake完全支持这种做法,而且可以做得简洁又灵活。
核心思路
因为同一个库目标只能拥有一套编译配置,所以我们需要为同一个库源码创建多个独立的库目标变体,每个变体携带专属的编译定义。之后让目标A、B分别链接对应的变体即可,这样它们就只会使用各自所需的库版本,互不干扰。
具体实现代码
首先我们可以封装一个自定义CMake函数,用来快速创建带指定编译定义的库变体:
# 自定义函数:生成带特定编译定义的库变体 # 参数:BASE_NAME(基础库名)、SUFFIX(变体后缀)、DEF(要添加的编译定义) function(add_library_with_def BASE_NAME SUFFIX DEF) # 拼接变体库的完整名称,比如将基础名mylib变成mylib_def_a set(VARIANT_TARGET "${BASE_NAME}_${SUFFIX}") # 创建库目标(这里用静态库STATIC,也可以根据需求改成SHARED) add_library(${VARIANT_TARGET} STATIC src/mylib.cpp) # 为该库变体添加私有编译定义(只影响库本身的编译) target_compile_definitions(${VARIANT_TARGET} PRIVATE ${DEF}) # 配置库的公共头文件路径(如果你的库有对外头文件的话) target_include_directories(${VARIANT_TARGET} PUBLIC include) endfunction()
接下来用这个函数创建我们需要的两个库变体:
# 创建带-DDEF_A的库变体 add_library_with_def(mylib def_a DEF_A) # 创建带-DDEF_B的库变体 add_library_with_def(mylib def_b DEF_B)
最后分别为目标A和B链接对应的库变体:
# 目标A:仅链接带DEF_A的库 add_executable(target_a src/target_a.cpp) target_link_libraries(target_a PRIVATE mylib_def_a) # 目标B:仅链接带DEF_B的库 add_executable(target_b src/target_b.cpp) target_link_libraries(target_b PRIVATE mylib_def_b)
额外技巧
- 如果需要创建更多库变体,可以结合CMake的循环批量处理,比如:
set(LIB_VARIANTS "def_a;def_b;def_c") set(LIB_DEFS "DEF_A;DEF_B;DEF_C") list(LENGTH LIB_VARIANTS VAR_COUNT) foreach(IDX RANGE 0 ${VAR_COUNT}-1) list(GET LIB_VARIANTS ${IDX} SUFFIX) list(GET LIB_DEFS ${IDX} DEF) add_library_with_def(mylib ${SUFFIX} ${DEF}) endforeach() - 如果使用动态库(SHARED),为了避免不同变体的库文件重名,可以用
set_target_properties设置输出名称和存储目录:set_target_properties(${VARIANT_TARGET} PROPERTIES OUTPUT_NAME "${BASE_NAME}_${SUFFIX}" ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/lib/${SUFFIX}" LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/lib/${SUFFIX}" )
这种方式完美解决了你的问题,每个目标只会使用对应编译定义的库版本,不会出现定义互相影响的情况。
内容的提问来源于stack exchange,提问作者Nick
相关产品推荐
相关产品推荐

