Makefile进阶

1、Makefile依赖关系

SRC     := $(wildcard *.c)
OBJ     := $(SRC:.c=.o)
$(TARGETS) : $(OBJ)
	cc $^ -o $@
%.o : %.c
	cc -c $<

在上记的Makefile中,%.o : %.c 规则并没有被显式调用。但是在执行 $(TARGETS) : $(OBJ) 时,
Makefile会根据$(TARGETS) : $(OBJ)%.o : %.c生成以下的依赖树:

$(TARGETS) <= $(OBJ) <= %.c

因此,当任意源文件发生变更时,make都会重新编译和链接发生变更的文件。

2、include

在实际的应用中,为了复用已有的Makefile,经常会使用include命令,将其它Makefile文件的内容包含到当前Makefile中。
1)将以下Makefile作为共同文件,放在外层目录
file:Makefile.common.mk

SRC     := $(wildcard *.c)
OBJ     := $(SRC:.cpp=.o)
$(TARGETS) : $(OBJ)
	cc $^ -o $@
%.o : %.c
	cc -c $<

2)编写具体的Makefile文件
file:Makefile

TARGETS = test
include ../Makefile.common.mk

3)扩展
当include指定的文件不存时,Makefile同样会在所有目标中查找是否存在include指定对象的目标;
若目标不存在,则发生错误;否则,执行对应的目标规则。
因此,我们可以将不会自动推导的依赖项作为include命令的对象,让目标可以自动编译。

4)实际应用
在前述的Makefile中,都只有对源文件的目标规则。当只有头文件方式更改时,Makefile无法自动检测到代码变更,也不会重新编译。

SRC     := $(wildcard *.c)
OBJ     := $(SRC:.c=.o)
$(TARGETS) : $(OBJ)
	cc $^ -o $@
%.o : %.c
	cc -c $<

DEPEND	:= $(SRC:.d=.o)
%.d : %.c
####  对指定的程序运行预处理程序,同时请求预处理程序生成 makefile 依赖性并将结果重定向到临时文件(目标文件.进程号)
	cc -M $< > $@.$$$$;		\
####  通过sed命令将临时文件中类似test.o : test.h的行,替换为test.o test.d : test.h
####  再通过egrep去除标准库头文件,并重定向到.d文件中
	sed 's,\($*\).o[ :],\1.o $@ : ,g' < $@.$$$$ | egrep -v ':[ ]*(/usr/|/opt/)' > $@;	\
####  删除临时文件
	rm -f $@.$$$$		

inlcude $(DEPEND)
上一篇:基于Ubuntu18.04的C语言编程教程(gcc、vim、Makefile)


下一篇:(转)一个JavaWeb项目开发总结