一、后缀规则

后缀规则是一种古老定义隐含规则的方式,在新版本的make中使用模式规则作为对它的替代,模式规则相比后缀规则更加清晰明了。在现在版本中保留它的原因是为了能够兼容旧的makefile文件。后缀规则有两种类型:“双后缀”和“单后缀”。

双后缀规则定义一对后缀:目标文件的后缀和依赖目标的后缀。它匹配所有后缀为目标后缀的文件。对于一个匹配的目标文件,它的依赖文件这样形成:将匹配的目标文件名中的后缀替换为依赖文件的后缀得到。如:一个描述目标和依赖后缀的“.o”和“.c”的规则就等价于模式规则“%o : %c”。

单后缀规则只定义一个后缀:此后缀是源文件名的后缀。它可以匹配任何文件,其依赖文件这样形成:将后缀直接追加到目标文件名之后得到。例如:单后缀“.c”就等价于模式规则“% : %.c”。

判断一个后缀规则是单后缀还是双后缀的过程:判断后缀规则的目标,如果其中只存在一个可被make识别的后缀,则规则是一个“单后缀”规则;当规则目标中存在两个可被make识别的后缀时,这个规则就是一个“双后缀”规则。

例如:“.c”和“.o”都是make可识别的后缀。因此当定义了一个目标是“.c.o”的规则时。make会将它作为一个双后缀规则来处理,它的含义是所有“.o”文件的依赖文件是对应的“.c”文件。下边是使用后追规则定义的编译.c源文件的规则:

  .c.o:

$(CC) -c $(CFLAGS) $(CPPFLAGS) -o $@ $<

  注意:一个后缀规则中不存在任何依赖文件。否则,此规则将被作为一个普通规则对待。因此规则:

.c.o: foo.h

$(CC) -c $(CFLAGS) $(CPPFLAGS) -o $@ $<

就不是一个后缀规则。它是一个目标文件为“.c.o”、依赖文件是“foo.h”的普通规则。它也不等价于规则:

%.o: %.c foo.h

$(CC) -c $(CFLAGS) $(CPPFLAGS) -o $@ $<

需要注意的是:没有命令行的后缀规则是没有任何意义的。它和没有命令行的模式规则不同,它也不能取消之前使用后追规则定义的规则。它所实现的仅仅是将这个后缀规则作为目标加入到make的数据库中。

可识别的后缀指的是特殊目标“.SUFFIXES”所有依赖的名字。通过给特殊目标“SUFFIXES”添加依赖来增加一个可被识别的后缀。像下边这样:

.SUFFIXES: .hack .win

它所实现的功能是把后缀“.hack”和“.win”加入到可识别后缀列表的末尾。

如果需要重设默认的可识别后缀,因该这样来实现:

.SUFFIXES:          #删除所有已定义的可识别后缀

.SUFFIXES: .c .o .h   #重新定义

首先使用没有依赖的特殊目标“.SUFFIXES”来删除所有已定义的可识别后缀;之后再重新定义。

注意:make的“-r”或“-no-builtin-rules”可以清空所有已定义的可识别后缀。

在make读取所有的makefile文件之前,变量“SUFFIXE”被定义为默认的可识别后缀列表。虽然存在这样一个变量,但是请不要通过修改这个变量值的方式来改变可识别的后缀列表,应该使用特殊目标“.SUFFIXES”来实现。

二、隐含规则搜索法

对于目标“T”,make为它搜索隐含规则的算法如下。此算法适合于:1. 任何没有命令行的双冒号规则;2. 任何没有命令行的普通规则;3. 那些不是任何规则的目标、但它是另外某些规则的依赖文件;4. 在递归搜索过程中,隐含规则链中前一个规则的依赖文件。

在搜索过程中没有提到后缀规则,因为所有的后缀规则在make读取Makefile时,都被转换为对应的模式规则。

对于形式为“ARCHIVE(MEMBER)”的目标,下边的算法会执行两次,第一次的目标是整个目标名“T”(“ARCHIVE(MEMBER)”),如果搜索失败,进行第二次搜索,第二次以“member”作为目标来搜索。

搜索过程如下:

1.        将目标“T”的目录部分分离,分离后目录部分称为“D”,其它部分称“N”。例如:“T”为“src/foo.o”时,D就是“src/”,“N”就为“foo.o”。

2.        列出所有和“T”或者“N”匹配的模式规则。如果模式规则的目标中包含斜杠,则认为和“T”相匹配,否则认为此模式规则和“N”相匹配。

3.        只要这个模式规则列表中包含一个非万用规则的规则,那么将列表中所有的非最终万用规则删除。

4.        删除这个模式规则列表中的所有没有命令行的规则。

5.        对于这个模式规则列表中的所有规则:

a)       计算出模式规则的“茎”S,S应该是“T”或“N”中匹配“%”的非空的部分。

b)       计算依赖文件。把依赖中的“%”用“S”替换。如果目标模式中不包含斜杠,则把“D”加在替换之后的每一个依赖文件开头,构成完整的依赖文件名。

c)        测试规则的所有依赖文件是否存在或是应该存在(一个文件,如果在Makefile中它作为一个明确规则的目标,或者依赖文件被提及,我们就说这个文件是一个“应该存在”的文件)。如果所有的依赖文件都存在、应该存在或是这个规则没有依赖。退出查找,使用该规则。

6.        截止到第5步,合适的规则还是没有被找到,进一步搜索。对于这个模式规则列表中的每一规则:

a)       如果规则是一个终止规则,则忽略它,继续下一条模式规则。

b)       计算依赖文件(同第5步)。

c)        测试此规则的依赖文件是否存在或是应该存在。

d)       对于此规则中不存在的依赖文件,递归的调用这个算法查找它是否可由隐含规则来创建。

e)       如果所有的依赖文件存在、应该存在、或是它可以由一个隐含规则来创建。退出查找,使用该规则。

7.        如果没有隐含规则可以创建这个规则的依赖文件,则执行特殊目标“.DEFAULT”所指定的命令(可以创建这个文件,或者给出一个错误提示)。如果在Makefile中没有定义特殊目标“DEFAULT”,就没有可用的命令来完成“T”的创建。make退出。

一旦为一类目标查找到合适的模式规则。除匹配“T”或者“N”的模式以外,对其它模式规则中的目标模式进行配置,使用“茎”S替换其中的模式字符“%”,将得到的文件名保存直到执行命令更新这个目标文件(“T”)。在命令执行以后,把每一个储存的文件名放入数据库,并且标志为已更新,其时间戳和文件“T”相同。

在执行更新文件“T”的命令时,使用自动化变量表示规则中的依赖文件和目标文件。

posted on 2011-12-06 23:07  风行雪舞  阅读(657)  评论(0编辑  收藏  举报
无觅相关文章插件,快速提升流量