我有这样的规则:
"foo" *> \out do
need something
create "foo" somehow
它构建正确,并且运行构建两次不会构建目标。 然后我为此规则添加了一个系统:
"foo" *> \out do
...
system' something
现在运行抖动不会重建“foo”目标,因为没有更改依赖项。无论如何,规则改变了。所以我希望新添加的系统'动作改变规则的历史,反过来强制重建“foo”,但事实并非如此。 通常在autoconf / automake系统中,甚至在非平凡的makefile中,规则依赖于Makefile本身,因此无论何时更改,项目都会重建。 在Shake中,我希望这可以工作并且细化。
在系统的源代码中,我看不到任何会对正在运行的命令添加隐式依赖的内容。
我做错了吗?是不是故意不支持这种依赖,或者它根本没有实现?
答案 0 :(得分:1)
您所看到的行为是预期的,ICFP 2012 paper S6.2概述了应对它的一些策略。如果每个输出都依赖于用于构建它的规则,那将是理想的,但这需要一些规则相等(这些规则只是在执行期间源代码不可用的函数)。有一天,我希望Shake会像你描述的那样工作,但我认为GHC目前不可能。
为了最大限度地减少构建系统更改的数量,最好将您认为会定期更改的任何内容保留在构建系统之外。任何文件列表(例如,链接C可执行文件所需的文件)都可以放在配置文件中,或者通过使用oracle机制正确依赖。
当然,规则仍会不时发生变化,您可以采取两种方法:
如果发生任何变化,重建所有内容
许多Makefile采用的简单保守方法是重建所有内容,如果有任何变化。实现此策略的一种简单方法是对Shake脚本进行哈希处理,并将其用作shakeVersion
字段。对于可以快速重建的项目,这可以很好地工作。
使用手动控制重建
对于较大的项目,构建系统通常处于日常变化中,但构建系统的大多数部分对大多数规则没有影响。对于某些规则,我明确need
规则中的一些源文件,例如,如果文件中有一个大型生成器,我会need
生成生成输出的规则中的writeFileChanged
。如果您还使用{{1}}来编写生成的文件,那么对生成器的许多修改将只会导致最小的重建。
如果更改更具侵入性,我手动增加shakeVersion字段,并强制完成重建。在具有适当依赖性跟踪的成熟构建系统中,此事件可能每年仅发生几次。