2

(这类似于GNU make: Execute target but take dependency from file但略有不同)。

当我试图强制构建一个目标时,make 会自动认为这个目标已经过时并强制运行所有依赖它的目标。

在我的例子中,目标是一个递归的 make 调用,它做了很多工作并且可能只是返回“无事可做”:

 .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

在这种情况下,“make all”会运行 40 秒,尽管 intermediate.dat 可能没有改变(递归 make 返回“无事可做”)。但是,如果递归使更新了intermediate.dat,则目标将过期。

真的没有办法做到这一点吗?

问候 divB

4

2 回答 2

3

使intermediate.dat 依赖于虚假目标而不是虚假本身。

 .PHONY : always-remake

 intermediate.dat : always-remake

IIRC,我上次解决问题时,.PHONY 没有按预期工作,我使用了:

 always-remake :
     @true

反而。但是,我不记得为什么了,所以先试试 .PHONY。

使intermediate.dat自己变得虚假的问题是make 永远不会检查虚假文件的存在/日期,这是您想要的行为。您只需要触发重建规则,这是由一个过时的先决条件完成的;一个虚假的先决条件总是过时的,所以它可以完成工作。

于 2012-06-20T13:53:35.917 回答
1

另一个技巧是使用仅订单的先决条件,以及对 的递归调用makeintermediate.dat当您想要在需要创建文件时实现一些额外的逻辑时,或者当您想要将目标与通常的exists && newer than检查分离时,这可能很有用make

例如:

假设该文件包含一些后续任务所依赖的对日期敏感的材料,并且它会在12 小时后过期。我们只想在其中任何一个为真时重新创建文件:

  • 文件超过 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 更新该文件时都会运行其配方。只要虚假目标永远不是真实目标的先决条件,虚假目标配方将仅在虚假目标是指定目标时执行(请参阅指定目标的参数)。

于 2016-05-16T23:32:08.080 回答