1. Makefile的内容
一个完整的 Makefile 中,包含了 5 个东西:显式规则、隐含规则、变量定义、 指示符和注释
1.1 显式规则
描述了在何种情况下如何更新一个或者多个被称为目标的文件。
1.2 隐含规则
它是make根据一类目标文件(典型的是根据文件名的后缀)而自 动推导出来的规则
1.3 变量定义
使用一个字符或字符串代表一段文本串
1.4 Makefile指示符
指示符指明在 make 程序读取 makefile 文件过程中所要执 行的一个动作。包含
- 读取一个文件
- 决定(通常是根据一个变量的得值)处理或者忽略Makefile中的某一特定
部分 - 定义一个多行变量
1.5 注释
Makefile 中“#”字符后的内容被作为是注释内容(和 shell 脚本一样) 处理。如果此行的第一个非空字符为“#”,那么此行为注释行
2. Makefile文件的命名
2.1
一般情况下,make 会在工作目录(执行 make 的目录)下按照文件名顺序寻找 makefile 文件读取并执行,查找的文件名顺序为:“GNUmakefile”、“makefile”、 “Makefile”。
2.2
通常应该使用“makefile”或者“Makefile”作为 makefile 的文件名(建议使用 Makefile )
2.3
如果make程序在工作目录下无法找到以上三个文件中的任何一个,它将不读取任 何其他文件作为解析对象。
当 makefile 文件的命名不是这三个任何一个时,需要通过 make 的“-f”或者“--file”选项来指定 make 读取的 makefile 文件。给 make 指定 makefile 文件的格式为:“-f NAME”或者“—file=NAME”。也可以指定多个文件,多个文件将按输出顺序解析。
3. 包含其它makefile文件
Makefile的文件包含和c语言一致,使用include关键字
-include FILENAMES...
4. 变量
4.1 MAKEFILES
如果在当前环境定义了一个“MAKEFILES”环境变量,make执行时首先将此变量的值作为需要读入的Makefile文件,多个文件之间使用空格分开。类似使用指示符“include”,但是它和include有几个区别
- 环境变量指定的makefile文件中的“目标”不会被作为make执行的“终极目 标”。
- 环境变量所定义的文件列表,在执行make时,如果不能找到其中某一个文件 (不存在或者无法创建)。make不会提示错误,也不退出
- make 在执行时,
首先读取的是环境变量“MAKEFILES”所指定的文件列表,“include”所指定的文件是在make发现此关键字的时暂停正在读取的文件而转去读取“include”所指定的文件
实际应用中很少设置此变量
4.2 MAKEFILE_LIST
MAKEFILE_LIST是make程序读取的文件名自动添加的
4.3 VARIABLES
VARIABLES是一个特殊的变量,不能通过任何途经给它赋值。它被展开为一个特定的值。
5 make解析Makefile文件过程
Gun make执行过程分为两个阶段
- 读取所有的Makefile文件(包含MAKEFILES变量指定的和include的以及命令行-file的),内建所有的变量、明确规则和隐含规则并建立依赖关系结构
- 根据第一阶段建立的关系,觉得那些目标需要更新,并依靠规则重建这些目标
其中,在第一步如果变量和函数被展开,则成为立即展开,之后的展开,成为延后展开
5.1 立即和延后
5.1.1 条件语句
所有使用的条件语句,make会根据程序预设条件展开,即条件分支的展开是“立即”的,包含
“ifdef”、“ifeq”、“ifndef”和 “ifneq”
5.1.2 规则
IMMEDIATE : IMMEDIATE ; DEFERRED
[Tab] DEFERRED
规则中的目标和依赖用到的变量,是立即展开,而命令行中的变量,则是延后展开
6 总结
make执行过程如下
- 依次读取变量“MAKEFILES”定义的makefile文件列表
- 读取工作目录下的 makefile 文件(根据命名的查找顺序“GNUmakefile”,
“makefile”,“Makefile”,首先找到那个就读取那个) - 依次读取工作目录makefile文件中使用指示符“include”包含的文件
- 查找重建所有已读取的makefile文件的规则(如果存在一个目标是当前读取的
某一个 makefile 文件,则执行此规则重建此 makefile 文件,完成以后从第一步
开始重新执行) - 初始化变量值并展开那些需要立即展开的变量和函数并根据预设条件确定执行
分支 - 根据“终极目标”以及其他目标的依赖关系建立依赖关系链表
- 执行除“终极目标”以外的所有的目标的规则(规则中如果依赖文件中任一个
文件的时间戳比目标文件新,则使用规则所定义的命令重建目标文件) - 执行“终极目标”所在的规则