(这类似于GNU化妆:执行目标,但需要从文件相关性 ,但略有不同)。
当我试图强行建立一个目标,使自动认为这个目标是过时的,并迫使其依赖于它的所有目标的运行。
在我的情况下,目标是一个递归发出呼叫其做了很多工作,可能只是“无计可施”回归:
.PHONY: intermediate.dat
intermediate.dat:
$(MAKE) expensive_chain_which_finally_creates_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
在这种情况下,“让所有”运行40秒,虽然intermediate.dat可能不会改变(递归make返回“毫无办法”)。 但是, 如果递归化妆intermediate.dat更新,目标应是过时的。
难道真的没有办法做到这一点?
问候DIVB
让intermediate.dat
取决于假目标的而不是虚假的本身。
.PHONY : always-remake
intermediate.dat : always-remake
IIRC,上次我解决了这个问题,为有意和我用.PHONY没有工作:
always-remake :
@true
代替。 但是,我不记得为什么,所以先试试.PHONY。
以使问题intermediate.dat
本身假冒是make
从不检查一个虚假的文件 ,这是您要的行为的存在/日 。 你只需要触发重建规则,这是由过时的先决条件完成的; 一个虚假的前提始终是过时的,所以它的工作。
另一个技巧是使用订单唯一先决条件 ,再加上一个递归调用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制造手柄.PHONY
目标 。 这可能会导致make
运行始终执行的时间昂贵的操作,即使它并不需要:
假目标不应该是一个真正的目标文件的前提; 如果是,它的配方将运行每次化妆去更新文件。 只要假目标从来都不是一个真正的目标的先决条件,只有当假目标是指定目标(见参数来设定目标)的假目标配方将被执行。