GUN make (8) make的隐含规则

隐含规则为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中明确提及的文件都不被作为中间过程文件来处理。

 

当中间文件不存在时:

  • 对于一个普通文件,因为makefile没有提及,则此文件可能是一个目标的依赖,make在执行它所在的规则前会试图重建它。
  • 对于一个中间文件,因为没有明确提及,make不会去试图重建它。除非这个中间文件所依赖的文件被更新。

 

如果make在执行时需要一个中间过程文件,那么默认的动作是:这个中间过程文件在make执行结束后会被删除。

 

5. 模式规则

在模式规则中,目标名中需要包含有模式字符 % ,其可以匹配任何非空字符串。

模式字符 % 的匹配和替换发生在规则中所有变量和函数引用展开之后。

 

普通多目标规则(多目标中没有模式):

  • 将每一个目标作为一个独立的规则来处理,所以多个目标就对应多个独立的规则。

多目标模式规则:

  • 所有规则的目标 共同拥有 依赖文件和规则的命令行,当文件符合多个目标模式中的 任何一个时,规则定义的命令就有可能将会执行。
  • 在执行一次命令之后,规则不会再去检查是否需要重建符合其他模式的目标。
  • 当一个目标文件同时符合多个目标模式时,make将会把 第一个 目标匹配的模式规则作为重建它的规则。
  • makefile中明确指定的模式规则会覆盖隐含模式规则。
比如有如下 多目标模式 规则:
%.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命令创建这样一个空的源文件。

 

 

 

 

你可能感兴趣的:(makefile)