CMake中为仓库内多项目的各自依赖设置对应编译选项/定义的方案咨询
CMake中为仓库内多项目的各自依赖设置对应编译选项/定义的方案咨询
嘿,你的问题很典型,先给你个明确答复:你目前用INTERFACE库传递编译选项和定义的方法完全可行。CMake里INTERFACE库就是专门用来封装这类接口属性的,当你把P1_configuration以PRIVATE方式链接到P1、A、B这些目标时,它们的编译过程会自动继承对应的选项和定义,而且不会把这些属性传递给依赖它们的上层目标,完全符合你的需求。
不过你提到项目多了容易漏加链接,确实手动一个个加太繁琐,这里给你两个更高效、不容易出错的优化方案:
方案一:自定义CMake函数批量处理
你可以写一个自定义函数,把创建配置库、链接主项目和所有依赖的逻辑封装起来,这样只需要调用一次函数就能搞定整个项目的配置,避免遗漏。
示例代码如下:
# 自定义函数:传入项目名、编译选项、编译定义,自动完成配置和链接 function(setup_project_config PROJECT_NAME COMPILE_OPTS COMPILE_DEFS) # 创建对应项目的INTERFACE配置库 add_library(${PROJECT_NAME}_configuration INTERFACE) target_compile_options(${PROJECT_NAME}_configuration INTERFACE ${COMPILE_OPTS}) target_compile_definitions(${PROJECT_NAME}_configuration INTERFACE ${COMPILE_DEFS}) # 提前定义好该项目的所有依赖列表(比如P1的依赖是A、B、C、D) foreach(DEP ${${PROJECT_NAME}_DEPS}) target_link_libraries(${DEP} PRIVATE ${PROJECT_NAME}_configuration) endforeach() # 把配置库链接到主项目 target_link_libraries(${PROJECT_NAME} PRIVATE ${PROJECT_NAME}_configuration) endfunction()
然后在顶层CMakeLists.txt里这样用:
# 定义P1的依赖列表 set(P1_DEPS A B C D) # 调用函数配置P1及其依赖 setup_project_config(P1 "${P1_compile_options}" "${P1_compile_definitions}") # 同理处理P2 set(P2_DEPS A ...) # 替换成P2实际的依赖 setup_project_config(P2 "${P2_compile_options}" "${P2_compile_definitions}")
这样不管项目有多少依赖,只要提前列好依赖列表,函数会自动帮你完成所有链接操作,再也不用担心漏加了。
方案二:利用目标依赖链传递配置(限专属依赖场景)
如果你的项目结构是主项目(比如P1)直接依赖A、B、C、D,且这些依赖项只服务于该主项目,那可以换一种思路:把配置库链接到主项目,然后让依赖项通过目标属性传递继承配置。
举个例子:
# 创建P1的配置库 add_library(P1_configuration INTERFACE) target_compile_options(P1_configuration INTERFACE ${P1_compile_options}) target_compile_definitions(P1_configuration INTERFACE ${P1_compile_definitions}) # 把配置库以INTERFACE方式链接到P1 target_link_libraries(P1 INTERFACE P1_configuration) # 让A、B等依赖以PUBLIC方式链接到P1 target_link_libraries(A PUBLIC P1) target_link_libraries(B PUBLIC P1) # ...以此类推
这样当编译A的时候,会自动继承P1的配置库属性,但这个方案的局限性在于:如果同一个依赖(比如A)要被多个主项目(P1、P2)使用,就会出现配置冲突,所以方案一的通用性更强。
最后再总结下:你当前的方法是正确的,但为了避免手动操作遗漏,用自定义函数批量处理是最优解。
备注:内容来源于stack exchange,提问作者zeb92
相关产品推荐
相关产品推荐

