Makefile动态依赖顺序问题:如何跳过已生成的中间目标?
解决Makefile中自动生成文件的重复构建问题
先看你的Makefile场景:
all: file4.txt file1.txt: ./program parameter1 file2.txt: file1.txt ./program parameter2 file3.txt: file2.txt ./program parameter3 file4.txt: file3.txt ./program parameter4
问题在于:./program parameter2有时会同时生成file2.txt和file3.txt,但直接执行make file4.txt时,Make仍会触发file3.txt的构建规则,导致已生成的file3.txt被覆盖;而分两次执行make file2.txt再make file4.txt却能跳过,因为此时file3.txt的时间戳比file2.txt新,Make认为它已经是最新的。
要解决这个问题,核心是让Make在构建file3.txt前,先检查它是否已经存在且足够新,避免重复执行破坏文件。这里有两种简单可行的修改方式:
方法一:极简条件判断构建
直接在file3.txt的构建命令前加入检查逻辑,只有当file3.txt不存在,或者它的修改时间比依赖的file2.txt旧的时候,才执行构建命令:
all: file4.txt file1.txt: ./program parameter1 file2.txt: file1.txt ./program parameter2 file3.txt: file2.txt @test -f $@ -a $@ -nt $< || ./program parameter3 file4.txt: file3.txt ./program parameter4
逻辑说明
test -f $@ -a $@ -nt $<:判断file3.txt是否存在(-f $@),且它的修改时间比file2.txt($<代表第一个依赖文件)新(-nt是newer than的缩写)。- 如果上述条件成立,
test返回0,||后面的构建命令就不会执行;如果条件不成立(文件不存在或过时),才执行./program parameter3。
方法二:带提示的条件判断(可选)
如果你需要明确的跳过提示,方便调试,可以用多行shell脚本实现:
all: file4.txt file1.txt: ./program parameter1 file2.txt: file1.txt ./program parameter2 file3.txt: file2.txt ifneq ($(wildcard file3.txt),) @if test $@ -nt $<; then \ echo "file3.txt already up to date, skipping build"; \ exit 0; \ fi endif ./program parameter3 file4.txt: file3.txt ./program parameter4
逻辑说明
- 先用
$(wildcard file3.txt)检查文件是否存在,存在的话再判断时间戳关系。 - 如果文件已处于最新状态,打印提示并退出,跳过后续构建命令;否则执行正常构建流程。
修改后,直接执行make file4.txt时,Make会自动检查file3.txt的状态,只要它已经存在且比file2.txt新,就会跳过构建,不会覆盖已有文件。
内容的提问来源于stack exchange,提问作者Amir
相关产品推荐
相关产品推荐

