热爱户外运动,热爱Linux系统
分类: LINUX
2013-03-11 21:57:45
什么是make?
make是一种自动化工具,用于解决更新依赖问题。所谓更新依赖,是指一个对象的更新,会导致其它对象过期,失效,必须重新创建或更新过期对象,以保证过期对象的有效性。这里的对象,一般是指文件。例如,源文件main.c在编译之后生成目标文件main.o,当main.c更新后,我们必须重新编译生成main.o, 即main.o的更新依赖于main.c, make 就擅长处理这类问题,主要用于自动控制大型程序源代码的编译流程,像Linux内核的编译。
什么是Makefile?
make之所以能够自动解决更新依赖问题,是因为有“人”告诉它各对象之间的更新依赖关系,以及如何解决更新依赖的方法, 这个“人”就是Makefile,Makefile的核心任务就是:
1. 告诉make, 什么时候对象过期
2. 告诉make, 如何处理过期对象
Makefile 的命名。
GNU make默认识别的Makefile文件名,依次为GNUmakefile , makefile,
Makefile。若不使用上述标准命名,则必须使用-f name或—file=name 选项指定文件名。GNUmakefile 仅能被GNU make识别,其它的make无法识别,一般不使用。一般使用makefile 或 Makefile。推荐使用Makefile。因为,在目录列表中,Makefile靠近起始部分,并且靠近其它重要文件,例如README。
Makefile rule 的语法格式
依赖关系 + 解决方法 = 规则(rule),是Makefile最核心,最基本的东西,其语法格式有两种:
1.
target 。。。 : prerequisites 。。。
recipe
。。。
2.
target 。。。 : prerequisites 。。。 ;recipe
recipe
。。。
其中target(目标)与 prerequisite (前提)构成了依赖关系,而recipe(方法)构成了解决方法
依赖关系有两层含义,分别是更新依赖,更新顺序依赖
更新依赖
target永远是最年轻的(时间戳最新),它见不得任何一个prerequisite比它年轻,若存在这样的prerequisite, target将涅磐重生。
这是一种更新依赖关系,即:prerequisite的更新导致target的更新。
更新顺序依赖
当target需要更新时, make首先把prerequisites分别作为一个target,尝试对其更新,等所有的prerequisite处理完毕,再对target进行更新处理,这是一个递归处理过程, 也是一种更新顺序依赖关系,即:prerequisite 的更新先于target的更新。
说到依赖关系,不得不提prerequisite的分类,实际上,prerequisite分两类,分别是普通,顺序,类属的划分跟依赖关系的含义相关。普通prerequisite(normal
prerequisite)满足依赖关系的两层含义,而顺序prerequisite(order-only prerequisite)只满足依赖关系的更新顺序依赖,不满足更新依赖,也就是说,此prerequisite的更新,不会导致target的更新,但当target需要更新时,此prerequisite会像其它普通prerequisite一样,参与target的更新。在rule的语法格式中,用如下方式区分两类prerequisite,
order-only-prerequisite置于normal-prerequisite的后面,并用“|”隔开,其中normal-prerequisite可以为空,但“|”不可省略。
targets :normal-prerequisites | order-only-prerequisites
解决方法
recipe由shell命令构成,负责target的涅槃(一般情况是这样),
make不会直接执行recipe, 而是把它丢给shell处理,另外,recipe行(新行,不包含直接跟在prerequisite之后的recipe)必须以Tab键(或.RECIPEPREFIX的值)打头,这些都是需要特别注意的地方。
同一个target可以同时处在多条rule中,多个target也可同时处在一条rule中,如下所示
1. target A, 处在三条rule中
A : B C
recipeA1
A :B D
recipeA2
A :E
2. target A, B, C处在一条rule中
A B C :D
recipeABC
make 对上述规则的处理原则是一致的:一个target对应一条规则。
当一个target分处在多条规则中时,make会把多条规则合成一条规则,规则的prerequisite是所有prerequisite的集合,而recipe是最后一个非空recipe。经make处理后,例1的结果为
A :B C D E
recipeA2
当一个规则有多个target时,make会把此规则分解成多条规则,每一个target独占一条规则,分解出的多条规则,除target不一样外,其它完全相同。经make处理后,例2的结果为
A :D
recipeABC
B :D
recipeABC
C :D
recipeABC
简单的说就是,
多目标,要分解
多规则,要合一
一句话,经make处理后的 makefile,每一条规则只包含一个target,规则与规则的target都是唯一的,均不相同。
需要注意的几个点:
1. 一条规则中不仅可有多个prerequisite,也可有多个target,相互之间以空格间隔。
2. recipe行必须以Tab键(或.RECIPEPREFIX的值)打头。
3. 只要以Tab键(或.RECIPEPREFIX的值)打头的行,make均视作recipe
4. prerequisite 和recipe均可以为空,但target不得为空。
5. recipe由shell命令组成,并由shell负责执行,make不参与recipe的执行。
除了规则外,Makefile还包含变量,指令,注释。