看了gnu make手册,关于自动依赖的原理,一直没理解,今天花时间分析了一下,做下记录:
makefile:自动生成依赖:
如果直接使用sinclude $(SOURCES:.c=.d)
%d: %c
@echo "create depend"
$(CC) -MM $(CFLAGS) $< > $@
则.d会自动依赖.c并生成对应的文件。
以file.c文件举例,其中包含#include "file1.h"
例如file1.d文件中包含
file1.o : file1.c file1.h
现在在file1.h中添加#include "file2.h"
由于此时file1.d这个依赖于file1.c,但file1.c并未改变,且file1.d已存在,file1.d里面的内容不变,
因此file1.o对file2.h的依赖会丢失。
第一次编译的时候,由于发现file1.h发生了改变(添加#include "file2.h"),根据file1.o的依赖关系,file1.o会重新编译,
但改变file2.h里面的内容再次编译时,由于file1.c和file1.h里面的内容都未改变,
编译器认为file1.o是最新的,不会重新编译。
解决方案:
sinclude $(SOURCES:.c=.d)
%d: %c
@echo "create depend"
$(CC) -MM $(CFLAGS) $< > $@.$$$$; \
sed 's/\($*\.*\)o[ :]*/\1o $@ : /g' < $@.$$$$ > $@; \
$(RM) $@.$$$$
说明:sed 's/\($*\.*\)o[ :]*/\1o $@ : /g'
该语句用来替换s/ / /表示替换
\($*\.*\)o[ :]* 中$*表示为file1或者file1.(注意这里的.号,可能系统不同返回结果不同),
所以后面\.*表示后面跟0或者多个“.”号 ,总之括号里面匹配(file1.),后面跟了一个后缀o,以及0到多个空格和":".
\1o $@ : 是替换后的内容
具体替换为“file1.o file1.d :”说明:file1.是\1的内容,即前面括号配匹配的内容,file1.d为$@
file1.d文件中的内容就变成了
file1.o file1.d : file1.c file1.h
现在在file1.h中添加#include "file2.h"
则第一次编译的时候,由于发现file1.h发生了改变,而file1.o和file1.d都依赖file1.h,故file1.o和file1.h都会重新生成
file1.d里面的内容就变成了
file1.o file1.d: file1.c file1.h file2.h
改变file2.h里面的内容再次编译时,file1.o和file1.d都会再次重新生成