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)