使用模式规则

廖雪峰
资深软件开发工程师,业余马拉松选手。

前面我们讲了使用隐式规则可以让make在必要时自动创建.o文件的规则,但make的隐式规则的命令是固定的,对于xyz.o: xyz.c,它实际上是:

	$(CC) $(CFLAGS) -c -o $@ $<

能修改的只有变量$(CC)$(CFLAGS)。如果要执行多条命令,使用隐式规则就不行了。

这时,我们可以自定义模式规则(Pattern Rules),它允许make匹配模式规则,如果匹配上了,就自动创建一条模式规则。

我们修改上一节的Makefile如下:

OBJS = $(patsubst %.c,%.o,$(wildcard *.c))
TARGET = world.out

$(TARGET): $(OBJS)
	cc -o $(TARGET) $(OBJS)

# 模式匹配规则:当make需要目标 xyz.o 时,自动生成一条 xyz.o: xyz.c 规则:
%.o: %.c
	@echo 'compiling $<...'
	cc -c -o $@ $<

clean:
	rm -f *.o $(TARGET)

make执行world.out: hello.o main.o时,发现没有hello.o文件,于是需要查找以hello.o为目标的规则,结果匹配到模式规则%.o: %.c,于是make自动根据模式规则为我们动态创建了如下规则:

hello.o: hello.c
	@echo 'compiling $<...'
	cc -c -o $@ $<

查找main.o也是类似的匹配过程,于是我们执行make,就可以用模式规则完成编译:

$ make
compiling hello.c...
cc -c -o hello.o hello.c
compiling main.c...
cc -c -o main.o main.c
cc -o world.out hello.o main.o

模式规则的命令完全由我们自己定义,因此,它比隐式规则更灵活。

但是,模式规则仍然没有解决修改hello.h头文件不会触发main.c重新编译的问题,这个依赖问题我们继续放到后面解决。

最后注意,模式规则是按需生成,如果我们在当前目录创建一个zzz.o文件,因为make并不会在执行过程中用到它,所以并不会自动生成zzz.o: zzz.c这个规则。

参考源码

可以从GitHub下载源码。

GitHub

小结

使用模式规则可以灵活地按需动态创建规则,它比隐式规则更灵活。

查看官方手册:



Comments

Loading comments...