1.模式规则
上一节我们的makefile文件如下:
makefile
src = $(wildcard *.c)
obj = $(patsubst %.c,%.o,$(src))
app:$(obj)
gcc $(obj) -o app
hello.o:hello.c
gcc -c hello.c -o hello.o
add.o:add.c
gcc -c add.c -o add.o
sub.o:sub.c
gcc -c sub.c -o sub.o
mul.o:mul.c
gcc -c mul.c -o mul.o
我们目前只有4个c文件,可以生成4个o文件,那如果我们有200个呢,2000个呢,要咋办?make里面提供了一种模式规则,来对一类规则进行匹配并简化。
2.基本语法
makefile
目标模式: 依赖模式1 依赖模式2
命令
- 目标模式 包含一个 %,匹配目标文件名的一部分。必须含且仅含一个 %(如 %.o、build/%.o)
- 依赖模式 也包含 %,匹配时 % 的值与目标中的 % 相同。
- % 匹配非空字符串(不能空),可以出现在任何位置,但通常出现在文件名末尾(如 %.o)或中间(如 build/%.exe)。
核心机制:当 Make 需要生成一个目标(比如 foo.o)且没有显式规则时,会查找模式规则。如果 foo.o 匹配 %.o(% = foo),则依赖变为 foo.c(若模式是 %.o: %.c)。然后 Make 会尝试生成或找到 foo.c,如果成功则执行命令。
3.自动变量
- $@:表示规则中的目标
- $<:表示规则中的第一个条件
- $^:表示规则中的所有条件,组成一个列表,以空格隔开,如果列表中有重复项,则消除重复项
到此,makefile可以修改为:
makefile
src = $(wildcard *.c)
obj = $(patsubst %.c,%.o,$(src))
app:$(obj)
gcc $^ -o app
%.o:%.c
gcc -c $^ -o $@
4.内置变量
- CC:默认是cc指令,可以改成gcc
- CPPFLAGS:C语言预处理的选项 -I(大写的i)
- CFLAGS:C编译器的选项
- LDFLAGS:链接器选项 -L -l(小写的l)
到此,makefile可以修改为:
makefile
src = $(wildcard *.c)
obj = $(patsubst %.c,%.o,$(src))
target=app
CC=gcc
CPPFLAGS=-I ./
$(target):$(obj)
$(CC) $^ -o $@
%.o:%.c
$(CC) -c $^ -o $@ $(CPPFLAGS)
5.伪目标
5.1.clean
我们每次make后都会产生.o文件以及可执行文件,当我们需要重新编译的时候,我们需要手动清理,make为我们提供了清理的机制,我们在makefile中编写clean即可。因为只有目标,没有依赖,又被称为伪目标 。
当我们clean的命令出错时应该如何处理呢?在指令前加上"-"
写法如下:
makefile
clean:
-rm -rf *.o $(target)
5.2. .PHONY
如果目录中存在名为 clean 的文件,make 会认为它们已经是最新的而不执行规则。
为避免这种情况,可以将它们声明为伪目标:
makefile
.PHONY:clean
clean:
-rm -rf *.o $(target)
6.最终的makefile
makefile
src = $(wildcard *.c)
obj = $(patsubst %.c,%.o,$(src))
target=app
CC=gcc
CPPFLAGS=-I ./
.PHONY: clean
$(target):$(obj)
$(CC) $^ -o $@
%.o:%.c
$(CC) -c $^ -o $@ $(CPPFLAGS)
clean:
-rm -rf *.o $(target)