(02)Makefile综述

来源:互联网 发布:四川麻将规则算法 编辑:程序博客网 时间:2024/05/16 19:26

02_1.Makefile的内容



在一个完整的 Makefile 中,包含了 5 个东西:显式规则、隐含规则、变量定义、指示符和注释。


1.显式规则:它描述了在何种情况下如何更新一个或者多个被称为目标的文件(Makefile 的目标文件) 。书写 Makefile 时需要明确地给出目标文件、目标的依赖文件列表以及更新目标文件所需要的命令(有些规则没有命令,这样的规则只是纯粹的描述了文件之间的依赖关系)。 


2.隐含规则:它是make根据一类目标文件(典型的是根据文件名的后缀)而自动推导出来的规则。make根据目标文件的名,自动产生目标的依赖文件并使用默认的命令来对目标进行更新(建立一个规则)。


3.变量定义:使用一个字符或字符串代表一段文本串,当定义了一个变量以后,Makefile后续在需要使用此文本串的地方,通过引用这个变量来实现对文本串的使用。


4.Makefile 指示符:指示符指明在 make 程序读取 makefile 文件过程中所要执行的一个动作。其中包括:
(1)读取一个文件,读取给定文件名的文件,将其内容作为makefile文件的一部分。
(2)决定(通常是根据一个变量的得值)处理或者忽略Makefile中的某一特定部分。
(3)定义一个多行变量。


5.注释:Makefile 中“#”字符后的内容被作为是注释内容(和shell 脚本一样)处理。如果此行的第一个非空字符为“#” ,那么此行为注释行。当在Makefile 中需要使用字符“#”时,可以使用反斜线加“#”(\#)来实现(对特殊字符“#”的转义),其表示将“#”作为一字符而不是注释的开始标志。


需要注意的地方: 
Makefile 中第一个规则之后的所有以[Tab]字符开始的的行,make程序都会将其交给系统 shell程序去解释执行。因此,以[Tab]字符开始的注释行也会被交给 shell 来处理,此命令行是否需要被执行(shell执行或者忽略)是由系统 shell程序来判决的。
 另外,在使用指示符“define”定义一个多行的变量或者命令包时,其定义体(“define”和“endef”之间的内容)会被完整的展开到 Makefile 中引用此变量的地方(包含定义体中的注释行) ;make 在引用此变量的地方对所有的定义体进行处理,决定是注释还是有效内容.对一个变量引用的地方 make 所做的就是将这个变量根据定义进行基于文本的展开,展开变量的过程不涉及到任何变量的具体含义和功能分析。


02_2.Makefile的命名

 
 默认的情况下,make会在工作目录(执行make的目录)下按照文件名顺序寻找makefile 文件读取并执行,查找的文件名顺序为: “GNUmakefile”、“makefile”、“Makefile”。

当 makefile 文件的命名不是这三个任何一个时,需要通过 make的“-f”或者“--file”选项来指定 make 读取的 makefile 文件。


也可以通过多个“-f”或者“--file”选项来指定多个需要读取的 makefile 文件,多个 makefile 文件将会被按照指定的顺序进行链接并被make解析执行。当通过“-f”或者“--file”指定 make读取 makefile 的文件时,make就不再自动查找这三个标准命名的 makefile 文件。


02_3.包含其它makefile文件



02_3_1.使用include

“include”指示符告诉 make 暂停读取当前的 Makefile,而转去读取“include”指定的一个或者多个文件,完成以后再继续当前 Makefile 的读取。Makefile 中指示符“include”书写在独立的一行,其形式如下:
include FILENAMES... 
FILENAMES是 shell 所支持的文件名(可以使用通配符)。指示符“include”所在的行可以一个或者多个空格


通常指示符“include”用在以下场合:
(1)有多个不同的程序,由不同目录下的几个独立的Makefile来描述其重建规则。它们需要使用一组通用的变量定义或者模式规则.通用的做法是将这些共同使用的变量或者模式规则定义在一个文件中(没有具体的文件命名限制) ,在需要使用的Makefile中使用指示符“include”来包含此文件。
(2)当根据源文件自动产生依赖文件时;我们可以将自动产生的依赖关系保存在另外一个文件中,主Makefile使用指示符“include”包含这些文件。


02_3_2.使用-include/sinclude

通常我们在 Makefile 中可使用“-include”来代替“include” ,来忽略由于包含文件不存在或者无法创建时的错误提示(“-”的意思是告诉 make,忽略此操作的错误。make继续执行)。
以下是这两种方式的比较: 
使用“include FILENAMES...”,make程序处理时,如果“FILENAMES”列表中的任何一个文件不能正常读取而且不存在一个创建此文件的规则时 make 程序将会提示错误并退出。 
使用“-include FILENAMES...”的情况是,当所包含的文件不存在或者不存在一个规则去创建它,make程序会继续执行,只有真正由于不能正确完成终极目标的重建时(某些必需的目标无法在当前已读取的makefile 文件内容中找到正确的重建规则) ,才会提示致命错误并退出。 
为了和其它的 make 程序进行兼容。也可以使用“sinclude”来代替“-include”(GNU所支持的方式)。 


02_3_3.变量MAKEFILES

如果在当前环境定义了一个“MAKEFILES”环境变量,make执行时首先将此变量的值作为需要读入的Makefile文件,多个文件之间使用空格分开。类似使用指示符“include”包含其它Makefile文件一样,如果文件名非绝对路径而且当前目录也不存在此文件,make会在一些默认的目录去寻找


它和使用“include”的区别:
1.  环境变量指定的 makefile 文件中的“目标”不会被作为 make 执行的“终极目标”
2.  环境变量所定义的文件列表,在执行 make 时,如果不能找到其中某一个文件(不存在或者无法创建) 。make 不会提示错误,也不退出。
3. make在执行时,首先读取的是环境变量“MAKEFILES”所指定的文件列表,之后才是工作目录下的 makefile 文件,“include”所指定的文件是在 make 发现此关键字的时、暂停正在读取的文件而转去读取“include”所指定的文件。


实际应用中很少设置此变量。因为一旦设置了此变量,在多级make调用时;由于每一级make都会读取“MAKEFILES”变量所指定的文件,将导致执行出现混乱(这可能不是你想看到的执行结果) 。不过,我们可以使用此环境变量来指定一个定义了通用“隐含规则”和变量的文件,比如设置默认搜索路径.
通过这种方式设置的“隐含规则”和定义的变量可以被任何make进程使用。


02_4.变量 MAKEFILE_LIST



make 程序在读取多个 makefile 文件时,包括由环境变量“MAKEFILES”指定、命令行指定、当前工作下的默认的以及使用指示符“include”指定包含的,在对这些文件进行解析执行之前 make 读取的文件名将会被自动依次追加到变量“MAKEFILE_LIST”的定义域中。 
这样我们就可以通过测试此变量的最后一个字来获取当前 make 程序正在处理的makefile 文件名。


02_5.其它特殊变量



GNU make支持一个特殊的变量,此变量不能通过任何途经给它赋值。它被展开为一个特定的值。一个重要的特殊的变量是“.VARIABLES” 。它被展开以后是此引用点之前、makefile文件中所定义的所有全局变量列表。包括:空变量(未赋值的变量)和make的内嵌变量,但不包含目标指定的变量,目标指定变量值在特定目标的上下文有效。


02_6.make如何解析makefile文件



GUN make 的执行过程分为两个阶段。 
第一阶段:读取所有的 makefile 文件(包括“MAKIFILES”变量指定的、指示符“include”指定的、以及命令行选项“-f(--file)”指定的 makefile 文件),内建所有的变量、明确规则和隐含规则,并建立所有目标和依赖之间的依赖关系结构链表。 
第二阶段:根据第一阶段已经建立的依赖关系结构链表决定哪些目标需要更新,并使用对应的规则来重建这些目标。


首先,明确以下基本的概念;在 make执行的第一阶段中如果变量和函数被展开,那么称此展开是“立即”的,此时所有的变量和函数被展开在需要构建的结构链表的对应规则中(此规则在建立链表时需要使用) 。
其他的展开称之为“延后”的。这些变量和函数不会被“立即”展开,而是直到后续某些规则须要使用时或者在make处理的第二阶段它们才会被展开。

























0 0
原创粉丝点击