查找CMake中add_custom_command生成文件时必须使用DEPENDS的示例
CMake add_custom_command DEPENDS 选项作用示例
核心原理说明
构建系统(如Make、Ninja)不会解析你在add_custom_command的COMMAND里写的命令内容,它无法自动判断该命令执行需要依赖哪些输入文件,必须通过DEPENDS显式声明。声明后:
- 当
DEPENDS指定的文件修改时间晚于OUTPUT指定的生成文件时,构建系统会自动重跑自定义命令更新生成文件 - 如果
DEPENDS的文件不存在,且是其他构建目标的输出,构建系统会先构建对应的依赖目标,再执行当前自定义命令
可复现测试示例
步骤1:准备初始文件
你需要在工作目录下创建3个文件:
good.cpp:用于读取生成的foo文件内容并输出
#include <iostream> #include <fstream> #include <string> int main() { std::ifstream foo_file("foo"); std::string content; std::getline(foo_file, content); std::cout << "foo 内容:" << content << std::endl; return 0; }
london:初始内容为初始内容CMakeLists.txt
cmake_minimum_required(VERSION 3.10) project(DependsTest VERSION 1.0) add_custom_command(OUTPUT foo COMMAND cp london foo DEPENDS london # 后续测试会注释掉这一行 COMMENT "正在生成foo文件" ) add_executable(cake good.cpp foo)
步骤2:测试带DEPENDS的正常逻辑
- 新建build目录并执行构建:
mkdir build && cd build cmake .. make ./cake
此时输出为foo 内容:初始内容,符合预期。
2. 修改工作目录下的london文件内容为更新后的内容,再次执行构建:
make ./cake
此时可以看到构建时打印了正在生成foo文件的日志,运行./cake输出为foo 内容:更新后的内容,依赖生效。
步骤3:注释DEPENDS后的异常表现
- 清空build目录,修改
CMakeLists.txt注释掉DEPENDS london这一行,重新执行首次构建:
rm -rf * cmake .. make ./cake
首次构建和之前表现一致,输出foo 内容:初始内容。
2. 再次修改工作目录下的london文件内容为第二次更新的内容,执行构建:
make ./cake
此时构建输出为Nothing to be done for 'all',没有重跑生成foo的命令,运行./cake仍然输出foo 内容:初始内容,修改london没有触发更新,这就是缺少DEPENDS导致的问题。
额外极端场景验证
如果首次构建前london文件不存在:
- 写了
DEPENDS london:CMake配置阶段就会提示找不到依赖文件,或者如果london是其他目标的输出,会先构建london再执行自定义命令 - 没写
DEPENDS london:构建阶段直接执行cp london foo命令,报错cp: cannot stat 'london': No such file or directory
内容的提问来源于stack exchange,提问作者Neymar87
相关产品推荐
相关产品推荐

