5. 模式规则

模式规则是在规则中使用百分号(%)通配符 来代替显示规则的一种方式,他可以制作显式规则的模版。让多个规则总结为一个规则的方法。

我们之前定义多个显式规则,使用显式规则可以自定义每一个规则执行的命令,当然文件比较多时,规则也就相应的增多,代码量会变大。

如下:

main.o : main.c $(HEADERS)
    gcc -o $@ -c $<

file1.o : file1.c $(HEADERS)
    gcc -o $@ -c $<

file2.o : file2.c $(HEADERS)
    gcc -o $@ -c $<

如果文件比较多的时候,我们可以使用隐含规则,但隐含规则只能匹配默认的几种规则,且不能够自定义命令的格式。此时使用模式规则可以解决上述问题。

模式规则的语法:

目标文件模式 : 依赖文件模式
<制表符> 命令1
<制表符> 命令2
...

说明:

例如,上述模式可以改写成

%.o : %.c $(HEADERS)
    gcc -o $@ -c $<
    echo "compiling $@, % is $* ..."

此模式规则中 %.o 表示以任何 .o 结尾的目标文件。%.c 是和目标同名且以 .c 结尾的文件。此时的 % 匹配非空的文件名,且文件名一定相同。即 %.o 匹配 file1.o 时,%.c 一定匹配 file1.c

在模式匹配中,使用自动变量 $* 可以获取通配符 % 匹配的字符串。

改写后的 Makefile 如下:

.PHONY: all clean

SOURCES := file1.c file2.c main.c
HEADERS := file1.h file2.h
OBJECTS := file1.o file2.o main.o
TARGET := myapp

# 修改隐含规则的变量,更改编译命令
CC = gcc
CFLAGS = -g -Wall

all: $(TARGET)  # 编译最终目标

$(TARGET) : $(OBJECTS)
    gcc -o $@ $^

# 自定义模式规则
%.o : %.c $(HEADERS)
    gcc -o $@ -c $<
    echo "compiling $@, % is $* ..."

clean:  # 清除目标文件
    rm $(OBJECTS)

make 的执行结果如下:

weimz@anonymous myapp % make
gcc -o file1.o -c file1.c
echo "compiling file1.o, % is file1 ..."
compiling file1.o, % is file1 ...
gcc -o file2.o -c file2.c
echo "compiling file2.o, % is file2 ..."
compiling file2.o, % is file2 ...
gcc -o main.o -c main.c
echo "compiling main.o, % is main ..."
compiling main.o, % is main ...
gcc -o myapp file1.o file2.o main.o

从上述执行结果可以看出,使用模式规则可以代替隐含规则并能够自定义任何通用规则,使用 $* 可以获取每次匹配的字符串。

实验:

尝试在自己的 Makefile 中使用模式规则。