Make生成目标文件后为何跳过先决条件仍执行对应配方?
问题原因分析
1. $(TEST_LOG) 不会被重建的原因
Make判断文件类目标是否需要重建的核心逻辑是:对比目标文件和它的所有先决条件的修改时间,只有当先决条件的修改时间晚于目标文件,或者目标文件不存在时,才会执行目标的重建配方。
你写的$(TEST_LOG)规则没有指定任何先决条件:
$(TEST_LOG): @echo "-- ERROR --" |& tee -a $@
所以只要test.log文件已经存在,不管它是1天前还是更早生成的,Make都会判定它是最新状态,直接跳过重建。你认知中“目标时间戳早于当前时间就算过期”是不符合Make的执行逻辑的。
额外说明:你当前配方用了tee -a是追加写入,就算触发重建也只是往现有文件末尾追加内容,不会覆盖旧文件。
2. eval_test 配方始终执行的原因
eval_test 是没有生成对应实体文件的规则,且你没有将它声明为.PHONY伪目标。此时Make的判断逻辑是:
只要当前目录下不存在名为eval_test的文件,Make就会认为这个目标始终需要被构建,不管它的先决条件$(TEST_LOG)有没有更新,都会执行对应的配方。
同理你写的check_tests也是相同逻辑,只要没有同名文件就会执行对应流程。
修正建议
如果你的预期是每次执行make eval_test/make check_tests时,都重新生成test.log再做校验,可以调整Makefile如下:
TEST_LOG = test.log # 声明伪目标,避免和目录下同名文件冲突,且始终执行配方 .PHONY: check_tests eval_test FORCE check_tests: $(TEST_LOG) eval_test # 加FORCE作为先决条件,强制每次都重建TEST_LOG $(TEST_LOG): FORCE @echo "-- ERROR --" |& tee $@ # 去掉-a参数改为覆盖写入,避免累积旧内容 eval_test: $(TEST_LOG) @if [ `grep -cs "ERROR" $(TEST_LOG)` -eq 0 ]; then exit 0; else exit 1 ; fi # 空规则的FORCE目标,作为强制重建的标记 FORCE:
内容的提问来源于stack exchange,提问作者Tom Ma
相关产品推荐
相关产品推荐

