CMake中如何为各子目录配置独立头文件包含目录?
CMake实现需求的两种方法
方法一:给单个源文件指定编译包含目录
直接在根CMakeLists.txt里,针对不同目录的源文件单独添加专属的包含目录,同时统一添加根目录的include:
# 定义main.elf目标,包含所有源文件 add_executable(main.elf main/main.c a/a1.c a/a2.c b/b.c ) # 给所有源文件添加根目录的include路径 target_include_directories(main.elf PRIVATE ${CMAKE_SOURCE_DIR}/include ) # 给a目录下的源文件额外添加自身的include目录 set_source_files_properties(a/a1.c a/a2.c PROPERTIES COMPILE_OPTIONS "-I${CMAKE_SOURCE_DIR}/a/include" ) # 给b目录下的源文件额外添加自身的include目录 set_source_files_properties(b/b.c PROPERTIES COMPILE_OPTIONS "-I${CMAKE_SOURCE_DIR}/b/include" )
这样a1.c、a2.c编译时会同时拥有-I./include和-I./a/include,可以直接写#include <a1.h>;而main.c、b.c只有根include目录,引用a的头文件必须用#include <a/a1.h>(依赖根include里的软链接),b的头文件外部引用则用#include <b/b.h>。
方法二:用对象库分组处理(更适合大型项目)
虽然a2.c和b.c有循环依赖,但CMake的**对象库(OBJECT库)**只负责编译源文件为目标文件,不做链接操作,刚好能避开循环依赖的问题,还能按目录分组管理包含目录:
# 创建a的对象库,包含a下的所有源文件 add_library(a_obj OBJECT a/a1.c a/a2.c ) # 给a_obj设置根include和自身的include目录 target_include_directories(a_obj PRIVATE ${CMAKE_SOURCE_DIR}/include ${CMAKE_SOURCE_DIR}/a/include ) # 创建b的对象库,包含b下的源文件 add_library(b_obj OBJECT b/b.c ) # 给b_obj设置根include和自身的include目录 target_include_directories(b_obj PRIVATE ${CMAKE_SOURCE_DIR}/include ${CMAKE_SOURCE_DIR}/b/include ) # 定义main.elf,链接两个对象库的目标文件 add_executable(main.elf main/main.c $<TARGET_OBJECTS:a_obj> $<TARGET_OBJECTS:b_obj> ) # 给main.c添加根include目录 target_include_directories(main.elf PRIVATE ${CMAKE_SOURCE_DIR}/include )
这种方式下,每个对象库的源文件编译时都有专属的包含目录,满足自身头文件直接引用的需求;main.c编译时只有根include目录,必须用完整路径引用子目录头文件。最终链接main.elf时,所有目标文件一起参与链接,循环依赖的符号能被正确解析。
注意事项
- 两种方法都不需要改动现有目录结构和软链接,完全适配你的布局。
- 循环依赖只在最终链接阶段存在,只要所有用到的符号都在目标文件中定义,链接器就能正常处理,不会影响编译过程。
内容的提问来源于stack exchange,提问作者JeffLee
相关产品推荐
相关产品推荐

