自动生成依赖关系(上)
值得思考的问题
- 目标文件(.o)是否只依赖于源文件(.c)?
- 编译器如何编译源文件和头文件?
编译行为带来的缺陷
- 预处理将头文件中的代码直接插入到源文件
- 编译器只通过预处理后的源文件产生目标文件
- 因此:
- 源文件以源文件为依赖,命令可能无法执行
下面的makefile是否有问题
OBJS := fun.o main.o
hello.out : $(OBJS)
@gcc -o $@ $^
@echo "Target File ==> $@"
$(OBJS) : %.o : %.c
@gcc -o $@ -c $^
代码依赖关系:
实验截图:
看上去没有什么问题,但是如果修改func.h
中打印的字符串。执行make命令,make会提示可执行文件是最新的,所以修改没作用;
编程实验
OBJS := func.o main.o
hello.out : $(OBJS)
@gcc -o $@ $^
@echo "Target File ==> $@"
$(OBJS) : %.o : %.c func.h
@gcc -o $@ -c $<
实验截图:
实验中解决方案的问题
- 头文件作为依赖条件出现于每个目标对应的规则中
- 当头文件改动,任何源文件都将会被重新编译(编译低效)
- 当项目头文件数量巨大时,makefile将很难维护
疯狂的想法
- 通过命令自动生成对头文件的依赖
- 将生成的依赖自动包含进makefile中
- 当头文件改动后,自动确认需要重新编译的文件
预备工作
- Linux命令sed
- 编译器依赖生成选项gcc -MM (gcc -M)
Linux中的sed命令
- sed是一个流编辑器,用于流文本(增/删/查/改)
- sed可用于流文本中的字符串替换
- sed的字符串替换方式为:
sed 's:src:xyz:g'
echo "test=>abc+abc=abc" | sed 's:abc:xyz:g'
# 结果为:
test=>xyz+xyz=xyz
sed的正则表达式支持
-
在sed中可以用正在表达式匹配替换目标
-
并且可以使用匹配的目标生成替换的结果
gcc关键编译选项 -
生成依赖关系
-
获取目标的完整依赖关系
gcc -M test.c
-
获取目标部分的依赖关系
gcc -MM test.c
-
小技巧:拆分目标的依赖
- 将目标的完整依赖拆分为多个部分依赖
编程实验
.PHONY : test a b c
test : a b
test : b c
test :
@echo "$^"
实验截图:
思考:
- 如何将sed和gcc -MM用于make自动生成依赖关系?
参考资料:
狄泰软件教学课件