You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用纯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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.22 02:48:22