接上一篇 makefile规则继续聊聊makefile语法。
- 通配符:
如果我们有大量的.c文件,我们要为每一个.c生成.o文件写一条规则,显然是不可能的,makefile使用通配符解决这种重复性的规则:
test : a.o b.o
gcc -o test a.o b.o
%.o : %.c
gcc -c -o $@ $<
%通配符,当想生成a.o文件时发现与%.o : %.c匹配,则将%替换为a,也就是a.o : a.c,则会执行规则的命令。
命令中的$@只目标文件,$<表示第一个依赖。
这样我们增加多个c.c文件时只需要修改第一条规则:
test : a.o b.o c.o
gcc -o test a.o b.o c.o
%.o : %.c
gcc -c -o $@ $<
使用通配符减少了makefile的书写。
其实我们还可以简化书写,使用$^来代替所有的依赖:
test : a.o b.o c.o
gcc -o test $^
%.o : %.c
gcc -c -o $@ $<
% 表示通配符
$@ 表示目标
$< 表示第1个依赖文件
$^ 表示所有依赖文件
- 假想目标:.PHONY
添加一个清除文件命令:
test : a.o b.o c.o
gcc -o test $^
%.o : %.c
gcc -c -o $@ $<
clean:
rm *.o test
使用make clean命令,则会清除所有.o文件与test文件
如果我们的目录中有一个名为clean的文件,则执行make clean的时候会失败,因为根据makefile的语法,检查clean文件已经是最新的,不会执行这个规则。解决方法就是使用假想目标:
test : a.o b.o c.o
gcc -o test $^
%.o : %.c
gcc -c -o $@ $<
clean:
rm *.o test
.PHONY: clean
当将clean定义为假想目标后,就不会去判断clean文件了,make ckean 成功执行删除操作
注:makefile使用:make [目标] 若无目标,默认执行第一个目标
- 即时变量、延时变量
即时变量 A := xxx # A的值在定义时立即确定
延时变量 B = xxx # B的值在使用到的时候才确定
延时变量 C ?=xxx #表示如果是第一次定义C才起效,如果已经定义过则忽略
附加变量 D +=xxx #具体是即时变量还是延时变量,取决与D的定义。
#$()表示引用变量
A := $(C)
B = $(C)
C = abc
all:
@echo A = $(A)
@echo B = $(B)
输出:
A =
B = abc
由于A在定义的时候没有C变量,所有A为空。B是运行时赋值,makefile会先加载整个文件,再运行,所以此时C已经有值,B = abc了
A := $(C)
B = $(C)
C = abc
D = zhang
D ?= yang
all:
@echo A = $(A)
@echo B = $(B)
@echo D = $(D)
C += 123
输出:
A =
B = abc 123
D = zhang
由于D已经定义过了,所以 D ?= yang 被忽略
我们还可以再执行make的时候传入变量,如:
D ?= yang
all:
@echo D = $(D)
执行 make D=zhang,输出:D = zhang 而D ?= yang又被忽略。