Makefile 学习 2 - 基于若干 Blog 的汇总

基于若干 Blog 汇总的 makefile 教程spa

陈皓 https://blog.csdn.net/haoel/article/details/2886操作系统

Makefile 进阶

1. 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 文件名

默认的状况下,make命令会在当前目录下按顺序找寻文件名为“GNUmakefile”、“makefile”、“Makefile”的文件,找到了解释这个文件。在这三个文件名中,最好使用“Makefile”这个文件名,由于,这个文件名第一个字符为大写,这样有一种显目的感受。最好不要用“GNUmakefile”,这个文件是GNU的make识别的。有另一些make只对全小写的“makefile”文件名敏感,可是基本上来讲,大多数的make都持“makefile”和“Makefile”这两种默认文件名。.net

固然,你可使用别的文件名来书写Makefile,好比:“Make.Linux”,“Make.Solaris”,“Make.AIX”等,若是要指定特定的Makefile,你可使用make的“-f”和“--file”参数,如:make -f Make.Linux或make --file Make.AIX。code

3. 引用别的 Makefile

在Makefile使用include关键字能够把别的Makefile包含进来,这很像C语言的 #include,被包含的文件会原模原样的放在当前文件的包含位置。include的语法是:blog

include<filename>
    filename能够是当前操做系统Shell的文件模式(能够保含路径和通配符)

在include前面能够有一些空字符,可是毫不能是[Tab]键开始。include和能够用一个或多个空格隔开。举个例子,你有这样几个Makefile:a.mk、b.mk、c.mk,还有一个文件叫foo.make,以及一个变量$(bar),其包含了e.mk和f.mk,那么,下面的语句:教程

include foo.make *.mk $(bar)

等价于:字符串

include foo.make a.mk b.mk c.mk e.mk f.mk

make命令开始时,会把找寻include所指出的其它Makefile,并把其内容安置在当前的位置。就好像C/C++的#include指令同样。若是文件都没有指定绝对路径或是相对路径的话,make会在当前目录下首先寻找,若是当前目录下没有找到,那么,make还会在下面的几个目录下找:自动化

1.若是make执行时,有“-I”或“--include-dir”参数,那么make就会在这个参数所指定的目录下去寻找。
2.若是目录/include(通常是:/usr/local/bin或/usr/include)存在的话,make也会去找。编译

若是有文件没有找到的话,make会生成一条警告信息,但不会立刻出现致命错误。它会继续载入其它的文件,一旦完成makefile的读取,make会再重试这些没有找到,或是不能读取的文件,若是仍是不行,make才会出现一条致命信息。若是你想让make不理那些没法读取的文件,而继续执行,你能够在include前加一个减号“-”。如:
-include
其表示,不管include过程当中出现什么错误,都不要报错继续执行。和其它版本make兼容的相关命令是sinclude,其做用和这一个是同样的。test

4. Makefile 的工做方式

stage1:

  1. 读入全部的Makefile。
  2. 读入被include的其它Makefile。
  3. 初始化文件中的变量。
  4. 推导隐晦规则,并分析全部规则。
  5. 为全部的目标文件建立依赖关系链。

stage2:

  1. 根据依赖关系,决定哪些目标要从新生成。
  2. 执行生成命令。

第一个阶段中,若是定义的变量被使用了,那么,make会把其展开在使用的位置。但make并不会彻底立刻展开,make使用的是拖延战术,若是变量出如今依赖关系的规则中,那么仅当这条依赖被决定要使用了,变量才会在其内部展开。

5. Makefile 中的通配符

~
波浪号(“~”)字符在文件名中也有比较特殊的用途。若是是“~/test”,这就表示当前用户的$HOME目录下的test目录。而“~hchen/test”则表示用户hchen的宿主目录下的test目录。(这些都是Unix下的小知识了,make也支持)而在Windows或是MS-DOS下,用户没有宿主目录,那么波浪号所指的目录则根据环境变量“HOME”而定。


通配符代替了你一系列的文件,如“.c”表示因此后缀为c的文件。一个须要咱们注意的是,若是咱们的文件名中有通配符,如:“”,那么能够用转义字符“\”,如“”来表示真实的“”字符,而不是任意长度的字符串。

clean:
    rm -f *.o

上面这个例子我不很少说了,这是操做系统Shell所支持的通配符。这是在命令中的通配符。

print: *.c
    lpr -p $?
    touch print

上面这个例子说明了通配符也能够在咱们的规则中,目标print依赖于全部的[.c]文件。其中的“$?”是一个自动化变量,我会在后面给你讲述。

objects = *.o

上面这个例子,表示了,通符一样能够用在变量中。并非说 [.o] 会展开,不!objects的值就是“.o”。Makefile中的变量其实就是C/C++中的宏。若是你要让通配符在变量中展开,也就是让objects的值是全部[.o]的文件名的集合,那么,你能够这样:

objects := $(wildcard *.o)

这种用法由关键字“wildcard”指出,关于Makefile的关键字,咱们将在后面讨论。

6. 文件搜寻

在一些大的工程中,有大量的源文件,咱们一般的作法是把这许多的源文件分类,并存放在不一样的目录中。因此,当make须要去找寻文件的依赖关系时,你能够在文件前加上路径,但最好的方法是把一个路径告诉make,让make在自动去找。

Makefile文件中的特殊变量“VPATH”就是完成这个功能的,若是没有指明这个变量,make只会在当前的目录中去找寻依赖文件和目标文件。若是定义了这个变量,那么,make就会在当当前目录找不到的状况下,到所指定的目录中去找寻文件了。

VPATH = src:../headers

上面的的定义指定两个目录,“src”和“../headers”,make会按照这个顺序进行搜索。目录由“冒号”分隔。(固然,当前目录永远是最高优先搜索的地方)

另外一个设置文件搜索路径的方法是使用make的“vpath”关键字(注意,它是全小写的),这不是变量,这是一个make的关键字,这和上面提到的那个VPATH变量很相似,可是它更为灵活。它能够指定不一样的文件在不一样的搜索目录中。这是一个很灵活的功能。它的使用方法有三种:

  1. vpath < pattern> < directories> 为符合模式< pattern>的文件指定搜索目录。
  2. vpath < pattern> 清除符合模式< pattern>的文件的搜索目录。
  3. vpath 清除全部已被设置好了的文件搜索目录。

vapth使用方法中的< pattern>须要包含“%”字符。“%”的意思是匹配零或若干字符,例如,“%.h”表示全部以“.h”结尾的文件。< pattern>指定了要搜索的文件集,而< directories>则指定了的文件集的搜索的目录。例如:

vpath %.h ../headers

该语句表示,要求make在“../headers”目录下搜索全部以“.h”结尾的文件。(若是某文件在当前目录没有找到的话)

咱们能够连续地使用vpath语句,以指定不一样搜索策略。若是连续的vpath语句中出现了相同的< pattern>,或是被重复了的< pattern>,那么,make会按照vpath语句的前后顺序来执行搜索。如:

vpath %.c foo
   vpath %   blish
   vpath %.c bar

其表示“.c”结尾的文件,先在“foo”目录,而后是“blish”,最后是“bar”目录。

vpath %.c foo:bar
   vpath %   blish

而上面的语句则表示“.c”结尾的文件,先在“foo”目录,而后是“bar”目录,最后才是“blish”目录。

相关文章
相关标签/搜索