Makefile
是定义管理工程编译依赖,在 Linux
系统编译 c/c++ 得到良好的使用
其定义指定哪些文件需要先编译,哪些文件需要后编译,哪些文件需要重新编译,甚至于进行更复杂的功能操作
因为 Makefile
就像一个 Shell
脚本一样,其中也可以执行操作系统的命令
Makefile
带来的好处就是——“自动化编译”,一旦写好,只需要一个 make
命令,整个工程完全自动编译,极大的提高了软件开发的效率。
规则
1 | target ... : prerequisites ... |
举个栗子1
2
3
4
5
6
7
8
9
10
11
12
13
14demo: max.o min.o sum.o avg.o
gcc -o demo max.o min.o sum.o avg.o
max.o: max.c
gcc -c max.c calc.h
min.o: min.c
gcc -c min.c calc.h
sum.o: sum.c
gcc -c sum.c calc.h
avg.o: avg.c
gcc -c avg.c calc.h
.PHONY : clean
clean:
rm demo max.o min.o sum.o avg.o
在命令行执行 make
编译生成 demo
运行文件,执行 make clean
清除编译生成文件
在默认的方式下,也就是我们只输入 make
命令,他的执行流程是:
make
会在当前目录下找名字叫Makefile
或makefile
的文件。- 如果找到,它会找文件中的第一个目标文件(target),在上面的例子中,他会找到
demo
这个文件,并把这个文件作为最终的目标文件。 - 如果
demo
文件不存在,或是demo
所依赖的后面的 .o 文件的文件修改时间要比demo
文件新,
他就会执行后面所定义的命令来生成demo
这个文件。 - 如果
demo
所依赖的 .o 文件也不存在,那么make
会在当前文件中找目标为 .o 文件的依赖性,再根据那一个规则生成 .o 文件 - 你的
C
文件和H
文件是存在的啦,make
会生成 .o 文件,然后再用 .o 文件生成make
的终极任务,也就是执行文件demo
使用变量
在上面的例子中,我们在三个地方用到了 max.o min.o sum.o avg.o
这些文件,重复多次,我们维护比较复杂,这是就会用到变量的概念
定义: 变量名:值 obj = max.o min.o sum.o avg.o
使用: $(变量名) $(obj)
优化上面栗子:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15obj = max.o min.o sum.o avg.o
demo: $(obj)
gcc -o demo $(obj)
max.o: max.c
gcc -c max.c calc.h
min.o: min.c
gcc -c min.c calc.h
sum.o: sum.c
gcc -c sum.c calc.h
avg.o: avg.c
gcc -c avg.c calc.h
.PHONY : clean
clean:
rm demo $(obj)
这样编译管理,有信息的 .o 文件需要编译的话,只需要修改 obj 变量即可
自动推导
GNU 的 make
很强大,它可以自动推导文件以及文件依赖关系后面的命令,于是我们就没必要去在每一个[.o]文件后都写上类似的命令
因为,我们的 make
会自动识别,并自己推导命令。
只要 make
看到一个[.o]文件,它就会自动的把[.c]文件加在依赖关系中,如果 make
找到一个 min.o
那么 min.c
,就是默认依赖文件。并且 gcc -c min.c 也会被推导出来,
于是,我们的 makefile
再也不用写得这么复杂
优化上面栗子:1
2
3
4
5
6
7
8
9
10
11obj = max.o min.o sum.o avg.o
demo: $(obj)
gcc -o demo $(obj)
max.o: calc.h
min.o: calc.h
sum.o: calc.h
avg.o: calc.h
.PHONY : clean
clean:
rm demo $(obj)
利用推导功能,还有例外一种写法1
2
3
4
5
6
7
8obj = max.o min.o sum.o avg.o
demo: $(obj)
gcc -o demo $(obj)
max.o min.o sum.o avg.o: calc.h
.PHONY : clean
clean:
rm demo $(obj)
这种风格,让我们的makefile变得很简单,但我们的文件依赖关系就显得有点凌乱了,显示不出依赖的层次关系
清空编译文件
1 | clean: |
这样便于重新编译
引入文件
1 | include filename |
补充make的工作方式:
- 读入所有的 Makefile。
- 读入被 include 的其它 Makefile。
- 初始化文件中的变量。
- 推导隐晦规则,并分析所有规则。
- 为所有的目标文件创建依赖关系链。
- 根据依赖关系,决定哪些目标要重新生成。
- 执行生成命令
©版权声明:原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 & 作者信息。
End