分类: LINUX
2010-11-14 18:47:59
一、隐含规则的使用
使用make内嵌的隐含规则,我们的makefile中就不需要明确给出重建某一个目标的命令,甚至可以不用写出明确的规则。Make会自动根据已存在或者可以被创建的源文件类型来启动相应的隐含规则。
二、make的隐含规则
1. 编译C程序
“N.o”自动由“N.c”生成,执行命令为“$(CC) –c $(CPPFLAGS) $(CFLAGS)”。
2. 汇编和需要预处理的汇编程序
“N.s”是不需要预处理的汇编源文件,“N.S”是需要预处理的汇编源文件。汇编器为“as”。
“N.o” 可自动由“N.s”生成,执行命令是:“$(AS) $(ASFLAGS)”。
“N.s” 可由“N.S”生成,C预编译器“cpp”,执行命令是:“$(CPP) $(CPPFLAGS)”。
3. 链接单一的object文件
“N”自动由“N.o”生成,通过C编译器使用链接器(GUN ld),执行命令是:“$(CC)
$(LDFLAGS) N.o $(LOADLIBES) $(LDLIBS)”。
此规则仅适用:由一个源文件可直接产生可执行文件的情况。当需要有多个源文件共同来创建一个可执行文件时,需要在Makefile中增加隐含规则的依赖文件。例如:
x : y.o z.o
当“x.c”、“y.c”和“z.c”都存在时,规则执行如下命令:
cc -c x.c -o x.o
cc -c y.c -o y.o
cc -c z.c -o z.o
cc x.o y.o z.o -o x
rm -f x.o
rm -f y.o
rm -f z.o
三、隐含变量
代表命令的变量:
AR
函数库打包程序,可创建静态库.a文档。默认是“ar”。
AS
汇编程序。默认是“as”。
CC
C编译程序。默认是“cc”。
CPP
C程序的预处理器(输出是标准输出设备)。默认是“$(CC) –E”。
RM
删除命令。默认是“rm –f”。
代表命令参数的变量:下边的是代表命令执行参数的变量。如果给出默认值则默认值为空。
ARFLAGS
执行“AR”命令的命令行参数。默认值是“rv”。
ASFLAGS
执行汇编语器“AS”的命令行参数(明确指定“.s”或“.S”文件时)。
CFLAGS
执行“CC”编译器的命令行参数(编译.c源文件的选项)。
CXXFLAGS
执行“g++”编译器的命令行参数(编译.cc源文件的选项)。
CPPFLAGS
执行C预处理器“cc -E”的命令行参数(C 和 Fortran 编译器会到)。
LDFLAGS
链接器参数。(如:“ld”)
四、模式规则
在模式规则中,目标的定义需要包含%字符,包含%的目标被用来匹配一个文件名,%可以匹配任何非空字符串。规则的依赖文件同样可以使用%,依赖中的%的取值情况由目标中的%来决定。
需要注意的是:%的替换是在规则的其他变量和函数引用扩展完成之后进行的,变量和函数的展开一般发生在make读取makefile时,而模式规则中的%则发生在make的执行过程。
1、 模式规则的介绍
%.o : %.c
Command
这个模式规则指定了如何由文件N.c来创建文件N.o,文件N.c应该是已经存在的或者可被创建的。模式规则的依赖中可以不包含模式字符%。当不包含模式字符时,它的含义是所有字符目标模式的目标文件都依赖于一个指定的文件。
模式规则需说明的:
A、 模式规则在makefile中的顺序需要注意,当一个目标文件符合多个模式规则的目标时,make将会按照第一个找到的作为重建它的规则。
B、 在makefile中指定的模式规则会覆盖隐含的模式规则,就是说在makefile中明确指定的会替代隐含的模式规则
C、 另外,依赖文件存在或者被提及的规则,优先于那些需要使用隐含规则来创建其依赖的文件的规则。
2、 模式的匹配
通常,模式规则中目标模式由前缀、后缀、模式字符“%”组成,这三个部分中可以同时两部分为空。实际的文件名应该是以模式指定的前缀开始、后缀结束的任何文件名。文件名中除前缀和后缀以外的所有部分我们称之为“茎”(模式字符“%”可以代表若干字符。因此:模式“%.o”所匹配的文件“test.c”中“test”就是“茎”)。模式规则中依赖文件名的确定过程是:在处理模式规则时。首先根据规则定义的目标模式匹配实际的目标文件,确定“茎”,之后使用 “茎”替代规则依赖文件名中的模式字符“%”,生成依赖文件名。这样就形成了一个明确指定了目标和依赖文件的规则。例如模式规则:“%.o : %.c”,当“test.o”需要重建时将形成规则“test.o : test.c”。
当目标模式中包含斜杠(目录部分)。在进行目标文件匹配时,文件名中包含的目录字符串在匹配之前被移除,只进行基本文件名的匹配;匹配成功后,再目录加入到匹配之后的字符串之前形成“茎”。文字的描述看起来比较复杂,来看一个例子:例如目标模式为“e%t”,文件“src/eat”匹配于这个目标模式,那么“茎”就是“src/a”;模式规则中依赖文件的产生是:首先使用“茎”非目录部分(“a”)替代依赖文件中的模式字符“%”,之后再将目录部分(“src/”)加入到形成的依赖文件名之前构成依赖文件的全路径名。这里如果模式规则的依赖模式为“c%r”,则那么目标“src/eat”对应的依赖文件就为“src/car”。
3、 万用规则
当一个模式规则的目标为“%”(它可以匹配任何文件名)时,我们称这个规则为万用规则。它非常有用,但是使用它可能会影响make的效率,因为make执行时将会为所有的规则的目标和依赖文件考虑万用规则。
为了避免由于万用规则所带来的效率问题,可以对万用规则的使用加以限制。通常有两种方式来实现,在定义万用规则时可以使用两者之一来对其进行限制:
A、 将万用规则设置为最终规则,定义时使用双冒号规则。作为最终规则,此规则只有在它的依赖文件存在时才能被应用,即使它的依赖可以由隐含规则创建也不行。就是说,最终规则中没有进一步的“链”。
B、特殊的内嵌伪模式规则用来指定一些特定的文件,避免在处理这些这种文件名的文件时使用非最终万用规则。这些伪模式规则没有依赖和命令行,用在其它的场合时被忽略。例如,内嵌的隐含规则:“%.p :”保证Pascal源程序如“foo.p”匹配特定的目标格式,从而避免make寻找“foo.p.o”或“foo.p.c”。 在后缀规则中,为后缀列表中的每一个有效后缀创建了一个“%.p”形式的伪模式规则。
4、 重建内嵌隐含规则
对隐含规则,我们可以对它进行重建。重建一个隐含规则时,需要使用相同的目标和依赖文件,但是命令可以不同。这样就替代了有相同目标和依赖的那个make内嵌的规则,替代之后的隐含规则的顺序由它在Makefile中的位置决定。例如通常我们Makefile中可能会包含这样一个规则:
%.o : %.c
$(CC) $(CFLAGS) –D__DEBUG__ $< -o $@
这个模式规则替代了编译.c文件的内嵌隐含规则。
5、 缺省规则
有时需要定义一个缺省的规则,当在Makefile中没有重建的规则时(没有重建它的明确规则和可用的隐含规则)。就是用这个规则来重建它。就是说,当所需要的重建的目标文件没有可用的命令时、就执行这个缺省规则的命令来创建它。
定义这样一个规则,我们可以使用最终万用规则来实现。例如:在调试Makefile时(可能一些源文件还没有完成),我们所关心的是Makefile中规则的正确执行,而不关心源文件的内容。这样我们就可以使用没有内容的源文件来代替。可以在Makefile中定义这样一个规则:
%::
touch $@
对没有找到的所有的.c文件使用“touch”命令创建一个空的文件。实现一个缺省规则的方式也可以不使用万用规则来实现,可以使用伪目标“.DEFAULT”实现。上边的例子也可以这样来书写:
.DEFAULT :
touch $@
对于没有命令行的伪目标“.DEFAULT”,其含义是取消前边所有使用“.DEFAULT”指定的缺省执行命令。同样,也可以让这个缺省的规则不执行任何命令(给它定义个一个空命令)。
另外缺省规则也可用来实现在一个Makefile中重载另一个makefile文件。
6、 隐含规则的搜索方法
对于目标“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”的命令时,使用自动化变量表示规则中的依赖文件和目标文件。
文件:
makefile的隐含规则.pdf
大小:
95KB
下载:
下载
chinaunix网友2010-11-15 15:57:41
很好的, 收藏了 推荐一个博客,提供很多免费软件编程电子书下载: http://free-ebooks.appspot.com