我有以下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 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
,然后在在最后一次make a
调用中,仅重制了c
(尽管我认为它们现在已经过时,但不重制b
和a
)。但是,由于我的目标是a
并且b
并没有改变,所以我不想重制c
。忘掉它!谁在乎! a
应该被认为是最新的。
另一件事是,当我
make a
rm c
make a
(而不是make example
),在第二次调用make
中将重建所有内容(而在make example
中,第二次调用将仅重建c
)。
当目标为make
并且c
的所有紧迫前提都存在且比其新鲜时,如何阻止a
建立a
({{ 1}}与a
相比不是陈旧的,即使前提条件中的前提条件没有?
编辑:我认为我可能希望将每个文件都视为旧文件(例如,使用b
)除非该文件不存在
答案 0 :(得分:1)
您似乎希望make
将文件c
视为中间文件,该文件除了生成另一个文件或其他文件时作为中间结果外,对您没有任何重要性。手册第10.4 Chains of Implicit Rules节对此概念进行了说明。由于您的示例未使用任何隐式规则,因此您可以将文件c
手动标记为.INTERMEDIATE
。
此生成文件将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
我添加了一个基于your comment的文件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.
除此之外,基于依赖关系的更新行为“与通常相同”。
.PRECIOUS
target是可选的。它是一个内置指令,指示make
不要删除名为c
的中间文件。您可以亲眼看到如果删除该行会发生什么情况。
答案 1 :(得分:0)
b
可能是根据c
构建的,但是您不想告诉Make b
取决于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
的存在。
也许有更优雅的表达方式,而无需调用子品牌。而且,如果c
有一些先决条件,如果它们在更新后会被重建,那么我想它们也需要列为b
的先决条件。