另一个技巧是使用仅订单的先决条件,以及对 的递归调用make
。intermediate.dat
当您想要在需要创建文件时实现一些额外的逻辑时,或者当您想要将目标与通常的exists && newer than
检查分离时,这可能很有用make
。
例如:
假设该文件包含一些后续任务所依赖的对日期敏感的材料,并且它会在12 小时后过期。我们只想在其中任何一个为真时重新创建文件:
为了实现 make 目标和配方,我们将创建一个目标,它运行时间检查,如果文件过期,则有条件地删除文件,然后为该文件.PHONY
check-intermediate.dat
重新运行。make
请注意,check-intermediate.dat
目标将通过仅顺序的先决条件语法(例如intermediate.dat: | check-intermediate.dat
)定义,这使其始终在目标之前运行(例如intermediate.dat
)。时间检查成本低,我们总是希望它为我们运行和管理文件,但不会像正常的先决条件目标那样使原始make
检查无效。intermediate.dat
.PHONY
.PHONY: check-intermediate.dat
check-intermediate.dat:
if [ -e intermediate.dat ]; then find intermediate.dat -mmin +720 -exec bash -c 'rm -f "{}"; $(MAKE) intermediate.dat' \; ; fi
intermediate.dat: | check-intermediate.dat
echo run-expensive-tasks-here-to-create-intermediate.dat
step1.dat: intermediate.dat
sleep 10
step2.dat: step1.dat
sleep 15
step3.dat: step2.dat
sleep 10
all: step3.dat
sleep 5
现在,任何依赖于目标的东西都将首先运行检查,如果文件过期则删除文件,然后在运行其余依赖目标之前intermediate.dat
重新运行。make intermediate.dat
如果intermediate.dat
文件已经存在,它将运行检查,如果检查通过,它将继续运行而不运行耗时的重新创建任务。
依赖.PHONY
目标的问题在于它总是会运行依赖它的任务,因为GNU Make 处理.PHONY
目标的方式。这可能导致make
运行始终执行耗时的操作,即使它不需要:
虚假目标不应该是真实目标文件的先决条件;如果是,则每次 make 更新该文件时都会运行其配方。只要虚假目标永远不是真实目标的先决条件,虚假目标配方将仅在虚假目标是指定目标时执行(请参阅指定目标的参数)。