目录
1.值得思考的问题
- 目标文件(.o)是否只依赖源文件(.c)?
- 编译器如何编译源文件和头文件?
2.编译行为带来的缺陷
- 预处理将头文件中的代码直接插入源文件
- 编译器只通过预处理后的源文件产生目标文件
- 因此,规则中以源文件为依赖,命令可能无法执行
3.下面的makefile有没有问题?
这种包含头文件的方式虽然可以,但是大型工程里面头文件非常多,不便于维护
makefile
OBJS := func.o main.o
hello.out : $(OBJS)
@gcc -o $@ $^
@echo "Target File ==> $@"
$(OBJS) : %.o : %.c func.h
@gcc -o $@ -c $<
main.c
#include <stdio.h>
#include "func.h"
int main()
{
foo();
return 0;
}
func.c
#include "stdio.h"
#include "func.h"
void foo()
{
printf("void foo() : %s\n", HELLO);
}
func.h
#ifndef FUNC_H
#define FUNC_H
#define HELLO "Hello D.T."
void foo();
#endif
4.实验中解决方案的问题
- 头文件作为依赖条出现于每个目标对应的规则中
- 当头文件改动,任何原文件都将被重新编译(编译低效)
- 当项目中投文件数量巨大时,makefile将很难维护
5.疯狂的想法
- 通过命令自动生成对头文件的依赖
- 将生成的依赖自动包含进makefile中
- 当头文件改动后,自动确认需要重新编译的文件
6.预备工作(原材料)
- Linux命令sed
- 编译器依赖生成选项gcc-MM(gcc-M)
7.Linux中的sed命令
sed是一个流编辑器,用于流文本的修改(增/删/查/改)
sed可用于流文本中的字符替换
sed的字符串替换方式
echo "test=>abc+abc=abc" | sed 's:abc:xyz:g'
8.sed的正则表达式支持
- 在sed中可以用正则表达式匹配替换目标
- 并且可以使用匹配的目标生成替换结果
9.gcc关键编译选项
- 生成依赖关系
获取目标的完整依赖关系
获取目标的部分依赖关系
10.小技巧:拆分目标的依赖
将目标的完整依赖拆分为多个部分依赖
.PHONY : test a b c
test : a b
test : b c
test :
@echo "$^"
- To be continued…
思考:
如何将sed和gcc –MM用于makefile,并自动生成依赖关系?