Linux 项目自动化构建工具 —— make/makefile
- 入门使用
- 原理
- 自动化构建
- 递归式自动推导
- 清理
- 注意
- 特殊符号
会不会写 makefile,从一个侧面说明了一个人是否具备完成大型工程的能力
一个工程中的源文件不计数,其按类型、功能、模块分别放在若干个目录中,makefile 定义了一系列的规则来指定,哪些文件需要先编译,哪些文件需要后编译,哪些文件需要重新编译,甚至于进行更复杂的功能操作
makefile 带来的好处就是 —— “自动化编译” ,一旦写好,只需要一个 make 命令,整个工程完全 自动编译 ,极大的提高了软件开发的效率
make 是一个 命令工具 ,是一个解释 makefile 中指令的命令工具,一般来说,大多数的 IDE 都有这个命令,比如: Delphi 的 make , Visual C++ 的 nmake ,Linux 下 GNU 的 make ;可见 makefile 都成为了一种在工程方面的 编译方法
入门使用
首先: make 是一条命令,makefile 是一个文件,两个搭配使用,完成项目自动化构建
现在在当前路径下有 code.c 代码,需要手动 touch 一个名为 makefile 或 Makefile 的文件
在里面写上如下代码:
mycode:code.c
gcc -o mycode code.c -std=c99
.PHONY:clean
clean:
rm -f mycode
- 构建可执行文件
mycode:code.c中mycode是指未来形成的 可执行程序 ,code.c是指此可执行程序依赖code.c文件gcc -o mycode code.c -std=c99这一行前面有一个Tab键,内容就是 编译 指令,不多说
- 清理
- 接下来的指令就都是清理所用
返回命令行,运行 make 指令,即可构建可执行程序 mycode ;运行 make clean 即可清理 mycode 文件
至此,你已经完成了入门使用 ^ ^
原理
自动化构建
先看下图:

这里的每一行都有其名称
- 依赖关系
:右边是 依赖文件列表 ,图中就只有code.c文件;可以为空,但若有多文件,以空格为分隔符,例:code1.c code2.c code3.c:左边是 目标文件 ,图中为mycode可执行程序
- 依赖方法
- 在单纯语法上,这一行 必须以 Tab 键开头,也不可是 4 个空格
当你在运行指令 make 后,会在当前目录下寻找 makefile 文件,根据 makefile 文件里的 依赖关系 ,遵循 依赖方法 ,为你完成 依赖方法 里的工作,生成 目标文件
递归式自动推导
当你知道目标文件如何生成时,再来看看类似 递归式的连锁生成 :
先来看看 makefile 文件:
mycode:code.o
gcc code.o -o mycode
code.o:code.s
gcc -c code.s -o code.o
code.s:code.i
gcc -S code.i -o code.s -std=c99
code.i:code.c
gcc -E code.c -o code.i
这就是 gcc 编译的每一步明细,在这里不做详细解释(如不明白,请查阅过往 gcc 拙作)
- 我们知道最终的目标文件是
mycode可执行程序,但:后面的依赖文件code.o在我们当前路径下并没有 - 于是
make就会在makefile文件里寻找名为code.o的目标文件 - 找到之后会根据
:后面的依赖文件,再根据依赖方法来生成code.o目标文件 - 但当前路径下
code.o的依赖文件code.s也没有,那make就会继续在makefile文件里寻找名为code.s的目标文件 - 于是一直找到
code.i目标文件,它的依赖文件是存在的,那么就会生成code.i,继而生成code.s,code.o直至最后的mycode可执行程序
那么这就很类似 栈式结构的递归调用 ,而上述就是 自动推导 makefile 中的依赖关系 的过程,即使乱序也可构建执行
清理
先看看 makefile 里的 clean 部分
clean:
rm -f code.i code.s code.o mycode
是否感觉和你要自动化构建的可执行程序写法十分相似?
实际上 clean 就是 makefile 里的 目标文件,只是它没有 依赖文件 而已(依赖文件列表可以为空),而下面就是 依赖方法 ,完成 依赖方法 里的工作,即为清理完成
而你要执行清理,就是生成 clean 这个目标文件,命令行也就需要在 make 后面指定要生成的目标文件,所以是:
make clean
注意
- 当你直接
make时,make会默认生成makefile里的第一个目标文件 - 如果你要生成
makefile里的其他的目标文件,就在make后面带上你要生成的目标文件(clean就是如此) - 当你第二次再运行
make时,只要 源文件 没有被更新修改,就会告诉你要生成的 目标文件 是最新的,不让你继续make,因为没有必要,为了提高效率(实现方法就是对比 源文件 和 目标文件 的最近修改时间) - 要想 目标文件 总是被执行,需要在 目标文件 前添加
.PHONY声明,相当于告诉make不要管什么时间问题;而此时的 目标文件 也被称为 伪目标
特殊符号
在 依赖关系 里存在 目标文件 和 依赖文件列表
那么在 依赖方法 里,就可以利用 $@ 、 $^ 分别表示 目标文件 和整个 依赖文件列表
在我们成功 make 时,命令行会给我们回显自动化构建的步骤,如果不想回显,可在 依赖方法 最前面添加 @





![[Meachines] [Easy] OpenAdmin OpenNetAdmin-RCE+RSA私钥解密+Nano权限提升](https://img-blog.csdnimg.cn/img_convert/bd71d2c2e3afb13fe024443e77b8ae9b.jpeg)












