点击蓝字
关注我们
在前一篇文章讲解了Makefile的一些概念和原理,接下来说说Makefile的一些知识点。
make与make clean
生成目标文件规则(make命令):
执行make命令则会根据当前目录的Makefile文件定义的规则生成对应的目标文件。
如果Makefile为其他名字,比如makefile.linux,则需要使用make的参数(-f or –file)执行对应的Makefile文件,例如:
make -f makefile.linux
清空目标文件的规则(make clean命令):
每个Makefile中都应该写一个清空目标文件(
.o
和目标文件等)的规则,这不仅便于重编译,也很 利于保持文件的清洁。也许在写Makefile的时候,都要养成这样一个习惯,一般的风格都是:
clean: rm $(obj) *.o
更为稳健的做法是(原因:如果当前目录存在clean文件,该命令会执行失败),解决办法:增加伪目标:.PHONY:clean:
.PHONY:cleanclean: rm $(obj) *.o
注意:
-
clean
的规则不要放在文件 的开头,不然,会变成make的默认目标,一般:clean从来都是放 在文件的最后。
书写规则
显示规则(@字符):
当用@字符在命令前面时,那么执行这条命令的时候,这条命令不会显示出来。对比:
命令前加@字符例子:
rice@rice:~/rice_file/mkfile$ cat Makefile exec: @echo "rice makefile"rice@rice:~/rice_file/mkfile$ makerice makefile
命令前不加@字符例子:
rice@rice:~/rice_file/mkfile$ cat Makefile exec: echo "rice makefile"rice@rice:~/rice_file/mkfile$ makeecho "rice makefile"rice makefile
注意:
make命令参数
-s
或
--silent
或
--quiet
则是全面禁止命令的显示
命令执行规则:
当依赖目标新于目标时,make会一条一条的执行其后的命令。其中,加入要让上一条命令的结果应用在下一条命令时,应使用
分号分隔这两条命令,并且不能将两条命令写在
同一行。
例子1:
Makefile:
exec: @cd /home/rice @pwd
结果:
/home/rice/rice_file/mkfile
例子2:
Makefile:
exec: @cd /home/rice;pwd
结果:
/home/rice
从上面两个例子可以证明命令依赖的规则。
命令出错规则(-符号):
当命令运行完,make会检测每个命令的返回码,如果返回成功,那make会执行下一条命令,当规所有的命令成功返回后,make执行完成。如果一个规则中的某个命令出错了(命令退出码 非零),那么make就会终止执行当前规则,这将有可能终止所有规则的执行。
有时命令的出错并不表示错误。例如mkdir命令,建立一个目录,如果目录不存 在,则mkdir不会出现错误。如果目录已存在,那么将产生错误。从例子说明,mkdir的出错并没有对其他命令产生影响,因为我只要目录存,所以mkdir出错不应该终止命令规则的运行。
为了解决上述问题,只需要在Makefile的命令行前加一个符号
-,即使命令执行出错,也依然继续执行后续的命令。
.PHONY:cleanclean: -rm $(obj) *.o
变量
变量的定义
Makefile
也支持变量定义,变量的定义也让的我们的Makefile
更加简化,可复用。
变量的定义:一般采用大写字母,赋值方式像C
语言的赋值方式一样。
DIR = ./src/
变量取值:使用括号将变量括起来再加美元符。
FOO = $(DIR)
Makefile
除了使用’=’
进行赋值,还有其他赋值方式,比如’:=’
和’?=’
,接下来我们来对比一下这几种的区别:
赋值符’=’:
PARA = RICECURPARA = $(PARA)PARA = riceprint: @echo $(CURPATA)
结果为:
rice
变量CURPARA
的值并不是“RICE”
。其值为PARA
最后一次赋值的值。说明,赋值符“=”
,可以借助另外一个变量,
可以将变量的真实值推到后面去定义。也就是变量的真实值取决于它所引用的变量的最后一次有效值。
赋值符’:=’:
PARA = RICECURPARA := $(PARA)PARA = riceprint: @echo $(CURPATA)
结果为:
RICE
变量CURPARA的值为“RICE”。“=”和“:=”的区别就在这里,“:=”只取第一次被赋值的值。
赋值符’?=’:
PARA = RICEPARA ?= riceprint: @echo $(PATA)
结果为:
RICE
如果上面例子第一行去掉,结果为:
rice
说明,如果变量PARA
前面没有被赋值,那么此变量就是“rice”
,如果前面已经赋值过,那么就使用前面赋的值。
赋值符’
+=’:Makefile
中的变量是字符串,有时候我们需要给前面已经定义好的变量添加一些字符串进去,
此时就要使用到符号”+=”:
OBJ = main1.o main2.oOBJ += main3.o
OBJ
的值为:”main1.o
,main2.o
,main3.o“
。说明“+=”
用作与变量的追加。
系统自带变量:
系统自定义了一些变量,通常都是大学,比如CC
,PWD
,CLFAG
等等,有些有默认值,有些没有,比如以下几种,如下
-
CPPFLAGS:预处理器需要的选项,如:-l
-
CFLAGS:编译的时候使用的参数-Wall -g -c
-
LDFLAGS:链接库使用的选项-L -l
其中:默认值可以被修改,比如CC
默认值是cc
,但可以修改为gcc
:CC=gcc
自动变量:
Makefile
的语法提供一些自动变量,这些变量可以让我们更加快速的完成Makefile
的编写,其中自动变量只能在规则中的命令使用,常用的自动变量如下:
-
$@:规则中的目标
-
$<:规则中的第一个依赖文件
-
$^:规则中的所有依赖文件
CC = gccOBJ = main.o add.ooutput: $(OBJ) $(CC) -o $@ $^main.o: main.c $(CC) -c $<add.o: add.c $(CC) -c $<.PHONY:cleanclean: @rm $(OBJ) output
模式规则
模式规则实在目标及依赖中使用%
来匹配对应的文件,我们依旧使用上面的例子,采用模式规则格式,如下:
CC = gccOBJ = main.o add.ooutput: $(OBJ) $(CC) -o $@ $^%.o: %.c $(CC) -c $<.PHONY:cleanclean: @rm $(OBJ) output
其中:
main.o
由main.c
生成 add.o
由add.c
生成
函数
Makefile
提供了大量的函数,其中我们经常使用的函数主要有两个(wildcard
,patsubst)。
wildcard
函数:用于查找指定目录下指定类型的文件,函数参数:目录+
文件类型,使用方法:
SRC = $(wildcard ./src/*.c)print: @echo $(SRC)
结果:
./src/add.c ./src/main.c
表示:找到目录./src
下所有后缀为.c
的文件,并赋值给变量SRC
。命令执行完,SRC
变量的值:./src/add.c ./src/main.c
patsubst函数:用于匹配替换。函数参数:原模式+目标模式+文件列表,使用方法:
SRC = $(wildcard ./src/*.c)OBJ = $(patsubst %.c, %.o, $(SRC))print: @echo $(OBJ)
结果:
./src/add.o ./src/main.o
表示:把变量中所有后缀为.c
的文件替换为.o
。命令执行完,OBJ
变量的值:./src/add.o ./src/main.o
我将持续更新文章和学习资料
可加作者的微信一起交流学习
—作者微信号:wueroo1314—
获取交流群,请添加作者微信
饭仔DIY
微信号 : Rice_DIY
技术 | 开源 | 分享
长按关注。。。