为何CMake中带DEPFILE的add_custom_command每次编译都会重运行?
问题分析与解决方案
核心问题
你搞反了DEPFILE的工作逻辑:
DEPFILE指定的依赖文件必须由自定义命令本身生成,而非在CMake配置阶段提前创建空文件。- 你用
write_file在配置阶段生成了空的.d文件,Ninja解析时会判定依赖信息无效(空依赖等同于无有效依赖),因此每次构建都会重新触发自定义命令。 - 即便后续Python脚本更新了
.d文件,CMake重新配置时write_file会再次覆盖它为空,陷入持续重运行的循环。
正确实现方式
- 删除CMake中的
write_file步骤,不要提前创建.d文件。 - 让Python脚本
myscript.py负责生成.d文件:- 脚本执行时,除了生成
static_init.cpp,还要生成对应的.d文件,格式遵循Makefile依赖规则:/path/to/static_init.cpp: dependency1.h dependency2.cpp ... - 可以在CMake中通过参数传递让Python脚本知晓
.d文件路径,示例:set(OUTPUT_FILE "${CMAKE_BINARY_DIR}/static_init/generated/${target}/static_init.cpp") set(DEP_FILE "${CMAKE_BINARY_DIR}/static_init/input/${target}.d") add_custom_command( OUTPUT ${OUTPUT_FILE} COMMAND ${Python3_EXECUTABLE} myscript.py --output ${OUTPUT_FILE} --depfile ${DEP_FILE} DEPFILE ${DEP_FILE} VERBATIM)
- 脚本执行时,除了生成
- 确保依赖文件生成时机:Python脚本必须在生成目标文件的同时生成
.d文件,Ninja会在命令执行完成后读取.d文件更新依赖链。
额外注意事项
- CMake 3.18对
DEPFILE的支持稳定,但要确保.d文件使用绝对路径(你当前的写法已基于CMAKE_BINARY_DIR,符合要求)。 - 若Python脚本生成相对路径的
.d文件,Ninja可能无法正确解析,建议始终传递绝对路径参数。
内容的提问来源于stack exchange,提问作者Crazy Sage
相关产品推荐
相关产品推荐

