Makefile里有什么
1、显式规则:要生成的文件,依耐文件和命令
2、隐晦规则:make有自动推导功能,所以我们有些地方可以不用写那么全, make会自动推导出来
3、变量的定义:makefile中变量经常被用到,这样会很方便修改,对后期的调试会带来很多好处。变量一般都是字符串,这里的作用其实和C语言的宏很想。
4、文件指示: 一个类似于C语言当中的include,包含头文件这个宏。在写makefile时也会用到引用另一个makefile时。再一个就是和C语言里的#if一样判断条件后再决定这一块代码区是否有效。还有一个就是定义多行的命令。
5、注释: makefile中只有行注释,“#”,类似于C语言里面的“//”。但是如果有时候要在makefile里用到#这个符号,可以使用反斜杠/进行转义,这样#就不是注释的功能,他会被看待成一个要被使用的符号。例:"/#"
makefile的文件名
“makefile”
“Makefile”
“GNUmakefile”
最好使用后面的两种
但是如果想自己定义一个文件名也可以,比如:“xhp.makefile”
不过在指定特定的文件名后,使用make命令的时候就有所变化了,可以使用make的"-f"和"–file"参数,例: make -f xhp.makefile 或者 make --file xhp.makefile
引用其它makefile
如同C语言所常见的
#include “****.h”
在编写makefile时也会有这种情况,只是语法规则稍有不同。
假如我需要包含几个makefile文件和变量。
分别有:makefile_1.mk、makefile_2.mk、makefile_3.mk、一个变量$(variable),此变量其实是包含的makefile_4.mk和makefile_5文件,还有一个名为file.make的文件,我们就可以利用include包含进来:
include file.make *.mk $(variable)
include前面可以有空格,但是绝不能是[tab]键开头,否则就被make视为命令。中间可以有多个空格隔开,不影响程序的功能。
上面语句其实等价于:
include file.make makefile_1.mk makefile_2.mk /
makefile_3.mk makefile_4 makefile_5
如果执行include语句时出现了找不到的文件,也不会中断程序的执行,只会提出警告,等载入后面全部的文件之后才会报错,但如果想不理睬这些错误,也可以这样,在include前面加一个小减号。例:
-include file.make makefile_1.mk makefile_2.mk /
makefile_3.mk makefile_4 makefile_5
加上小减号后,就告诉make,无论出现什么你错误都继续往后面执行,不理睬没有载入的文件。
make的工作方式
make执行步骤如下:
1、读入所有的Makefile
2、读入被include引用的makefile
3、初始化文件中的变量
4、推导出隐晦规则,并分析所有规则
5、为所有的目标文件创建依赖关系链
6、根据依赖关系,决定哪些依赖关系需要重新生成
7、执行生成命令
书写规则
规则包含两个部分,一个是依赖关系,另一个时生成目标的方法
在makefile中,规则的顺序很重要,只有第一条规则当中的目标才是makefile的最终目标。其他的目标都是被这个目标所连带出来的。
规则的语法
targets : prerequisites
[tab]command
或者是这样:
targets : prerequisites;command
[tab]command
targets是文件名,以空格分隔开,目标有可能是一个文件或者多个文件
在规则中使用通配符
波浪号“ ~ ”在文件名中也有比较特殊的用途。如果是 “ ~/test”,表示是在当前用户的$HOME目录下的test目录。
通配符代替了一系列的文件,如“.c”表示所有后缀为.c的文件。如果我们文件名中带有通配符,如: “ * ”
那么可以用转义字符“/”,如“/”来表示真实的“”字符,而不是字符串
文件搜寻
1、VPATH
当在当前目录下面找不到的情况下,就会到VPATH所指定的目录下面寻找文件。例:
VPATH = src : ../headers
上面的定义指定了两个目录,一个是“src”,另一个是“…/headers”,make会按照先后顺序进行搜寻。每个目录由冒号分隔开。当前目录永远是最高优先搜索的地方。
2、vpath
注意这个是小写,上面那个是大写,这个功能更强大。这是一个关键字,它可以指定不同文件在不同的搜索目录中。
(1)vpath <pattern> <directories>
为符合 “pattern” 的文件指定搜索目录" directories "
(2)vpath <pattern>
清除符合模式 “pattern” 的文件的搜索目录
(3)vpath
清除所有已被设置好了的文件搜索目录
伪目标
伪目标一般是没有依赖文件的,不过有时也可以有依赖文件。
例:
OBJ : Task1 Task2 Task3
.PHONY : OBJ
Task1 : Task1.o
[Tab]gcc -o Task1 Task1.o
Task2 : Task1.o
[Tab]gcc -o Task2 Task2.o
Task3 : Task1.o
[Tab]gcc -o Task3 Task3.o
makefile的第一个规则的目标会成为整个makefile的最终目标。但是我们可以利用伪目标这个功能,声明一个OBJ为伪目标,OBJ这个目标依赖于其他三个目标。伪目标的特性是总是被执行的,所以其他三个目标总是不如OBJ新,所以每次都会被执行。所以我们一次性能生成三个可执行文件
从这个例子我们可以看出,目标也可以成为依赖。所以伪目标同样可以成为依赖。
例:
.PHONY : file1 file2 file3
file1 : file2 file3
[Tab]rm test
file2 :
[Tab]rm *.o
file3 :
[Tab]rm *.diff
这段makefile的意思很好理解
如果我们只用make命令不带参数或者make file1,那整段程序的作用就是删除test、删除当前目录下面的.o文件、删除当前目录下面的.diff文件
如果我们使用make file2,那么它的作用就是删除当前目录下面的.o文件
如果我们使用make file3,那么它的作用就是删除当前目录下面的.diff文件
参考资料:
https://blog.csdn.net/haoel/article/details/2889