基于若干 Blog 汇总的 makefile 教程spa
陈皓 https://blog.csdn.net/haoel/article/details/2886操作系统
默认的状况下,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
在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
stage1:
stage2:
第一个阶段中,若是定义的变量被使用了,那么,make会把其展开在使用的位置。但make并不会彻底立刻展开,make使用的是拖延战术,若是变量出如今依赖关系的规则中,那么仅当这条依赖被决定要使用了,变量才会在其内部展开。
~
波浪号(“~”)字符在文件名中也有比较特殊的用途。若是是“~/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的关键字,咱们将在后面讨论。
在一些大的工程中,有大量的源文件,咱们一般的作法是把这许多的源文件分类,并存放在不一样的目录中。因此,当make须要去找寻文件的依赖关系时,你能够在文件前加上路径,但最好的方法是把一个路径告诉make,让make在自动去找。
Makefile文件中的特殊变量“VPATH”就是完成这个功能的,若是没有指明这个变量,make只会在当前的目录中去找寻依赖文件和目标文件。若是定义了这个变量,那么,make就会在当当前目录找不到的状况下,到所指定的目录中去找寻文件了。
VPATH = src:../headers
上面的的定义指定两个目录,“src”和“../headers”,make会按照这个顺序进行搜索。目录由“冒号”分隔。(固然,当前目录永远是最高优先搜索的地方)
另外一个设置文件搜索路径的方法是使用make的“vpath”关键字(注意,它是全小写的),这不是变量,这是一个make的关键字,这和上面提到的那个VPATH变量很相似,可是它更为灵活。它能够指定不一样的文件在不一样的搜索目录中。这是一个很灵活的功能。它的使用方法有三种:
- vpath < pattern> < directories> 为符合模式< pattern>的文件指定搜索目录。
- vpath < pattern> 清除符合模式< pattern>的文件的搜索目录。
- 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”目录。