如何在CMake全构建流程前仅执行一次自定义代码生成脚本
配置方案
你不需要给INTERFACE库添加PRE_BUILD步骤,通过全局自定义目标+依赖传递的方式即可满足需求,具体配置如下:
1. 定义全局唯一的代码生成目标
首先创建一个全局独立的自定义目标用于执行你的代码生成脚本,配置ALL参数保证它会进入默认构建流程,通过BYPRODUCTS声明脚本生成的代码文件,避免重复执行:
add_custom_target(global_code_gen ALL # 替换为你实际的脚本执行命令,注意路径配置正确 COMMAND python ${CMAKE_CURRENT_SOURCE_DIR}/tools/your_gen_script.py BYPRODUCTS # 替换为脚本实际输出的所有代码文件路径 ${CMAKE_CURRENT_BINARY_DIR}/gen/auto_defs.h ${CMAKE_CURRENT_BINARY_DIR}/gen/auto_impl.c COMMENT "Running global code generation script..." VERBATIM ) # 可选配置:禁止该任务与其他构建任务并行执行(CMake 3.16+支持) set_property(GLOBAL PROPERTY JOB_POOLS code_gen_pool=1) set_property(TARGET global_code_gen PROPERTY JOB_POOL code_gen_pool)
2. 关联依赖到INTERFACE库
直接给INTERFACE库添加对上述生成目标的依赖即可,所有链接该INTERFACE库的小型库会自动继承这个依赖,保证编译前脚本已经执行完成:
add_library(${PROJECT_NAME} INTERFACE) # 添加对代码生成目标的依赖 add_dependencies(${PROJECT_NAME} global_code_gen) # 把生成代码的目录加入INTERFACE包含路径,子库可以直接找到生成的头文件 target_include_directories(${PROJECT_NAME} INTERFACE ${CMAKE_CURRENT_BINARY_DIR}/gen ) # 原有链接逻辑保持不变 target_link_libraries(${PROJECT_NAME} ${MANY_SMALL_LIBRARIES})
原理说明
global_code_gen是全局唯一目标,整个构建流程中只会执行1次脚本- 所有依赖
${PROJECT_NAME}的子库都会自动等待global_code_gen执行完成再启动编译,不会出现并行冲突 - 脚本没有修改生成文件内容时,CMake会自动跳过该目标的执行,不会触发不必要的重编译
内容的提问来源于stack exchange,提问作者Inline
相关产品推荐
相关产品推荐

