什么是Makefile ?
Makefile 可以看作是一个脚本,是用来组织编译工程项目用的,同时也可以执行操作系统的命令。
比如我们常见的集成开发工具Qt Creator 在构建项目时通常会自动生成Makefile。
Makefile一般在嵌入式领域用的比较多,因为可能需要修改编译环境(如编译工具链等),不像应用开发那样,开发环境是固定的。
为什么要用Makefile ?
- 高效的编译程序:一个文件修改无需挨个编译;
- 有层次的组织项目工程
Makefile 基本规则
基本规则
目标(target)... : 依赖(DEPENDEDS)... #这里的是tab键并非空格 <TAB>命令(command) #example hello: hello.c gcc -o hello hello.c
命令被执行的两个条件:
- 依赖文件比目标文件新
- 或者目标文件还未生成
foreach函数
#for each var in list,change it to text #把list中的值改为text $(foreach var,list,text) #example objs:= a.o b.o #最终生成.a.o.d .b.o.d dep_files:= $(foreach f, $(objs), .$(f).d)
wildcard函数
#pattern 所列出的文件是否存在 $(wildcard pattern) #example #列出当前目录下的所有.c文件 src_files:= $(wildcard *.c)
一步步完善Makefile
简单粗暴
test: main.c sub.c sub.h gcc -o test main.c sub.c
执行make 会自动 解析名为Makefile的文件并执行gcc命令。
改进1
执行make后会依次检测目标,并逐个编译,如果文件没有更新则不修改,重新编译只编译更新过的文件。
执行 make clean 会删除.o和test文件
- 效率高
- 相似规则太多
- 不支持检测头文件
改进2
相比改进1精简
说明:
- %为通配符:%.o表示所有的.o %.c所有的.c
- %@:所有的目标
- $<:第一个依赖(这里只有%.c)
改进3
支持头文件检测:修改头文件后会重新编译
- 效率高
- 精简
- 需要手动添加头文件规则,不够灵活
改进4
自动生成依赖
- $^:所有的依赖
- foreach:将*.o替换成.*.o.d
- wildcard:列出当前目录下的所有依赖文件
- gcc -Wp, -MD, .*.o.d 生成依赖文件
.main.o.d
.sub.o.d
到此为止,是一个相对完善的Makefile文件,不过还是有很多缺陷(例如多层目录等处理),留待后续介绍。
总结
- 引入Makefile基本规则
- foreach:遍历并替换
- wildcard:列出当前目录指定的文件
- $@:所有的目标
- $^:所有的依赖
- $<:第一个依赖
- := :即时等于
- %: 通配符