通配符
假如一个目标文件所依赖的依赖文件很多,那样岂不是我们要写很多规则,这显然是不合乎常理的,我们可以使用通配符,来解决这些问题。
我们对上节程序进行修改,代码如下:
test : a.o b.ogcc -o test $^%.o : %.cgcc -c -o $@ $<
- %.o表示所有的.o文件
- %.c表示所有的.c文件
- $@:表示目标文件
- $<:表示第一个依赖文件
- $^:表示所有依赖文件
假想目标:.PHONY
我们想清除文件,在Makefile的结尾处添加如下代码就可以了:
clean:rm *.o test
- 执行make,生成第一个目标文件
- 执行make clean:清除所有文件
make后面可以带上目标名,也可以不带,如果不带目标名的话就会生成第一个规则里面的第一个目标。
make [目标]也可以不跟目标名,若无目标默认第一个目标。我们直接执行make的时候,会在makefile里面找到第一个目标然后执行下面的指令生成第一个目标。
当我们执行make clean的时候,就会在Makefile里面找到clean这个目标,然后执行下面的命令。
这个写法有些问题,原因是我们的目录里面没有clean这个文件
如果该目录下面有名为clean文件怎么办?
我们在该目录下创建一个名为clean的文件,然后重新执行make clean,结果显示
make: \`clean' is up to date.
一个规则能够执行的条件:
- 目标文件不存在
- 依赖比目标新
现在目标文件有,但是没有依赖文件,就无法判断文件的时间。
有同名的“clean”文件时,就没有办法执行make clean操作。解决办法:我们需要把目标定义为假象目标,用关键字PHONY
.PHONY:clean
重定向输出
在Linux命令行中,>符号通常用于重定向输出。
当输入> newfile时,它的作用是将命令的输出重定向到一个名为newfile的文件。
如果newfile文件不存在,则它会被创建;如果已经存在,则文件的内容会被覆盖。
如果希望输出追加到文件而不是覆盖文件内容,则可以使用>>符号。
command >> newfile
这样command的输出追加到newfile文件的末尾。
变量
在makefile中有两种变量:
- 简单变量(即时变量)
A := xxx #A的值在定义时就确定了
- 延时变量
B = xxx #B的值在使用时才确定
想使用变量的时候使用$来引用,如果不想看到命令输出时,在前面加上@符号。
:= # 即时变量
= # 延时变量
?= # 延时变量, 如果是第1次定义才起效, 如果在前面该变量已定义则忽略这句
+= # 附加, 它是即时变量还是延时变量取决于前面的定义
?=: 如果这个变量在前面已经被定义了,这句话就会不会起效果
A := $(C)
B = $(C)
C = abc#D = 100ask
D ?= weidongshanall:@echo A = $(A)@echo B = $(B)@echo D = $(D)C += 123
输出
A =
B = abc 123
D = weidongshan
- A:=$©
A为即时变量,在定义时就确定,由于刚开始时C值为空,所以A的值也为空。 - B=$©
B为延时变量,只有使用到它的时候值才确定,当执行make时,会解析里面所有的变量,所以先解析C= abc,然后解析C += 123,此时,C = abc 123,当执行:@echo B = $(B) B的值为 abc 123。 - D?=weidongshan
D变量在前面没有定义,所以D的值为weidongshan,如果在前面添加D = 100ask,最后D的值为100ask。
我们还可以通过命令行存入变量的值 例如:
执行:make D=123456 里面的 D ?= weidongshan 这句话就不起作用了。
函数foreach
$(foreach var,list,text)
A = a b c
B = (foreach f, $(A), $(f).o)all:@echo B = $(B)
函数filter/filter-out
C = a b c d/D = $(filter %/, $(C))
E = $(filter-out %/, $(C))all:@echo D = $(D)@echo E = $(E)
wildcard
$(wildcard pattern)
这个函数会以pattern这个格式,去寻找存在的文件,返回存在文件的名字
files = $(wildcard *.c)all:@echo files = $(files)
我们也可以用wildcard函数来判断,真实存在的文件
files2 = a.c b.c c.c d.c e.c abc
files3 = $(wildcard $(files2))all:@echo files3 = $(files3)
patsubst函数
files2 = a.c b.c c.c d.c e.c abcdep_files = $(patsubst %.c, %.d, $(files2))all:@echo dep_files = $(dep_files)