一. 为什么需要 Makefile
我们都知道在 Linux 下可以使用 gcc
来编译源程序, 当源文件不多的时候, gcc
足以承担编译的工作. 但是一个工程的源文件不计其数, 按照其类型, 功能, 模块分别放在若干个目录当中, 每次使用 gcc 进行编译无疑会使得编译效率低下, 于是项目自动化构建工具 Makefile 就应运而生了.
自动化编译
Makefile 定义了一系列的规则来指定: 哪些文件需要先编译, 哪些文件需要后编译, 甚至于进行更复杂的功能操作. Makefile 带来的好处就是"自动化编译", 一旦写好, 只需一个 make
命令, 整个工程完全自动编译, 极大地提高了软件开发的效率. make是一条命令, Makefile是一个文件,两个工具搭配使用, 完成项目自动化构建.
二. 如何使用 make/Makefile
创建 makefile / Makefile 文件
touch Makefile
创建 Makefile 文件.
接下来, 我们需要在 Makefile 文件中阐明多个文件之间的依赖关系 & 依赖方法.
依赖关系 & 依赖方法
在使用 make/Makefile 前我们首先应该理解各个文件之间的依赖关系以及它们之间的依赖方法.
- 依赖关系: 文件 A 的变更会影响到文件 B, 那么就称文件 B 依赖于文件 A.
例如: hello
文件是由 hello.c
文件通过预处理, 编译, 汇编, 链接之后生成的文件, 所以hello.c
文件的变更会影响 hello
文件, 所以说 hello
文件依赖于 hello.c
文件.
- 依赖方法: 如果文件 B 依赖于文件 A, 那么通过文件 A 得到文件 B 的方法, 就是文件 B 依赖于文件A 的依赖方法.
例如: hello
文件依赖于 hello.c
文件, 而 hello.c
通过 gcc hello.c -o hello
指令就可以得到 hello
, 那么 hello
依赖于 hello.c
的依赖方法就是 gcc hello.c -o hello
.
vim Makefile
打开 Makefile 文件, 并在其中编辑好 hello
和 hello.c
的依赖关系和依赖方法.
创建出 hello.c
文件并在其中编辑文本.
执行 make
指令, 并运行可执行文件 hello
.
项目清理
在我们每次重新生成可执行程序前,都应该将上一次生成可执行程序时生成的一系列文件进行清理,但是如果我们每次都手动执行一系列指令进行清理工作的话,未免有些麻烦,因为每次清理时执行的都是相同的清理指令,这时我们可以将项目清理的指令也加入到 Makefile 文件当中.
显示执行 make clean
指令.
像 clean 这种没有被第一个目标文件直接或间接关联的文件, 那么它后面所定义的命令将不会被自动执行.
提示: 一般将这种 clean 的目标文件设置为伪目标, 用.PHONY修饰. 伪目标的特性是: 总是被执行.
Makefile 文件中依赖关系的简写方式
- $@: 表示依赖关系中的目标文件 (冒号左侧)
- $^: 表示依赖关系中的依赖文件 (冒号右侧)
上图中的依赖关系可以改写为:
三. make/Makefile 的一些问题
stat 指令
我们可以通过 stat
指令来查看源文件和可执行文件的所有属性, 重点需要关注如下属性.
- Access: 最后一次访问该文件的时间.
- Change:最后一次改变该文件属性的时间.
- Modify:最近一次修改文件内容的时间.
make 命令的执行机制
当我们使用 make
命令生成目标文件后, 再次 make 就会得到 'hello' is up to date (hello 文件已经是最新的) 的信息.
那么 make
指令是否执行, 究竟取决于什么呢?
取决于目标文件与其所依赖的文件的 Modify 时间谁更新.
可以看到目标文件 hello
的 Modify 时间在 hello .c
文件的 Modify 时间之后, 所以 make
指令不执行.
当目标文件 hello
的 Modify 时间在 hello .c
文件的 Modify 时间之前, make
指令执行, 无论目标文件是否存在.