一、makefile的组成部分
makefile由五部分组成,分别为显式规则、隐式规则、变量定义、指示符、注释。
- 显式规则(explicit rules)。显示规则用于阐述什么时候或者怎样(重新)生成目标。
- 隐式规则(implicit rules)。隐式规则是基于make的自动推导功能。用来阐述什么时候或者怎样(重新)生成一类目标,依据的就是这类目标的名称。这类目标一般依赖同名的文件。
- 变量定义(variable definitions)。makefile中的变量跟C中的宏很类似,使用时make会将变量扩展到相应的引用位置上。
- 指示符(directives)。指示符用来指示make在读取makefile文件时做一些特殊的动作。
- 注释(comments)。
二、makefile的“规则”语法结构
makefile的“规则”语法格式如下:
target ... : prerequisites
recipe
...
...
target(目标):规则的目标。通常是最后需要生成的文件名。最典型的就是最后的可执行文件名,或者编译后生成的目标文件的名字。不过,“目标”也可以是一个动作的名称,例如clean,此类目标被称为“伪目标(phony target)”。
prerequisites(先决条件):规则的依赖,或者目标的依赖。生成规则目标所依赖的文件名列表。通常,一个目标依赖一个或多个文件。
recipe(命令):规则的命令。规则的命令描述了如何使用规则中的先决条件来最终得到目标。
三、make的工作方式
默认情况下,make执行的是Makefile中的第一个“规则”,则“规则”中的第一个“目标”也可称为“终极目标”(default goal)。
当在命令行输入make命令后,make读取当前目录下的Makefile文件,并开始处理第一个规则,最终的结果是生成“终极目标”。
平时开发过程中,当输入make命令后,工程中以下几种文件应当被编译(或者重新编译):
- 所有没有被编译过的源文件,则对各个源文件进行编译并进行链接,生成最后的可执行程序;
- 每一个在上次执行make之后修改过的源代码文件,在本次执行make时将会被重新编译;
- 头文件在上一次执行make之后被修改,则所有包含此头文件的源文件在本次执行make时应该被重新编译。
make是根据什么来判断需要更新目标的呢?是文件的最后修改时间戳(time of last modification)。make会分别检测目标文件和依赖文件的时间戳,只要其中有任何依赖文件的时间戳“新”于目标,则需要执行命令来更新目标。
make的工作过程如下:
- 依次读取变量“MAKEFILES”定义的makefile文件列表;
- 读取工作目录下的makefile文件(根据命名的查找顺序“GNUmakefile”, “makefile”,“Makefile”,首先找到哪个就读取哪个);
- 依次读取工作目录makefile文件中使用指示符“include”包含的文件;
- 查找重建所有已读取的makefile文件中的规则(如果存在一个目标是当前读取的某一个makefile文件,则执行此规则重建此makefile文件,完成以后从第一步开始重新执行);
- 初始化变量并展开那些需要立即展开的变量和函数并根据预设条件确定执行分支;
- 根据“终极目标”以及依赖关系建立依赖关系链表;
- 执行除“终极目标”以外的所有的目标的规则(规则中如果依赖文件中任一个文件的时间戳比目标文件新,则使用规则所定义的命令重建目标文件);
- 执行“终极目标”所在的规则