之前花过一点时间看了一部分makefile的资料,但是基本上做到了大概能够看懂就止步了。因为现在构建工具有多了很多,掌握的难度要低不少。不够,makefile是去了解很多项目必然要面对的一个部分,因此基础的知识,尤其是可以以读懂为目的的一些基础知识还是需要补充一下。这一次,来通过简单的翻译整理理解一下隐式规则的链。
10.4隐含规则的锁链
有时,一个文件可以由一系列的隐式规则来生成。例如,处理依赖文件n.y,先运行yacc然后cc可以生成文件n.o。这样的序列被称为链式序列。
如果文件n.c存在,或者在makefile中提到,不需要特殊搜索:make可以发现目标文件可以从n.c编译;稍后,在考虑如何创建n.c时,使用运行Yacc的规则。最终,n.c和n.o都被更新了。
然而,即使n.c不存在,也没有被提及,也要知道如何把它想象成n.o和n.y之间缺失的环节!在这种情况下,n.c被称为中间文件。一旦make决定使用中间文件,它就会被输入到数据库中,就像在makefile中提到过它一样,以及说明如何创建它的隐式规则。
中间文件和所有其他文件一样,使用它们的规则重新生成。但是处理中间文件的方式有两种不同。
第一个区别是,如果中间文件不存在,则会发生什么。如果一个普通文件b不存在,并且make考虑一个依赖于b的目标,它总是创建b,然后从b更新目标。但是如果b是一个中间文件,那么make就可以单独留下了:它不会创建b,除非它的先决条件之一已经过时。这意味着依赖于b的目标也不会被重建,除非有其他原因来更新目标:例如目标不存在或者不同的先决条件比目标更新。
第二个区别是,如果make为了更新其他东西而创建了b,它会在不再需要之后删除b。因此,一个在制作之前不存在的中间文件在制作之后也不存在。通过打印‘rm’命令显示正在删除的文件,向您报告删除文件。
通过将文件列为特殊目标(.INTERMEDIATE)的先决条件,可以显式地标记为中间文件。即使以其他方式显式地提到该文件,这也会生效。
如果在makefile中提到一个文件作为目标或先决条件,则它不能是中间文件,因此避免删除中间文件的一种方法是将其作为添加到某些目标的先决条件。但是,这样做可能会导致make在搜索模式规则时做额外的工作(请参见隐式规则搜索算法)。
作为一种替代方法,将一个文件作为特殊目标.NOTINTERMEDIAT的先决条件,将强制它不被视为中间文件(就像任何其他提到该文件一样)。同样,列出模式规则的目标模式作为.NOTINTERMEDIATE的先决条件,可以确保使用该模式规则生成的目标不会被视为中间目标。
如果您不希望make仅仅因为文件不存在而创建该文件,也不希望make自动删除该文件,可以将其标记为辅助文件。要做到这一点,请将其列为特殊目标.SECONDARY的先决条件。将文件标记为次要文件也会将其标记为中间文件。
一个链可以包含两个以上的隐含规则。例如,可以通过运行RCS、Yacc和cc,从RCS/foo.y、v生成一个文件foo。然后foo.y和foo.c都是中间文件,最后会被删除。
任何一条隐式规则都不能在链中出现多次。这意味着make甚至不会考虑通过运行两次链接器从foo.o.o.o生成foo这样荒谬的事情。这种约束还有一个额外的好处,即可以防止在搜索隐式规则链时出现任何无限循环。
有一些特殊的隐式规则可以优化某些情况,否则这些情况将由规则链处理。例如,使用foo.o作为中间文件,可以通过编译和链接单独的链式规则来处理从foo.c生成foo。但实际发生的是,这种情况下的一个特殊规则用一个cc命令进行编译和链接。优化的规则优先于逐步链,因为它在规则排序中出现得更早。
最后,出于性能原因,make在搜索规则以构建隐式规则的先决条件时不会考虑非终端匹配任何规则(即“%:”)(请参阅MatchAnything Pattern rules)。