Makefile Make不应重建深度依赖关系
下面的Makefile示例大致描述了一个构建过程:Makefile Make不应重建深度依赖关系,makefile,Makefile,下面的Makefile示例大致描述了一个构建过程: a: b @echo "Build a, just using b. Don't care about c." touch a b: c @echo "Constructing b from c is cheap..." touch b @echo "Once accomplished, I no longer need c." c: @echo "Constructing c is ver
a: b
@echo "Build a, just using b. Don't care about c."
touch a
b: c
@echo "Constructing b from c is cheap..."
touch b
@echo "Once accomplished, I no longer need c."
c:
@echo "Constructing c is very expensive..."
@echo "Work work work..."
touch c
clean:
$(RM) a b c
example: clean
make a
$(RM) c
make a
关键是:我需要c
来构建b
,但一旦我拥有b
,我就再也不需要c
。当我做make example
,make
做c
,b
和a
(如预期的那样),删除c
,然后,在最后一次调用中,只需重新做c
(并且不重新做b
和a
,尽管我认为它们现在已经过时了)。但是,由于我的目标是a
,而b
没有改变,我不想重拍c
。算了吧!谁在乎<代码>a
应视为最新的
另一件奇怪的事是当我
make a
rm c
make a
(而不是makeexample
),在第二次调用中make
重建一切(而在makeexample
中,第二次调用只重建c
)
如果make
的目标是a
,并且a
的所有直接先决条件都存在并且比它们更新鲜(a
与b
相比并不过时),我如何防止make
构建c
编辑:我想我可能想要的是将每个文件视为旧文件(例如使用
--旧文件),除非该文件不存在。b
可能是从c
构建的,但你不想告诉Makeb
取决于c
——如果b
仅仅存在,那就足够了。因此,您可以将b
的配方编写为
b:
$(MAKE) c
@echo "Constructing b from c is cheap..."
touch b
@echo "Once accomplished, I no longer need c."
或者,如果c
仅用于制作b
,您可以将制作c
的命令折叠到b
的配方中,而不公开要制作的c
的存在
也许有更优雅的方式表达这一点,而无需调用sub make。如果c
有一些先决条件,这些先决条件在更新后会导致重建,我想它们也需要被列为b
的必备条件。看起来您希望使
将文件c
视为中间文件,一种对您没有任何重要性的文件,除了在生成另一个或多个文件时作为中间结果。本手册第节对此概念进行了解释。由于您的示例不使用任何隐式规则,因此可以手动将文件c
标记为
此生成文件将c
显示为中间文件
a: b
@echo "Build a, just using b. Dont care about c."
touch a
b: c
@echo "Constructing b from c is cheap..."
touch b
@echo "Once accomplished, I no longer need c."
c: d
@echo "Constructing c is very expensive..."
@echo "Work work work..."
touch c
.INTERMEDIATE: c
.PRECIOUS: c
我添加了一个基于的文件d
,尽管本例不需要它
在调用make
之前,文件d
必须存在,它是链的起点。调用make
时,会发生以下情况:
$ touch d
$ make
Constructing c is very expensive...
Work work work...
touch c
Constructing b from c is cheap...
touch b
Once accomplished, I no longer need c.
Build a, just using b. Dont care about c.
touch a
现在删除c
不会对构建产生任何影响:
$ rm c
$ make
make: `a' is up to date.
除此之外,基于依赖关系的更新行为“与平常一样”
选项是可选的。它是一个内置程序,指示make
不删除名为c
的中间文件。你可以自己看看如果你删除那行会发生什么。我无法重现你为做例子:删除c
后,重建c
,b
和a
。您使用的make版本是什么?GNU make 3.81(OS X)使用GNU make 4.2.1
似乎与3.81有所不同。当我使用4.2.1时,第二个在make example
中创建一个,它重建了一切。非常有趣,我不知道3.81和更新版本之间的差异。虽然我没有证据证明你看到了这一点,请注意,有报告称MacOS/Xcode提供的GNU make 3.81版本存在问题,即使是为MacOS编译的GNU make 3.81原始版本中也没有出现这些问题。不幸的是,在我的真实例子中,我有很多东西可能依赖于c,而不仅仅是b。一旦有了这些东西,c就可以被扔了。c也有一些先决条件,如果这些先决条件发生变化,c也会发生变化(这取决于c的变化)。但是如果删除了c,并且您已经得到了依赖于它的东西,那就没问题了。有趣的是,我不知道.INTERMEDIATE
。你能解释一下.INTERMEDIATE
和.SECONDARY
之间的区别吗?我从来没有使用过.SECONDARY
,但它看起来与.INTERMEDIATE
的功能相同,而且它不会丢弃你的中间文件。看来你也可以用它来代替.INTERMEDIATE
和.PRECIOUS
。对我来说,后两者的名称更清楚地表明了它们的意图,但这是一个偏好问题。再仔细想想:必须明确地将文件标记为.INTERMEDIATE
。由于第10.4节中解释的隐式链接,文件通常是中间的。不过,.PRECIOUS
指示很常见。这就是我最终明确使用这两种方法的原因,也是我对.SECONDARY
不太熟悉的原因。当然,如果您首先不想保留c
,那么只需使用。中间就足够了,make
将自动删除c
。确定。因此,如果我不想自动删除c,我可以标记它(.INTERMEDIATE
和.PRECIOUS
)或.SECONDARY
,因为它们是等效的?如果它们是等效的,为什么要有一个.SECONDARY
目标呢?.PRECIOUS
的文档确实表明与.SECONDARY
有重叠。不同之处似乎是当make在shell执行时收到致命信号时所产生的行为,s