Makefile
一、什么是 Makefile
直接答案
简单来说,Makefile 就像一个自动化构建脚本,它告诉计算机如何编译和链接程序。你只需要在 Makefile 中定义好编译规则和依赖关系,然后运行 make 命令,它就会自动根据文件的修改情况,只编译那些需要重新编译的文件,最终生成可执行文件。
从底层原理理解
想象你要做一道菜(比如番茄炒蛋):
- 你需要知道这道菜由哪些材料组成(番茄、鸡蛋、油、盐)
- 你还需要知道做菜的步骤:先炒鸡蛋,再炒番茄,最后混合
- 如果某个材料更新了(比如换了新鲜的番茄),那么需要重新执行用到了这个材料的步骤
Makefile 就是这样的'菜谱',与上面对应它定义了:
- 目标(要做的菜)
- 依赖(需要的材料)
- 命令(具体的烹饪步骤)
计算机视角
我们在用编译器编译一个 C++ 项目时:
- 目标:通常是可执行文件(比如
main) - 依赖:源文件(
main.cpp、add.cpp)和头文件(add.h) - 命令:编译器和链接器的命令(
g++ -c main.cpp、g++ main.o add.o -o a.out)
Makefile 的核心机制:依赖关系检查和增量编译
依赖关系检查
我们想执行一个.cpp 文件的时候,需要经过四个步骤:预处理 --> 编译 --> 汇编 --> 链接,然后最后才能生成我们的可执行程序。把这四个步骤拆分成文件来看对应着 .cpp -> .i -> .s -> .o 这四种文件。我们可以理解为:可执行程序依赖于.o 文件,.o 文件依赖于.s 文件,.s 文件依赖于.i 文件,.i 文件依赖于.cpp 文件。这一串关系链就是所谓的依赖关系检查。
增量编译
以一个小案例来看看什么是增量编译:
- 第一次构建:编译所有文件
- 修改 add.cpp 后构建:只编译 add.cpp 和重新链接
- 只修改头文件后构建:编译所有包含该头文件的源文件
- 什么都没修改后构建:什么都不做
有了依赖关系,我们就不用因为一个文件的改动而重编所有文件,只会根据依赖项去针对性处理中间操作。此处的文件时间戳检查实际是由 make 指令来实现的。
这两个特性可以帮我们的程序节省很大一部分时间效率。下图就是我们 makefile 的执行逻辑:

二、什么是 make
直接答案
make 是一个执行 Makefile 的工具,是一个解释器用来对 Makefile 中的命令进行解析并执行一个 shell 指令。make 这个指令在 /usr/bin 中。
默认 linux 系统中都已经安装。如果没有安装 make,安装指令如下 sudo apt install make(此处为 ubuntu,centos 将 apt 改为 yum 即可)。
查看是否安装成功:make --version
简单来说,make 就像一个智能的施工队长,它看着一张施工图(Makefile),知道:
- 要建什么(目标)
- 需要什么材料(依赖)
- 怎么建(命令)
- 哪些部分已经建好了(时间戳比较)
然后它指挥工人们(执行命令)高效地完成建设任务。















