如何用纯CMake处理非无限循环依赖下的头文件生成?
纯CMake实现YOMM2代码生成依赖方案
核心思路
- 将自动生成的
generated.hpp存放在构建目录下(避免污染源码目录) - 先构建
generator可执行文件,通过自定义命令触发其运行以生成generated.hpp - 让
main目标直接依赖生成的generated.hpp,确保构建main前必先生成该文件 - 利用CMake的依赖追踪机制,结合
__has_include处理初始空文件的编译兼容问题 - 强制每次构建
main前都执行generator,即使依赖文件未发生变化
CMake配置代码
cmake_minimum_required(VERSION 3.18) project(yomm2_generator_demo LANGUAGES CXX) set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD_REQUIRED ON) # 创建构建目录下的include文件夹,用于存放生成的头文件 set(GENERATED_INCLUDE_DIR "${CMAKE_CURRENT_BINARY_DIR}/include") file(MAKE_DIRECTORY ${GENERATED_INCLUDE_DIR}) # 定义生成文件的完整路径 set(GENERATED_HEADER "${GENERATED_INCLUDE_DIR}/generated.hpp") # 1. 构建generator可执行文件 add_executable(generator generator.cpp domain.cpp ) target_include_directories(generator PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} ${GENERATED_INCLUDE_DIR} # 支持generator读取自身生成的文件,处理循环依赖 ) # 2. 自定义命令:运行generator生成/更新generated.hpp add_custom_command( OUTPUT ${GENERATED_HEADER} COMMAND generator DEPENDS generator domain.cpp domain.hpp generator.cpp COMMENT "Running generator to update generated.hpp..." BYPRODUCTS ${GENERATED_HEADER} VERBATIM ) # 3. 构建main可执行文件 add_executable(main main.cpp domain.cpp ${GENERATED_HEADER} # 让main直接依赖生成文件,确保构建前先执行generator ) target_include_directories(main PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} ${GENERATED_INCLUDE_DIR} # 让main能找到生成的generated.hpp ) # 强制每次构建main前都重新检查并运行generator set_property(SOURCE ${GENERATED_HEADER} PROPERTY SYMBOLIC TRUE)
关键细节说明
- 生成文件路径控制:通过
CMAKE_CURRENT_BINARY_DIR将generated.hpp放在构建目录,完全隔离源码与构建产物 - 循环依赖处理:generator依赖自身生成的文件,但CMake会先构建generator(此时
generated.hpp为空,通过__has_include兼容编译),运行后更新文件,后续构建时generator会使用最新文件,仅需一次循环即可满足需求 - 强制运行generator:
set_property(SOURCE ${GENERATED_HEADER} PROPERTY SYMBOLIC TRUE)让CMake每次构建main时都触发自定义命令,而非仅在依赖文件变化时执行 - 初始空文件兼容:在
domain.hpp中加入以下代码,处理初始状态下generated.hpp不存在的情况:#ifndef DOMAIN_HPP #define DOMAIN_HPP #if __has_include("generated.hpp") #include "generated.hpp" #endif // domain相关业务代码 #endif // DOMAIN_HPP - 依赖追踪可靠性:
add_custom_command的DEPENDS参数确保domain.cpp、domain.hpp或generator.cpp变更时,自动重建generator并更新生成文件;BYPRODUCTS标记避免生成文件被CMake误清理
内容的提问来源于stack exchange,提问作者yorel
相关产品推荐
相关产品推荐

