自动生成依赖关系(上)
1.思考
- 目标文件(.o)是否只依赖于源文件(.c)
- 编译器如何编译源文件和头文件?
2.编译行为带来的缺陷
- 预处理器将头文件中的代码直接插入源文件
- 编译器只通过预处理后的源文件产生目标文件
- 因此,
- 规则中以源文件为依赖,命令可能无法执行
3.下面的makefile有没有问题?
OBJS := func.o main.o
hello.out : $(OBJS)
@gcc -o $@ $^
$(OBJS) : %.o : %.c func.h
@gcc -o $@ -c $<
4.问题
- 头文件作为依赖条件出现于每个目标对应的规则中
- 当头文件改动,任何源文件都将被重新编译(编译低效)
- 当项目中头文件数量巨大时,makefile将很难维护
5.疯狂的想法
- 通过命令自动生成对头文件的依赖
- 将生成的依赖自动包含进makefile中
- 当头文件改动后,自动确认需要重新编译的文件
6.预备工作(原材料)
- Linux中的sed命令
- 编译器依赖生成选项gcc -MM(gcc -M)
7.Linux中的sed命令
-
sed是一个流编辑器,用于流文本的修改(增删查改)
-
sed可用于流文本中的字符串替换
-
sed的字符串替换方式为:
sed 's:src:des:g'
-
sed的正则表达式支持
- 在sed中可以用正则表达式匹配替换目标
- 并且可以使用匹配的目标生成替换结果
8.gcc关键编译选项
- 生成依赖关系
- 获取目标的完整依赖关系
- gcc -M test.c
- 获取目标的部分依赖关系
- gcc -MM test.c
- 获取目标的完整依赖关系
9.小技巧:拆分目标的依赖
- 将目标的完整依赖拆分为多个部分依赖
.PHONY : test a b c
test : a b
test : b c
test :
@echo "$^"
//编译运行
$ make -f makefile.1
a b c