CMake中add_subdirectory无法找到add_custom_command生成文件的问题
CMake结合FlatBuffers生成API的子目录依赖问题
问题描述
在使用CMake结合FlatBuffers生成API时,遇到以下问题:顶层CMake目录生成API后,子目录中无法找到生成的头文件。
项目结构与操作细节:
- 顶层
CMakeLists.txt定义INTERFACE_FBS,调用flatbuffers_generate_headers生成incl接口目标,添加链接库并设置清理属性,随后通过add_subdirectory引入app子目录。 app子目录的CMakeLists.txt创建app可执行文件并链接incl目标。
错误现象:
- 构建时提示找不到
testapi_generated.h,但flatbuffers_generate_headers已通过add_custom_command配置生成该文件。 - 将可执行文件构建代码移至顶层时,头文件能正常生成且构建成功;此时启用子目录也能正常构建,但执行
make clean后再次构建会失败。
疑问:操作哪里有误?是否无法在子目录中使用add_custom_command生成的文件?
问题根源
核心问题是接口目标的依赖传递不完整:
- 子目录链接
incl目标时,CMake未正确识别需要先执行顶层的自定义命令生成头文件,导致构建顺序出错。 make clean后构建失败,是因为第一次顶层构建生成的头文件被缓存,子目录可复用;清理后缓存消失,CMake未触发顶层生成命令就开始编译子目录代码。
修复方案
1. 为接口目标设置公共包含目录
在顶层CMakeLists.txt中,为incl目标添加公共包含目录,确保子目录能找到生成的头文件:
target_include_directories(incl INTERFACE ${CMAKE_CURRENT_BINARY_DIR})
${CMAKE_CURRENT_BINARY_DIR}是顶层构建目录,即testapi_generated.h的生成位置。
2. 将生成的头文件关联到接口目标
使用target_sources把生成的头文件添加为incl目标的接口源文件,让CMake明确该目标依赖这些生成文件:
set(GENERATED_HEADER ${CMAKE_CURRENT_BINARY_DIR}/testapi_generated.h) target_sources(incl INTERFACE ${GENERATED_HEADER})
这样所有链接incl的目标(比如子目录的app)会自动依赖该生成文件,触发add_custom_command执行。
3. 确认FlatBuffers生成命令的依赖追踪
检查flatbuffers_generate_headers的实现,确保它已将生成的头文件作为add_custom_command的OUTPUT并关联到incl目标。若函数未自动处理依赖传递,补充上述两步配置即可。
验证效果
修改后,子目录的app目标链接incl时,CMake会先执行顶层自定义命令生成testapi_generated.h,再编译子目录代码。执行make clean后重新构建,也能正确触发头文件生成流程,不会再出现找不到头文件的错误。
内容的提问来源于stack exchange,提问作者Cedric Schmeits
相关产品推荐
相关产品推荐

