1个规则:
目标:依赖条件
(一个tab缩进)命令
1.目标的时间必须晚于依赖条件的时间,否则,更新目录
2.依赖条件如果不存在,找寻新的规则去产生依赖
ALL:指定makefile的终极目标
2个函数:
src = $(wildcard ./*.c):匹配当前目录下所有.c文件,将文件名组成列表,赋值给src。
src = add.c sub.c div1.c ......
obj = $(patsubst %.c,%.o, $(src)):将参数3中,包含参数1(.c)的部分,替换为参数2。 obj = add.o sub.o div1.o(.o是后缀)
clean:(没有依赖)
-rm -rf $(obj) a.out “-”:删除不存在文件时,不会报错,顺序执行结果
3个自动变量:
$@:在规则的命令中,表示规则目标。
$^:在规则的命令中,表示所有依赖条件。如果将该变量应用在模式规则中,它可将依赖条件列表中的依赖依次取出,套用模式规则。
$<:在规则的命令中,表示第一个依赖条件。如果将该变量用在模式规则中,它可以将依赖条件列表中的依赖依次取出,套用模式规则
add.o:add.c
gcc -c add.c -o add.o在这里面上面的add.c是规则目标,下面的add.o是规则目标
模式规则:
%.o:%.c
gcc -c %.c -o %o
静态模式规则:
$(obj):%.o:%.c
gcc -c $< -o %@
伪目标:
.PHONY: clean ALL
参数:
-n:模拟执行make、make clean 命令。
-f:指定文件执行 make 命令。 xxxx.mk
、、、、、、
下面一步步优化makefile
、、、、、、
一个规则
makefile的依赖是从上至下的,换句话说就是目标文件是第一句里的目标,如果不满足执行依赖,就会继续向下执行。如果满足了生成目标的依赖,就不会再继续向下执行了。
make会自动寻找规则里需要的材料文件,执行规则下面的行为生成规则中的目标。
执行make指令
运行
、、
修改test.c
此时要进行编译,则需要多文件联合编译:gcc test.c add.c sub.c div1.c -o a.out
编写makefile
运行
修改一下add.c函数,在编译的时候,其他的函数也会重新编译一下,不合理
这里就可以修改一下makefile文件
执行make,运行
修改sub.c
执行make,运行
就会发现只重新编译了sub.c
、、、、、、
makefile检测原理:
修改文件后,文件的修改时间发生变化,会出现目标文件的时间早于作为依赖材料的时间,出现这种情况的文件会重新编译。
修改sub.c后,sub.o的时间就早于sub.c ,a.out的时间也早于sub.o的时间了,于是重新编译这俩文件了。
、、、、、、
修改makefile文件里面的顺序
执行make,发现只执行了第一句,并且没有a.out
这是因为,makefile默认第一个目标文件为终极目标,生成就跑路,这时候可以用ALL来指定终极目标
两个函数
src = $(wildcard *.c)
找到当前目录下所有后缀为.c的文件,赋值给src
obj = $(patsubset %.c,%.o, $(src))
把src变量里所有后缀为.c的文件替换成.o
修改makefile
执行make
-rm -rf:这里加“-”代表出错依然执行。比如,待删除文件集合是5个,已经手动删除了1个,就只剩下4个,然而删除命令里面还是5个的集合,就会有删除不存在文件的问题,不加这-,就会报错,告诉你有一个文件找不到。加了-就不会因为这个报错。
在清除的时候可以加上-n,来,模拟清除的部分,确认无误就可以清除
然后在执行
三个自动变量
$@ :在规则命令中,表示规则中的目标
$< :在规则命令中,表示规则中的第一个条件,如果将该变量用在模式规则中,它可以将依赖条件列表中的依赖依次取出,套用模式规则
$^ :在规则命令中,表示规则中的所有条件,组成一个列表,以空格隔开,如果这个列表中有重复项,则去重
修改makefile
模式规则
再来,上面这个makefile,可扩展性不行。比如,要添加一个乘法函数,就需要在makefile里面增加乘法函数的部分。不科学,所以,模式规则就来了
%.o:%.c
gcc -c $< -o $@
这里添加一个mul函数(乘法函数)
执行make
静态模式规则
继续优化makefile,使用静态模式规则,就是指定模式规则给谁用,这里指定模式规则给obj用,以后文件多了,文件集合会有很多个,就需要指定哪个文件集合用什么规则
$(obj):%.o:%.c
gcc -c $< -o $@
再来一个扩展
当前文件夹下有ALL文件或者clean文件时,会导致makefile瘫痪,如下所示,make clean没有工作
这里就用伪目标
还有一个扩展就是,编译时的参数,-g,-Wall这些,可以放在makefile里面
修改后makefile如下:
执行make