对于GNU Make或许很多Windows开发的程序员并不是很了解,因为Windows中的很多集成开发环境(IDE)都帮我们做了这件事。但是作为一个专业从事Linux嵌入式开发的程序员就必须要了解GNU Make,会不会使用GNU Make从一定角度上反应了一个人是否具备大型工程能力。本文主要围绕Make命令展开,介绍Linux下Make的使用以及Makefile的语法和使用Make进行源码安装。 一、什么是GNU Make GNU Make是一个控制从程序的源文件中生成程序的可执行文件和其他非源文件的工具。 Make可以从一个名为Makefile的文件中获得如何构建程序的知识,该文件列出了每个非源文件以及如何从其他文件计算它。当你编写一个程序时,你应该为它编写一个Makefile文件,这样就可以使用Make来编译和安装这个程序。 二、如何获取Make Make可以在GNU的主要FTP服务器上找到:http : //ftp.gnu.org/gnu/make/ (通过HTTP)和 ftp://ftp.gnu.org/gnu/make/ (通过FTP)。它也可以在GNU镜像列表上找到; 请尽可能GNU的镜像列表。 三、为什么需要Make 任何一种技能或知识都是源之于某种社会需求,那为什么要用Make呢?当项目源文件很少的时候,我们也许还可以手动使用gcc命令来进行编译,但是当项目发展到一个庞大的规模时,再手动敲gcc命令去编译就变得不可能的事情。所以呢,在这样的历史背景下,就出现了一位大牛(斯图亚特·费尔德曼),在1977年贝尔实验室制作了这样一个软件,它的名字就叫做Make。所以实际开发中,我们在编译大型项目的时候往往会使用Make进行编译,为此我们还需要了解Make软件所依赖的Makefile规则文件。 四、Makefile Makefile 文件需要按照某种语法进行编写,文件中需要说明如何编译各个源文件并连接生成可执行文件,并要求定义源文件之间的依赖关系。Makefile的语法还是略微有些复杂,因篇幅有限,本文只能简述Makefile的编写原则。 (1)Makefile的组成部分 Makefile包含五个东西:显示规则,隐式规则,变量定义,文件指示,注释。 <1>显式规则,显式规则说明了,如何生成一个或多的的目标文件。这是由Makefile的书写者明显指出,要生成的文件,文件的依赖文件,生成的命令。 <2>隐式规则,由于我们的make有自动推导的功能,所以隐晦的规则可以让我们比较粗糙地简略地书写Makefile,这是由make所支持的。 <3>变量的定义,在Makefile中我们要定义一系列的变量,变量一般都是字符串,这个有点你C语言中的宏,当Makefile被执行时,其中的变量都会被扩展到相应的引用位置上。 <4>文件指示,其包括了三个部分,一个是在一个Makefile中引用另一个Makefile,就像C语言中的include一样;另一个是指根据某些情况指定Makefile中的有效部分,就像C语言中的预编译#if一样;还有就是定义一个多行的命令。有关这一部分的内容,我会在后续的部分中讲述。 <5>注释,Makefile中只有行注释,和UNIX的Shell脚本一样,其注释是用“#”字符,这个就像C/C++中的“//”一样。如果你要在你的Makefile中使用“#”字符,可以用反斜框进行转义,如:“/#”。 (2) Makefile的规则 我们先来粗略地看一看Makefile的规则。 target... : prerequisites ... command ... ... ------------------------------------------------------------------------------- target也就是一个目标文件,可以是Object File,也可以是执行文件。还可以是一个标签(Label),对于标签这种特性,在后续的“伪目标”章节中会有叙述。 prerequisites就是,要生成那个target所需要的文件或是目标。 command也就是make需要执行的命令。(一定要以Tab键作为开头) 这是一个文件的依赖关系,也就是说,target这一个或多个的目标文件依赖于prerequisites中的文件,其生成规则定义在command中。说白一点就是说,prerequisites中如果有一个以上的文件比target文件要新的话,command所定义的命令就会被执行。这就是Makefile的规则。也就是Makefile中最核心的内容。 (3)Makefile之模式规则 模式规则其实也是普通规则,但它使用了如%这样的通配符。如下面的例子: 此规则描述了一个.o文件如何由对应的.c文件创建。规则的命令行中使用了自动化变量“$<”和“$@”,其中自动化变量“$<”代表规则的依赖,“$@”代表规则的目标。此规则在执行时,命令行中的自动化变量将根据实际的目标和依赖文件取对应值。 其含义是,字指出了从所有的.c文件生成相应的.o文件的规则。如果要生成的目标是”a.o b.o”,那么 %.c”就是”a.c b.c”。 在模式规则中,目标的定义需要有“%”字符。“%”定义对文件名的匹配,表示任意长度的非空字符串。在依赖目标中同样可以使用“%”,只是依赖目标中“%”的取值,取决于其目标。 注意:模式规则中“%”的展开和变量与函数的展开是有区别的,“%”的展开发生在变量和函数的展开之后。变量和函数的展开发生在make载入Makefile时,而“%”的展开则发生在运行时。 <1> 自动化变量 自动化变量只应出现在规则的命令中。变量含义$@表示规则中的所有目标文件的集合。在模式规则中如果有多个目标,“$@”就是匹配于目标中模式定义的集合$%仅当目标是函数库文件时,表示规则中的目标成员名,如果目标不是函数库文件(UNIX下是.a,Windows是.lib),其值为空。$<依赖目标中的第一个目标名字,如果依赖目标是以模式(即”%“)定义的,则”$<”是符合模式的一系列的文件集$?所有比目标新的依赖目标的集合,以空格分隔$^所有依赖目标的集合,以空格分隔。如如果在依赖目标中有多个重复的,则自动去除重复的依赖目标,只保留一份$+同”$^”,也是所有依赖目标的集合,只是它不去除重复的依赖目标。$*目标模式中“%”及其之前的部分$(@D)“$@”的目录部分(不以斜杠作为结尾),如果”$@”中没有包含斜杠,其值为“.”(当前目录)$(@F)“$@”的文件部分,相当于函数”$(notdir $@)”$(*D)同”$(@D)”,取文件的目录部分$(*F)同”$(@F)”,取文件部分,但不取后缀名$(%D)函数包文件成员的目录部分$(%F)函数包文件成员的文件名部分$(<d)</d)依赖目标中的第一个目标的目录部分$(<f)</f)依赖目标中的第一个目标的文件名部分$(^D)所有依赖目标文件中目录部分(无相同的)$(^F)所有依赖目标文件中文件名部分(无相同的)$(+D)所有依赖目标文件中的目录部分(可以有相同的)$(+F)所有依赖目标文件中的文件名部分(可以有相同的)$(?D)所有被更新文件的目录部分$(?F)所有被更新文件的文件名部分
一周热门 更多>