makefile的自动化变量

1
2
3
$< 表示第一个依赖文件,即依赖目标中的第一个目标名字。如果依赖目标是以模式(即%)定义的,那么$<将是符合模式的一系列的文件集。注意是一个一个取出来的。
$^ 表示所有的依赖目标的集合。以空格分隔。如果在依赖目标中有多个重复的,会自动去除重复的依赖目标,只保留一份。
$@ 表示规则中的目标集。在模式规则中,如果有多个目标,那么$@就是匹配于目标中模式定义的集合。

静态模式

1
2
3
4
5
6
7
<targets ...> : <target-pattern> : <prereq-patterns>
	<commands>
	...
其中 
	targets: 定义了一系列的目标文件,可以有通配符,是目标的一个集合
	target-parrtern 是指明了targets的模式,也就是目标集模式
	prereq-parrterns 是目标的依赖模式,它对target-parrtern形成的模式再进行一次依赖目标的定义。

下面看一个例子

1
2
3
4
5
6
7
8
9
objs = foo.o bar.o
all: $(objs)

$(objs): %.o : %c
	$(CC) -c $(CFLAGS) &< -o $@ 
	
可以写成下边的样子
%.o:%.c:
	$(CC) -c $(CFLAGS) &< -o $@ 

例子中目标从$objs中获取, %.o是变量$objs的模式,及所有以.o结尾的目标。依赖模式是%.c,也就是所有.o文件替换为.c作为依赖的文件名。

书写命令

@:省略命令

1
2
3
exec:
	@echo "xxx正在编译"
make exec时输出 "xxx正在编译" 而隐藏了命令echo

-:忽略错误,标记不管命令出不出错都认为是成功的

1
2
clean :
	-rm -f *.o

使用变量

在makefile中变量是可以使用后边的变量来定义的。

1
2
3
4
5
6
7
foo = $(bar)
bar = $(ugh)
ugh = Huh?

all:
	echo $(foo) 
#执行make输出Huh?

好处就是可以把变量的真实值推到后边定义;

缺点是一旦发生嵌套定义就会报错,或者导致不可预知的错误。

:=

这种方法定义的变量,前面的变量不能使用后边的变量,只能使用前边已经定义的变量。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
x := foo
y := $(x) bar
x := later
其等价于
y := foo bar
x := later

a := $(b) bar
b := foo
 a的值是 bar b的值是 foo

?=

1
2
FOO ?= bar
其含义是如果FOO没有被定义过,那么变量FOO的值就是bar,如果FOO先前被定义过,那么这条语句什么都不干。

+=

追加变量值

1
2
3
objects = main.o foo.o bar.o utils.o
objects += another.o
$(objects)的值是 main.o foo.o bar.o utils.o another.o

隐含规则

老式风格的“后缀规则”

双后缀: 双后缀规则定义了一对后缀:依赖目标(源文件)的后缀和目标文件的后缀。比如 .c.o相当于 %.o:%.c。

1
2
.c.o:
	$(CC) -c $(CFLAGS) $(CPPFLAGS) -o $@ $<

单后缀:但后缀规则只定义一个后缀。

后缀规则不允许任何的依赖文件,如果有依赖文件的话,那就不是后缀规则,那些后缀统统被认为是文件名。