如何让引用指定头文件的可执行自动依赖外部项目构建?
嘿,这个场景我太熟悉了——给几十个可执行文件挨个加add_dependencies确实烦死人。下面给你几个实用的解决方案,按推荐程度排序:
方案1:用INTERFACE目标封装依赖(最推荐)
这是CMake现代最佳实践的做法,把extproj的头文件路径、依赖关系都封装成一个INTERFACE库,之后所有需要用到这些头文件的目标只要链接这个库,就能自动继承所有依赖和路径配置,完全不用逐个加add_dependencies。
具体代码示例:
# 创建一个INTERFACE类型的"虚拟库",用来封装extproj的配置 add_library(extproj_interface INTERFACE) # 把extproj的头文件目录添加到INTERFACE目标中,这样链接它的目标会自动获得这个include路径 target_include_directories(extproj_interface INTERFACE ${EXTERNAL_INSTALL_PATH}/extproj ) # 给这个INTERFACE目标添加对extproj的依赖——所有链接它的目标都会自动继承这个依赖关系 add_dependencies(extproj_interface extproj) # 之后你的可执行文件只需要链接这个INTERFACE目标就行 add_executable(myapp1 src/myapp1.cpp) target_link_libraries(myapp1 PRIVATE extproj_interface) add_executable(myapp2 src/myapp2.cpp) target_link_libraries(myapp2 PRIVATE extproj_interface) # 哪怕有100个可执行文件,只要链接extproj_interface,就自动搞定依赖!
这个方案的好处是封装性极强,如果后续extproj的路径或者依赖逻辑变了,只需要修改extproj_interface的配置,所有关联目标都会自动更新,维护成本极低。
方案2:给关键头文件添加依赖标记
如果你不想用INTERFACE库,或者只是针对少数几个核心头文件做依赖,可以给这些头文件本身添加依赖标记,让任何包含它们的源文件自动触发extproj的构建。
具体步骤:
- 先让extproj构建完成后生成一个"标记文件"(用来标识extproj已经解压完成)
- 把这个标记文件设为目标头文件的依赖
代码示例:
# 定义一个标记文件路径,用来确认extproj已经完成解压 set(EXTPROJ_DONE_MARKER ${EXTERNAL_INSTALL_PATH}/extproj/.extproj_installed) # 让extproj构建完成后自动生成这个标记文件 add_custom_command(TARGET extproj POST_BUILD COMMAND ${CMAKE_COMMAND} -E touch ${EXTPROJ_DONE_MARKER} COMMENT "Marking extproj installation as complete" ) # 给你提到的header_file.h添加依赖:它必须等到标记文件存在才能被使用 set_source_files_properties(${EXTERNAL_INSTALL_PATH}/extproj/header_file.h PROPERTIES OBJECT_DEPENDS ${EXTPROJ_DONE_MARKER} )
这样,任何包含header_file.h的源文件在编译时,CMake会先检查标记文件是否存在,而标记文件又依赖extproj的POST_BUILD步骤,间接保证了extproj先构建完成。
不过这个方案的缺点是如果有多个头文件需要处理,得逐个设置OBJECT_DEPENDS,不如INTERFACE方案高效。
总结
优先选方案1,它完全符合CMake的设计理念,能帮你彻底摆脱重复添加依赖的繁琐工作。如果是特殊场景下无法使用INTERFACE库,再考虑方案2。
内容的提问来源于stack exchange,提问作者Gillespie
相关产品推荐
相关产品推荐

