系统未建立
分类: LINUX
2018-03-26 11:08:21
原文地址:Makefile 学习笔记二 作者:好喜儿
在一个完整的Makefile 中,包含了5 个东西:显式规则、隐含规则、变量定义、
指示符和注释
显式规则:它描述了在何种情况下如何更新一个或者多个被称为目标的文件
(Makefile 的目标文件)。(就是规则)
隐含规则:它是make根据一类目标文件(典型的是根据文件名的后缀)而自
动推导出来的规则
变量定义:使用一个字符或字符串代表一段文本串,当定义了一个变量以后,
Makefile后续在需要使用此文本串的地方,通过引用这个变量来实现对文本串
的使用。
Makefile 指示符:指示符指明在make程序读取makefile 文件过程中所要执
行的一个动作。其中包括:
— 读取一个文件,读取给定文件名的文件,将其内容作为makefile文件的一
部分。参考 3.3 包含其它makefile文件一节
— 决定(通常是根据一个变量的得值)处理或者忽略Makefile中的某一特定
部分。参考 第七章Makefile的条件执行
— 定义一个多行变量。参考 6.8 多行定义 一节
Makefile 中“# ”字符后的内容被作为是注释内容(和 shell脚本一样)
处理。如果此行的第一个非空字符为“# ”,那么此行为注释行。注释行的结尾如果存在反斜线(\ ),那么下一行也被作为注释行。一般在书写Makefile时推荐将注释作为一个独立的行
注意:Makefile 中第一个规则之后的所有以[Tab]字符开始的的行,make程序都会将其交
给系统shell程序去解释执行。因此,以[Tab]字符开始的注释行也会被交给shell来处
理,此命令行是否需要被执行(shell执行或者忽略)是由系统shell程序来判决的。
make会在工作目录(执行 make的目录)下按照文件名顺序寻找makefile 文件读取并执行,查找的文件名顺序为:“GNUmakefile ”、“makefile”、“Makefile”。
“GNUmakefile ”是我们不推荐使用的文件名,因为以此命名的文件只有“GNU make ”
才可以识别,而其他版本的make程序只会在工作目录下“makefile”和“Makefile”这两个文件
给make 指定makefile 文件的格式为:“-f NAME ”或者“—file=NAME”
“include”指示符告诉make暂停读取当前的Makefile,而转去读取“include”指定的一个或者多个文件,完成以后再继续当前Makefile 的读取
“include”书写在独立的一行,其形式如下:
include FILENAMES...
指示符“include”所在的行可以一个或者多个空格(make程序在处理时将忽略这些空格)开始,切忌不能以[Tab]字符开始(如果一行以[Tab]字符开始make程序将此行作为一个命令行来处理)。 指示符“include”和文件名之间、多个文件之间使用空格或者[Tab]键隔开
通常指示符“include”用在以下场合:
1. 有多个不同的程序,由不同目录下的几个独立的Makefile来描述其重建规则
2. 当根据源文件自动产生依赖文件时;我们可以将自动产生的依赖关系保存在另外一个文件中,主Makefile使用指示符“include”包含这些文件。
如果在当前环境定义了一个“MAKEFILES”环境变量,make执行时首先将此变量的值作为需要读入的Makefile文件,多个文件之间使用空格分开。类似使用指示符“include”包含其它Makefile文件一样
推荐的做法实:在需要包含其它makefile 文件时使用指示符“include”来实现。
make程序在读取多个makefile 文件时,包括由环境变量“MAKEFILES”指定、命令行指、当前工作下的默认的以及使用指示符“include”指定包含的,在对这些文件进行解析执行之前make 读取的文件名将会被自动依次追加到变量
“MAKEFILE_LIST”的定义域中。
一个重要的特殊的变量是“.VARIABLES ”。它被展开以后是此引用点之前、makefile文件中所定义的所有全局变量列表。包括:空变量(未赋值的变量)和make的内嵌变量(参考10.3 隐含变量 一节),但不包含目标指定的变量,目标指定变量值在特定目标的上下文有效。
Makefile 可由其它文件生成,例如RCS或SCCS 文件。如果Makefile 由其它文件重建,那么在make在开始解析这个Makefile 时需要重新读取更新后的Makefile、而不是之前的Makefile实际应用中,我们会明确给出makefile文件,而并不需要来由make自动重建它们
make在每一次执行时总会自动地试图重建那些已经存在的makefile文件,如果需要处于效率考虑,可以采用一些办法来避免make在执行过程时查找重建makefile的隐含规则。例如我们可以书写一个明确的规则,以makefile文件作为目标,规则的命令定义为空。(参考 5.8 空命令 一节)
Makefile规则中,如果使用一个没有依赖只有命令行的双冒号规则去更新一个文件,那么每次执行make时,此规则的目标文件将会被无条件的更新(此规则定义的命令会被无条件执行)
有些情况下,存在两个比较类似的 makefile 文件。其中一个(makefile-A)需要使用另外一个(makefile-B)中所定义的变量和规则.
但使用这种方式,如果在两个makefile 文件中存在相同目标,而在不同的文件中其描述规则使用不同的命令。
在需要包含的makefile文件(makefile-A)中,定义一个称之为“所有匹配模式”(参考 10.5 模式规则 一节)的规则,它用来述那些在“makefile-A”中没有给出明确创建规则的目标的重建规则
(讲的很清晰)
第一阶段:读取所有的makefile 文件(包括“MAKIFILES”变量指定的、指示符“include”指定的、以及命令行选项“-f(--file)”指定的makefile 文件),内建所有的变量、明确规则和隐含规则,并建立所有目标和依赖之间的依赖关系结构链表
在第二阶段:根据第一阶段已经建立的依赖关系结构链表决定哪些目标需要更新,并使用对应的规则来重建这些目标。
首先,明确以下基本的概念;在make执行的第一阶段中如果变量和函数被展开,那么称此展开是“立即”的,此时所有的变量和函数被展开在需要构建的结构链表的对应规则中(此规则在建立链表是需要使用)。其他的展开称之为“延后”的。这些变量和函数不会被“立即”展开,而是直到后续某些规则须要使用时或者在make处理的第二阶段它们才会被展开
当变量使用追加符(+=)时,如果此前这个变量是一个简单变量(使用 :=定义的)则认为它是立即展开的,其它情况时都被认为是“延后”展开的变量。
所有使用到条件语句在产生分支的地方,make程序会根据预设条件将正确地分支展开。就是说条件分支的展开是“立即”的。其中包括:“ifdef ”、“ifeq ”、“ifndef ”和“ifneq”所确定的所有分支命令。
所有的规则在make执行时,都按照如下的模式展开:
IMMEDIATE : IMMEDIATE ; DEFERRED
DEFERRED
其中,规则中目标和依赖如果引用其他的变量,则被立即展开。而规则的命令行中
的变量引用会被延后展开。此模板适合所有的规则,包括明确规则、模式规则、后缀规
则、静态模式规则