隐含规则为make提供了一类目标文件通用方法,不需要在makefile中明确的给出重建特定目标文件所需的细节描述。
只要目标文件中除后缀以外其他部分相同,make都能够使用若干隐含规则来最终产生这个目标文件。
对应关系:
EXENAME.o 对应 EXENAME.c
EXENAME 对应 EXENAME.o
1.隐含规则的使用
foo:foo.o
cc -o foo foo.o $(CFLAGS) $(LDFLAGS)
这里并没有给出重建文件foo.o的规则,在make执行这条规则的时候,无论foo.o存在与否,都会试图根据隐含规则来重建这个文件。
可以使用 -r 或者 -R 参数取消隐含规则
2.常用隐含规则
编译c程序:
N.o 自动由 N.c 生成,执行命令 $(CC) -c $(CPPFLAGS) $(CFLAGS)
链接单一的object文件
N 自动由 N.o 生成,执行命令 $(CC) $(LDFLAGS) N.o $(LOADLIBES) $(LDLIBS)
3. 隐含变量
内嵌隐含变量的命令中,所使用的变量都是预定义的变量,我们称之为隐含变量。
在makefile中,通过命令行参数或者设置系统环境变量来对它进行重定义。
隐含规则中所使用的隐含变量分为两类:
3.1 代表命令的变量
AR 函数库打包程序,可以创建静态库.a文档,默认是 ar
AS 汇编程序,默认 as
CC c编译程序,默认是cc
CPP c程序的预处理器,默认是 $(CC) -E
YACC yacc文法分析器,默认命令是 yacc
RM 删除命令, 默认是rm -f
3.2 代表参数的变量
ARFLAGS 执行AR命令的命令行参数,默认是 rv
ASFLAGS 执行汇编语器 AS 的命令行参数
CFLAGS 执行CC编译器的命令行参数
YFLAGS yacc文法分析器参数
4. make隐含规则链
如果一个目标文件需要一系列隐含规则才能完成它的创建,则把这个系列称为一个 链。
中间过程文件:
文件N.c不存在也没有在makefile中提及的情况,只要存在N.y这个文件,那么make也会经过这两个步骤来重建N.o :
N.y -> N.c -> N.o
其中,N.c就在中间过程文件。并且会自动加入到依赖关系链中。
在Makefile中明确提及的文件都不被作为中间过程文件来处理。
当中间文件不存在时:
如果make在执行时需要一个中间过程文件,那么默认的动作是:这个中间过程文件在make执行结束后会被删除。
5. 模式规则
在模式规则中,目标名中需要包含有模式字符 % ,其可以匹配任何非空字符串。
模式字符 % 的匹配和替换发生在规则中所有变量和函数引用展开之后。
普通多目标规则(多目标中没有模式):
多目标模式规则:
比如有如下 多目标模式 规则:
%.o %.x : %.c
$(CC) $(CFLAGS) $< -o $@
当执行make foo.o foo.c时,会只看到第一个目标foo.o被创建,同时make会提示foo.x文件是最新的,其实foo.x并没有被创建。
6. 自动化变量
自动化变量的取值取决于所执行的规则的目标和依赖的文件名。
有以下自动化变量:
$@ 表示规则的文件名
$% 当规则的目标文件是一个静态库文件时,代表静态库的一个成员名。如果目标不是静态库,其值为空。
$< 规则的第一个依赖文件名。
$? 所有比目标文件更新的依赖文件列表,空格分隔。
$^ 规则的所有依赖文件列表,使用空格分隔。
$+ 类似于$^,但是保留了依赖文件中重复出现的文件。
$* 在模式规则和静态模式规则中,代表 茎,茎 是目标模式中 % 所代表的部分。
$(@D) 表示目标文件的目标部分,不包括斜杠。如果$@是 dir/foo.o 则$(@D) 为 dir
$(@F) 表示目标文件完整文件名中除目录以外的部分。如果$@是 dir/foo.o 则$(@F) 为 foo.o
$(*D)
$(*F) 表示目标 茎 中的目录和文件名部分。
$(%D)
$(%F) 当目标为静态库时,表示库文件成员中目录部分和文件名部分。
$( $( $(^D) $(^F) 表示规则中所有依赖文件的目录部分和文件名部分。 $(+D) $(+F) 表示规则中所有依赖文件的目录部分和文件名部分(可存在重复文件)。 $(?D) $(?F) 表示被更新的依赖文件的目录部分和文件名部分。 7. 万用规则 当模式规则的目标只有一个模式字符 % ,我们称之为 万用规则。 使用万用规则会导致make执行时考虑的情况变多,从而效率降低,所以需要对万用规则的使用进行限制: 将万用规则设置为最终规则,定义时使用双冒号规则。作为最终规则,此规则只有在它的依赖文件存在时才能被应用。即使它的依赖可以由隐含规则创建也不行。 8.缺省规则 在make执行过程中无法为一个文件找到合适的重建规则,那么就用缺省规则去创建。 比如: %::
touch $@
执行make时,对所有不存在的.c文件将会使用touch命令创建这样一个空的源文件。