目录
一、何为 Makefile
二、使用注意事项
三、Make 的执行过程:
四、Makefile语法
1、归则格式
2、四种赋值方式
3、模式归则
4、自动化变量
5、伪目标
6、Makefile 条件判断
7、Makefile函数
<1>、函数 subst
<2>、函数 patsubst
<3>、函数 dir
<4>、函数 notdir
<5>、函数 foreach
<6>、函数 wildcard
如果我们的工程只有一两个 C 文件还好,需要输入的命令不多,当文件有几十、上百甚至上万个的时候用终端输入 GCC 命令的方法显然是不现实的。描述哪些文件需要编译、哪些需要重新编译的文件就叫做 Makefile,Makefile 就跟脚本文件一样,Makefile 里面还可以执行系统命令。
1.在工程目录下创建名为“Makefile”的文件,文件名一定要叫做“Makefile”!!!区分大小写的哦!
2.代码中所有行首需要空出来的地方一定要使用“TAB”键!不要使用空格键!
3.Makefile 中的变量都是字符串!$(objects)
4.注释是“#” !
1、make 命令会在当前目录下查找以 Makefile(makefile 其实也可以)命名的文件。
2、当找到 Makefile 文件以后就会按照 Makefile 中定义的规则去编译生成最终的目标文件。
3、当发现目标文件不存在,或者目标所依赖的文件比目标文件新(即最后修改时间比目标文件晚)的话就会执行后面的命令来更新目标。
目标...: 依赖...
命令1
命令2
...
main : main.o input.o calcu.o
gcc -o main main.o input.o calcu.o
= 变量的真实值取决于它所引用的变量的最后一次有效值。
:= 不会使用后面定义的变量,只能使用前面已经定义好的。
?= 如果变量前面没有被赋值,那么此变量就是当前 ?= 赋值,如果前面已经赋过值了,那么就使用前面赋的值。
+= 变量的追加。相当于追加一些字符串。
模式规则中,至少在规则的目标定定义中要包涵“%”,否则就是一般规则,目标中的“%”表示对文件名的匹配,“%”表示长度任意的非空字符串,比如“%.c”就是所有的以.c 结尾的文件,类似与通配符。
%.o : %.c
命令
所谓自动化变量就是这种变量会把模式中所定义的一系列的文件自动的挨个取出,直至所有的符合模式的文件都取完,自动化变量只应该出现在规则的命令中。
$@ 表示目标文件
$^ 表示所有的依赖文件
$< 表示第一个依赖文件
$? 表示比目标还要新的依赖文件列表
一般的目标名都是要生成的文件,而伪目标不代表真正的目标名,执行 make 命令时通过指定这个伪目标来执行其所在规则定义的命令。
使用伪目标主要是为了避免 Makefile 中定义的执行命令的目标和工作目录下的实际文件出现名字冲突。
clean:
rm *.o
rm main
工作目录下永远都不会存在文件 clean,当我们输入“make clean”以后,后面的“rm *.o”和“rm main”总是会执行。可是如果我们“手贱”,在工作目录下创建一个名为“clean”的文件,那就不一样了,当执行“make clean”的时候,规则因为没有依赖文件,所以目标被认为是最新的,因此后面的 rm 命令也就不会执行,我们预先设想的清理工程的功能也就无法完成。为了避免这个问题,我们可以将 clean 声明为伪目标,声明方式如下:
.PHONY : clean
声明 clean 为伪目标以后不管当前目录下是否存在名为“clean”的文件,输入“make clean”的话规则后面的 rm 命令都会执行。
<条件关键字>
<条件为真时执行的语句>
endif
<条件关键字>
<条件为真时执行的语句>
else
<条件为假时执行的语句>
endif
条件关键字有 4 个:ifeq、ifneq、ifdef 和 ifndef。
ifeq 用来判断是否相等,ifneq 就是判断是否不相等。ifeq 用法如下:
ifeq (<参数 1>, <参数 2>)
ifeq ‘<参数 1 >’,‘ <参数 2>’
ifeq “<参数 1>”, “<参数 2>”
ifeq “<参数 1>”, ‘<参数 2>’
ifeq ‘<参数 1>’, “<参数 2>”
ifdef 和 ifndef 的用法如下,如果“变量名”的值非空,那么表示表达式为真,否则表达式为假。
ifdef <变量名>
Makefile 中的函数是已经定义好的,我们直接使用,不支持我们自定义函数。函数用法为以下两种:
$(函数名 参数集合)
${函数名 参数集合}
参数集合是函数的多个参数,参数之间以逗号“,”隔开,函数名和参数之间以“空格”分隔开,函数的调用以“$”开头。
函数 subst 用来完成字符串替换:
$(subst ,,)
将字符串
函数 patsubst 用来完成模式字符串替换:
$(patsubst ,,)
此函数查找字符串
$(patsubst %.c,%.o,a.c b.c c.c)
将字符串“a.c b.c c.c”中的所有符合“%.c”的字符串,替换为“%.o”,替换完成以后的字符串为“a.o b.o c.o”。
函数 dir 用来获取目录,使用方法如下:
$(dir )
此函数用来从文件名序列
$(dir )
提取文件“/src/a.c”的目录部分,也就是“/src”。
函数 notdir 去除文件中的目录部分,也就是提取文件名,用法如下:
$(notdir )
此函数用与从文件名序列
$(notdir )
提取文件“/src/a.c”中的非目录部分,也就是文件名“a.c”。
$(foreach , ,)
此函数把参数中的单词逐一取出来放到参数中,然后再执行
# 定义一个列表
fruits := apple banana cherry
# 使用 foreach 迭代列表,并为每个元素打印一行信息
$(foreach fruit,$(fruits),echo $(fruit);)
# 输出
apple
banana
cherry
通配符“%”只能用在规则中,只有在规则中它才会展开,如果在变量定义和函数使用时,通配符不会自动展开,这个时候就要用到函数 wildcard,使用方法如下:
$(wildcard PATTERN…)
比如下方代码, 用来获取当前目录下所有的.c 文件,也就是说该函数的作用相当于 “%”。
$(wildcard *.c)