规则
make的规则有具体规则(explicit rule),模式规则(pattern rule),隐含规则(implicit rule)。
1.具体规则
(1) 我们编写到规则大部分是具体规则。规则不必一次定义完全(all at once),同一个目标可以分多次:
path.o:path.c make.h config.h
path.o: fiedef.h hash.h job.h
(2) 通配符的使用要谨慎:
*.o: constants.h
这个规则到目的是所有到目标文件都依赖constans.h,但是如果工作目录中并未包含任何目标文件,则通配符扩展后如下:
: constants.h
实现此规则的正确方法是针对源文件使用通配符(因为它们总是存在的)。当模式出现在工作目标或是必要条件中时,是由make进行通配符的扩展,但是当模式出现在命令中时,
由 subshell扩展。
(3) 假想工作目标
任何不代表文件到工作目标叫假想工作目标(phony target)。通常,make总会执行假想工作目标。
标准的假想工作目标:
all:执行编译应用程序的所有工作;
install:从已编译到二进制文件进行应用程序到安装;
clean:将产生自源代码的二进制文件删除;
distclean:删除编译过程中所产生的任何文件(除了二进制文件,还包括configure所产生到makefile);
TAGS:建立可供编辑器使用到标记表;
info:从Texinfo源码来创建GNU info文件;
check:执行与应用程序相关的任何测试。
(4)空工作目标
prog: size prog.o
$(CC) $(LDFLAGS) -o $@ $^
size: prog.o
size $^
touch size
size 规则在执行完之后,会使用touch创建一个名为size的空文件。这个空文件可作为它的时间戳,因此只在prog.o被更新后才会执行size规则。
通常空文件可用来标明最近发生了一个特殊事件。
(5)变量
自动变量
$@: 工作目标的文件名
$%: 档案文件成员结构中的文件名元素。若工作目标是foo.a(bar.o),则$%是bar.o, $@ 是foo.a。
$<: 第一个必要条件的文件名。
$?: 时间戳在工作目标之后的所有必要条件,并以空格隔开这些必要条件。
$^: 所有必要条件的文件名,并以空格隔开这些文件名。这份列表已删掉重复的文件名。
$+: 如$^,代表所有必要条件的文件名,并以空格隔开这些文件名,但是包括重复的文件名
$*: 工作目标的主文件名。一个文件名称是由两个部分组成:主文件名(stem)和扩展名(suffix)。不要在模式规则以外使用此变量。
为与其他版本的make兼容,有两个变体:一个变体只返回值的目录部分,指定方式是在原有的符号之后附加D这个字母,如$(@D),$(<D);另一个变体只返回值的文件部分,指定方式是在原有的符号之后附加F,如$(@F),$(<F)
2. 模式规则
(1) GNU make有很多的内置模式,--print-data-base选项列出内置模式。
(2)静态模式规则
静态模式可容易的用来定义多目标的规则,其语法:
<targets ...>: <target-pattern>: <prereq-patterns ...>
<commands>
...
targets定义了一系列的目标文件,可以有通配符。是目标的一个集合。
target-parrtern是指明了targets的模式,也就是的目标集模式。
prereq-parrterns是目标的依赖模式,它对target-parrtern形成的模式再进行一次依赖目标的定义。
例子:
objects = foo.o bar.o
all: $(objects)
$(objects): %.o: %.c
$(CC) -c $(CFLAGS) $< -o $@
扩展后,等价于:
foo.o : foo.c
$(CC) -c $(CFLAGS) foo.c -o foo.o
bar.o : bar.c
$(CC) -c $(CFLAGS) bar.c -o bar.o
(3)后缀规则
后缀规则有两种:双后缀和单后缀。
双后缀规则定义了一对后缀:目标文件的后缀和依赖目标(源文件)的后缀。如".c.o"相当于"%o : %c"。单后缀规则只定义一个后缀,也就是源文件的后缀。如".c"相当于"% : %.c"。如下:
.c.o:
$(CC) -c $(CFLAGS) $(CPPFLAGS) -o $@ $<
后缀规则不允许任何的依赖文件,如果有依赖文件的话,那就不是后缀规则,那些后缀统统被认为是文件名
要让make知道一些特定的后缀,我们可以使用伪目标".SUFFIXES"来定义或是删除,如:
.SUFFIXES: .hack .win
把后缀.hack和.win加入后缀列表中的末尾。
.SUFFIXES: # 删除默认的后缀
.SUFFIXES: .c .o .h # 定义自己的后缀
先清楚默认后缀,后定义自己的后缀列表。