调试含重写参数的Makefile:解析GetDependenciesFile目标疑问
Makefile中
$(if ...) GetDependenciesFile行的逻辑解析 首先还原你提供的相关Makefile代码:
顶层Makefile的collect目标
collect: file_list="file_list.txt" for makefile in $(ALL_PROJECTS) ; do \ $(MAKE) -s -f $$(basename $$makefile) --directory=$$(dirname $$makefile) GetDependenciesFile RELATIVE_DIR="$$(dirname $$makefile)" DEPENDENCIES_FILE="$$file_list"; \ done;
子Makefile的相关目标
.PHONY: GetDependenciesFile $(if $(filter GetDependenciesFile, $(.OVERRIDEN)),OVERRIDEN,) GetDependenciesFile: DependenciesFile.tmp ifeq ("$(DEPENDENCIES_FILE)","") echo "DEPENDENCIES_FILE is not specified" else cat DependenciesFile.tmp >> $(DEPENDENCIES_FILE) endif DependenciesFile.tmp: echo "$(ALL_DEPENDENCIES)" >> DependenciesFile.tmp
你已经理解了核心逻辑,下面针对你疑惑的那行代码详细解释:
核心知识点:.OVERRIDEN是GNU Make内置变量
你找不到OVERRIDEN的定义是因为它是GNU Make的内置自动变量,并非用户自定义。这个变量会记录所有通过命令行直接指定的目标——比如你在顶层Makefile里用$(MAKE) GetDependenciesFile调用子Makefile时,这个GetDependenciesFile就会被加入到子Make进程的.OVERRIDEN列表中。
拆解目标定义行的逻辑
$(if $(filter GetDependenciesFile, $(.OVERRIDEN)),OVERRIDEN,) GetDependenciesFile: DependenciesFile.tmp
这是一行动态生成目标规则的代码,拆解为以下三步:
$(filter GetDependenciesFile, $(.OVERRIDEN)):检查.OVERRIDEN列表中是否包含GetDependenciesFile目标。如果包含则返回GetDependenciesFile,否则返回空字符串。$(if 条件, 真值输出, 假值输出):如果前面的filter返回非空(即GetDependenciesFile是命令行指定的目标),就输出字符串OVERRIDEN;否则输出空。- 最终生成的规则分为两种情况:
- 当
GetDependenciesFile是命令行指定目标时,规则变为:OVERRIDEN GetDependenciesFile: DependenciesFile.tmp(多目标规则,两个目标共享同一个依赖和后续命令) - 当不是命令行指定目标时,规则就是普通的:
GetDependenciesFile: DependenciesFile.tmp
- 当
这么写的实际意义
这是一种防御性编程手段,专门适配递归Make调用的场景:
在你的场景中,顶层Makefile通过递归调用触发子Makefile的GetDependenciesFile目标,此时子Make进程会标记该目标为“被覆盖”(即存在于.OVERRIDEN中)。通过动态生成OVERRIDEN作为额外目标,可以:
- 避免该目标被依赖链中的其他规则意外触发
- 明确区分“用户主动指定执行的目标”和“通过依赖间接触发的目标”,确保只有主动调用时才执行后续的文件追加逻辑
内容的提问来源于stack exchange,提问作者user23743938
相关产品推荐
相关产品推荐

