论坛里有人写了一个用于自动生成C/C++依赖的脚本。但是他的脚本处理不同目录的源文件时会有些问题,.o
会生成在当前目录,而不是和 .cc
同一个目录。
gcc
其实有一些生成用于 Makefile
规则的选项,-M
等,说明如下:
-MM
,忽略依赖中的系统头文件-MF
,指定生成的规则文件的路径-MT
,指定规则的目标-MP
,对每一个依赖创建一个force target
,典型输出:test.o: test.c test.h test.h:
没有这个选项的话是不会有
test.h:
的
我写的 Makefile
如下,注意要把规则中的8格替换成tab。
PROG := main
SRCS := $(PROG).c
$(PROG): $(SRCS:.c=.o)
$(LINK.c) $^ -o $@
sinclude $(SRCS:.c=.d)
%.o: %.c
gcc -MM -MP -MT $@ -MF $(@:.o=.d) $<
$(COMPILE.c) $< -o $@
比较难说明每个规则的作用,所以还是用实例好了。
- 一开始,
*.o
*.d
都不存在,只有一个main.c
- 执行
make
,make
没法读取sinclude
那行表示的文件main.d
,但由于是sinclude
,忽略这个错误 - 尝试重建
main
,发现需要的main.o
不存在 - 因此尝试先重建
main.c
。执行规则%.o: %.c
,生成main.o
的同时也 生成了main.d
。假设main.c
包含一个头文件a.h
,那么main.d
的内容将会是: main.o: main.c foo/a.h foo/a.h:
之后如果修改 main.c
或者 foo/a.h
,因为
main.d
中的规则都会重建 main.o
。
再看添加新依赖 bar/b.h
的情况,没错,这时我们的
main.d
是过期的,不能反映 main.c
的真实依赖情况。但注意到 main.d
的过期必然蕴含:main.c
被修改了。根据规则
%.o: %.c
,再次重建 main.d
和
main.o
。
假设我们删除 main.c
中的
#include "foo/a.h"
,同样的,main.d
过期了,不能反映 main.c
的真实依赖情况。但注意到
main.d
的过期必然蕴含:main.c
被修改了。根据规则 %.o: %.c
,再次重建 main.d
和 main.o
。
如果我们不改动 main.c
而是直接删除
foo/a.h
,那么根据
main.o: main.c foo/a.h
,无法重建
main.o
,make
报错。注意:foor/a.h
是
force target
,它不存在的话不会报错,只是让依赖它的目标强制重建。这也是我们之所以使用
-MP
的原因,否则如果不存在目标为 foo/a.h
的规则,make
会报错:无法重建 foo/a.h
。
还有种生成依赖的方式是让 main.o
依赖
main.d
,main.d
依赖
main.c
,但是这种方法可能会导致 make
的重启,当
make
很复杂的时候性能不如前文的方法。