Makefile里主要包含了五个东西:显式规则、隐晦规则、变量定义、文件指示和注释
显式规则:显式规则说明了,如何生成一个或多的的目标文件。这是由Makefile的书写者明显指出,要生成的文件,文件的依赖文件,生成的命令。
隐晦规则:由于我们的make有自动推导的功能,所以隐晦的规则可以让我们比较粗糙地简略地书写Makefile,这是由make所支持的。
变量的定义:在Makefile中我们要定义一系列的变量,变量一般都是字符串,这个有点你C语言中的宏,当Makefile被执行时,其中的变量都会被扩展到相应的引用位置上。
文件指示:其包括了三个部分,一个是在一个Makefile中引用另一个Makefile,就像C语言中的include一样;另一个是指根据某些情况指定Makefile中的有效部分,就像C语言中的预编译#if一样;还有就是定义一个多行的命令。有关这一部分的内容,我会在后续的部分中讲述。
注释:Makefile中只有行注释,和UNIX的Shell脚本一样,其注释是用“#”字符,这个就像C/C++中的“//”一样。如果你要在你的Makefile中使用“#”字符,可以用反斜框进行转义,如:\#
makefile中经常会出现这三个变量 $@,$^,$<代表的意义分别是: 他们三个是十分重要的三个变量,所代表的含义分别是:
$@–目标文件,$^–所有的依赖文件,$<–第一个依赖文件。
只要make看到一个[.o]文件,它就会自动的把[.c]文件加在依赖关系中,如果make找到一个whatever.o,那么whatever.c,就会是whatever.o的依赖文件。并且 cc -c whatever.c 也会被推导出来
main.o : defs.h 等同于 main.o : main.c defs.h
.PHONY : clean
clean :
-rm a.out *.o
.PHONY意思表示clean是一个“伪目标”,而在rm命令前面加了一个小减号的意思就是,也许某些文件出现问题,但不要管,继续做后面的事。当然,clean的规则不要放在文件的开头,不然,这就会变成make的默认目标,相信谁也不愿意这样。不成文的规矩是“clean从来都是放在文件的最后”
make工作时的执行步骤
- 读入所有的Makefile。
- 读入被include的其它Makefile。
- 初始化文件中的变量。
- 推导隐晦规则,并分析所有规则。
- 为所有的目标文件创建依赖关系链。
- 根据依赖关系,决定哪些目标要重新生成。
- 执行生成命令。
1-5步为第一个阶段,6-7为第二个阶段。第一个阶段中,如果定义的变量被使用了,那么,make会把其展开在使用的位置。但make并不会完全马上展开,make使用的是拖延战术,如果变量出现在依赖关系的规则中,那么仅当这条依赖被决定要使用了,变量才会在其内部展开。
makefile常见的目标命名含义:
“all”
这个伪目标是所有目标的目标,其功能一般是编译所有的目标。
“clean”
这个伪目标功能是删除所有被make创建的文件。
“install”
这个伪目标功能是安装已编译好的程序,其实就是把目标执行文件拷贝到指定的目标中去。
“print”
这个伪目标的功能是例出改变过的源文件。
“tar”
这个伪目标功能是把源程序打包备份。也就是一个tar文件。
“dist”
这个伪目标功能是创建一个压缩文件,一般是把tar文件压成Z文件。或是gz文件。
“TAGS”
这个伪目标功能是更新所有的目标,以备完整地重编译使用。
“check”和“test”
这两个伪目标一般用来测试makefile的流程。
Makefile的规则
target ... : prerequisites ...
command
...
...
target也就是一个目标文件,可以是Object File,也可以是执行文件。还可以是一个标签(Label)。如果只输入make的话,他会自动执行makefild中的第一个target。
prerequisites就是,要生成那个target所需要的文件或是目标。
command也就是make需要执行的命令。(任意的Shell命令) (一定要以一个Tab键作为开头)
Makefile使用变量
赋值:
objects = main.o kbd.o 直接使用变量赋值就行,不需要定义
当给变量赋值时,赋值右边也有变量时,最好用”:=“赋值,表示赋当前变量的值(效率高,不要一直去算右边变量的值,不会出意想不到的错误),例如
x = foo
y = $(x) bar
x = later
现在y的值为 later bar
x := foo
y := $(x) bar
x := later
现在y的值为 foo bar
FOO ?= bar
其含义是,如果FOO没有被定义过,那么变量FOO的值就是“bar”,如果FOO先前被定义过,那么这条语将什么也不做 。
输出:
edit : $(objects) 使用的时候一定要加$(),这样才是取值,跟指针取值类似
$(warning $(objects)) $( error $(objects)) Makefile中打印变量值只能以警告的形式或者错误的形式打印出来(注意只要碰到error打印,makefile边直接退出不会继续往下执行)
变量值的替换:
1:foo := a.o b.o c.o
bar := $(foo:.o=.c)
这里的bar就等于 a.c b.c c.c
2:foo := a.o b.o c.o
bar := $(foo:%.o=%.c)
这里的bar也等于 a.c b.c c.c
追加变量值:
objects = main.o foo.o bar.o utils.o
objects += another.o
$(objects)值变成:“main.o foo.o bar.o utils.o another.o”如果前次的赋值符是“=”,所以“+=”也会以“=”来做为赋值,如果前一次的是“:=”,那么“+=”会以“:=”作为其赋值符
override 指示符:
变量是可以make的命令行参数设置的,如果你只想在makefile文本里去改这个值,只需要赋值的时候在前面加上override指示,例如
override obj = a.o
define指示符:
define指示符后面跟的是变量的名字,而重起一行定义变量的值,定义是以endef关键字结束。其工作方式和“=”操作符一样。变量的值可以包含函数、命令、文字,或是其它变量。使用define关键字设置变量的值可以有换行。(一般用于合成几条命令,然后放在某个目标中去执行)
define obj
this is
obj
endef
obj就等于
his is
obj
目标变量:
prog : CFLAGS = -g
prog : prog.o foo.o bar.o
$(CC) \$(CFLAGS) prog.o foo.o bar.o
全局的$(CFLAGS)的值是什么,在prog目标,以及其所引发的所有规则中(prog.o foo.o bar.o的规则),$(CFLAGS)的值都是“-g”
%.o : CFLAGS = -O
表示只要目标是.o结尾的,里面的CFLAGS的值一直是“-O”
make自动推导
GNU的make很强大,它可以自动推导文件以及文件依赖关系后面的命令,只要make看到一个[.o]文件,它就会自动的把[.c]文件加在依赖关系中。
main.o : defs.h 就等于 main.o : main.c defs.h
Makefile的命名规则
Makefile文件命名一般都会是“GNUmakefile”、“makefile”、“Makefile”,直接执行make就能找到这三个文件,也可以随意命名执行make命名时指定文件名。
如:make -f Make.Linux或make --file Make.AIX。
Makefile中引用其他的Makefile
在Makefile使用include关键字可以把别的Makefile包含进来,这很像C语言的#include,被包含的文件会原模原样的放在当前文件的包含位置。
include foo.make ./test/test.make 包含的哪个makefile写在前面就先执行哪个makefile,可以带路径,
如果没带路径的话会去三个地方找:
1:当前路径。
2:执行make时,有-I参数指定路径时。
3:系统的一些文件的地方(一般是:/usr/local/bin或/usr/include)
Makefile中执行其他的Makefile
例如,我们有一个子目录叫subdir,这个目录下有个Makefile文件,来指明了这个目录下文件的编译规则。那么我们总控的Makefile可以这样书写:
subsystem:
cd subdir && $(MAKE)
其等价于:
subsystem:
$(MAKE) -C subdir
定义$(MAKE)宏变量的意思是,也许我们的make需要一些参数,所以定义成一个变量比较利于维护。这两个例子的意思都是先进入“subdir”目录,然后执行make命令。
如果想往下级makefile文件中传递变量,就要使用 export命令,如果不想传某个变量就使用 unexport命令
1:export 所有的变量都会传递到下级makefile
2:export object 只能传递object这个变量给下级makefile
3:unexport object 不能传递object这个变量给下级makefile
需要注意的是,有两个变量,一个是SHELL,一个是MAKEFLAGS,这两个变量不管你是否export,其总是要传递到下层Makefile中,特别是MAKEFILES变量,其中包含了make的参数信息,如果我们执行“总控Makefile”时有make参数或是在上层Makefile中定义了这个变量,那么MAKEFILES变量将会是这些参数,并会传递到下层Makefile中,这是一个系统级的环境变量。
Makefile使用通配符
make支持三各通配符:“*”,“?”和“[…]”
objects = *.o 这里的objects的值就是 “*.o”
objects := $(wildcard *.o) 而这里的objects的值才是所有的.o文件
Makefile文件搜寻
1:VPATH变量 (先找当前路径)
Makefile文件中的特殊变量“VPATH”就是完成文件搜寻功能的,如果没有指明这个变量,make只会在当前的目录中去找寻依赖文件和目标文件。
VPATH = src:headers 如果定义了这个变量,makefile会先找当前路径,找不到的情况下再去src路径下找,如果还找不到就去headers路径找,这里可以指定很多路径,中间以冒号隔开。
2:使用make的“vpath”关键字,也可以搜索文件。(先找当前路径)
vpath <pattern> <directories> 如:vpath %.h ../headers
为符合模式<pattern>的文件指定搜索目录<directories>。
vpath <pattern> 如:vpath %.h
清除符合模式<pattern>的文件的搜索目录。
vpath
清除所有已被设置好了的文件搜索目录。
注意:gcc在链接.o的时候,如果没有指定.o的路径,只会链接当前路径的.o文件,所以这个时候就算使用了VPATH或vpath找到了.o文件也没用。
Makefile伪目标
伪目标解决两个问题:
1:不会生成目标文件
2:解决和当前路径下文件重名问题
“伪目标”并不是一个文件,只是一个标签,由于“伪目标”不是文件(不会生成目标文件),所以make无法生成它的依赖关系和决定它是否要执行。我们只有通过显示地指明这个“目标”才能让其生效。如果makefile中的目标和文件名重了,比如说你要使用 make clean但是在当前目录有一个名字叫clean的文件,你make clean的时候就会出错,你把clean申明为伪目标,.PHONY : clean,这样才能使用 make clean。
伪目标一般没有依赖的文件。但是,我们也可以为伪目标指定所依赖的文件。伪目标同样可以作为“默认目标”,只要将其放在第一个。比如
all : prog1 prog2 prog3
.PHONY : all
作为默认目标的时候,会生成prog1 prog2 prog3三个文件,但是不会出现all文件(它只是个标签)
Makefile静态模式
<targets ...>: <target-pattern>: <prereq-patterns ...>
<commands>
...
targets定义了一系列的目标文件,可以有通配符。是目标的一个集合。
target-parrtern是指明了targets的模式,也就是的目标集模式。
prereq-parrterns是目标的依赖模式,它对target-parrtern形成的模式再进行一次依赖目标的定义。
还是举个例子来说明一下吧。如果我们的<target-parrtern>定义成“%.o”,意思是我们的<target>集合中都是以“.o”结尾的,而如果我们的<prereq-parrterns>定义成“%.c”,意思是对<target-parrtern>所形成的目标集进行二次定义,其计算方法是,取<target-parrtern>模式中的“%”(也就是去掉了[.o]这个结尾),并为其加上[.c]这个结尾,形成的新集合。
objects = foo.o bar.o
all: $(objects)
$(objects): %.o: %.c
$(CC) -c $(CFLAGS) $< -o $@
等价于:
foo.o : foo.c
$(CC) -c $(CFLAGS) foo.c -o foo.o
bar.o : bar.c
$(CC) -c $(CFLAGS) bar.c -o bar.o
Makefile命令出错
如果我们想忽视某条命令的错误,让程序继续运行下去,只需要在这条命令最开始的时候加上一个“-”,或者把这个目标声明为“.IGNORE”目标。
1:
clean:
-rm -f *.o
2:
.IGNORE :clean
clean:
rm -f *.o
Makefile声明目标为声明为中介目标
中间目标,它和一般的目标有两个地方所不同:第一个不同是除非中间的目标不存在,才会引发中间规则。第二个不同的是,只要目标成功产生,那么,产生最终目标过程中,所产生的中间目标文件会被以“rm -f”删除。使用“.INTERMEDIATE”来声明。
.INTERMEDIATE:test1.o
test1.o:test1.c test.h
cc -c test1.c test.h
Makefile命令执行
当依赖目标新于目标时,也就是当规则的目标需要被更新时,make会一条一条的执行其后的命令。需要注意的是,如果你要让上一条命令的结果应用在下一条命令时,你应该使用分号分隔这两条命令。比如你的第一条命令是cd命令,你希望第二条命令得在cd之后的基础上运行,那么你就不能把这两条命令写在两行上,而应该把这两条命令写在一行上,用分号分隔。
错的:
exec:
cd /home/hchen
pwd
对的:
exec:
cd /home/hchen; pwd
Makefile使用条件判断
语法:
ifeq (<arg1>, <arg2>)
ifeq '<arg1>' '<arg2>'
ifeq "<arg1>" "<arg2>"
ifeq "<arg1>" '<arg2>'
ifeq '<arg1>' "<arg2>"
ifneq (<arg1>, <arg2>)
ifneq '<arg1>' '<arg2>'
ifneq "<arg1>" "<arg2>"
ifneq "<arg1>" '<arg2>'
ifneq '<arg1>' "<arg2>"
举例:
判断$(CC)变量是否“gcc”
1:ifeq ($(CC),gcc)
$(CC) -o foo $(objects) $(libs_for_gcc)
else
$(CC) -o foo $(objects) $(normal_libs)
endif
Makefile使用函数
$(<function> <arguments>)
这里,<function>就是函数名,make支持的函数不多。<arguments>是函数的参数,参数间以逗号“,”分隔,而函数名和参数之间以“空格”分隔。
字符串替换函数:
$(subst <from>,<to>,<text>)
功能:把字串
返回:函数返回被替换过后的字符串。
示例:
$(subst ee,EE,feet on the street),
把“feet on the street”中的“ee”替换成“EE”,返回结果是“fEEt on the strEEt”。
模式字符串替换函数:
$(patsubst <pattern>,<replacement>,<text>)
功能:查找<text>中的单词(单词以“空格”、“Tab”或“回车”“换行”分隔)是否符合模式<pattern>,如果匹配的话,则以<replacement>替换。这里,<pattern>可以包括通配符“%”,表示任意长度的字串。如果<replacement>中也包含“%”,那么,
<replacement>中的这个“%”将是<pattern>中的那个“%”所代表的字串。(可以用“\”来转义,以“%”来表示真实含义的“%”字符)
返回:函数返回被替换过后的字符串。
示例:
$(patsubst %.c,%.o,x.c.c bar.c)
把字串“x.c.c bar.c”符合模式[%.c]的单词替换成[%.o],返回结果是“x.c.o bar.o”
去空格函数:
$(strip <string>)
功能:去掉<string>字串中开头和结尾的空字符(如果字符串中间有两个或以上的空格,那么只留一个空格,多余的去掉)。
返回:返回被去掉空格的字符串值。
示例:
$(strip a b c )
把字串“a b c ”去到开头和结尾的空格,结果是“a b c”。
查找字符串函数:
$(findstring <find>,<in>)
功能:在字串<in>中查找<find>字串。
返回:如果找到,那么返回<find>,否则返回空字符串。
示例:
$(findstring a,a b c)
$(findstring a,b c)
第一个函数返回“a”字符串,第二个返回“”字符串(空字符串)
过滤函数:
$(filter <pattern...>,<text>)
功能:以<pattern>模式过滤<text>字符串中的单词,保留符合模式<pattern>的单词。可以有多个模式。
返回:返回符合模式<pattern>的字串。
示例:
sources := foo.c bar.c baz.s ugh.h
foo: $(sources)
cc $(filter %.c %.s,$(sources)) -o foo
$(filter %.c %.s,$(sources))返回的值是“foo.c bar.c baz.s”。
反过滤函数:
$(filter-out <pattern...>,<text>)
功能:以<pattern>模式过滤<text>字符串中的单词,去除符合模式<pattern>的单词。可以有多个模式。
返回:返回不符合模式的字串。
示例:
objects=main1.o foo.o main2.o bar.o
mains=main1.o main2.o
$(filter-out $(mains),$(objects)) 返回值是“foo.o bar.o”。
排序函数:
$(sort <list>)
功能:给字符串<list>中的单词排序(升序)。
返回:返回排序后的字符串。
示例:$(sort foo bar lose)返回“bar foo lose” 。
备注:sort函数会去掉<list>中相同的单词。
取单词函数:
$(word <n>,<text>)
功能:取字符串<text>中第<n>个单词。(从一开始)
返回:返回字符串<text>中第<n>个单词。如果<n>比<text>中的单词数要大,那么返回空字符串。
示例:$(word 2, foo bar baz)返回值是“bar”。
取单词串函数:
$(wordlist <s>,<e>,<text>)
功能:从字符串<text>中取从<s>开始到<e>的单词串。<s>和<e>是一个数字。
返回:返回字符串<text>中从<s>到<e>的单词字串。如果<s>比<text>中的单词数要大,那么返回空字符串。如果<e>大于<text>的单词数,那么返回从<s>开始,到<text>结束的单词串。
示例: $(wordlist 2, 3, foo bar baz)返回值是“bar baz”。
单词个数统计函数:
$(words <text>)
功能:统计<text>中字符串中的单词个数。
返回:返回<text>中的单词数。
示例:$(words, foo bar baz)返回值是“3”。
备注:如果我们要取<text>中最后的一个单词,我们可以这样:$(word $(words <text>),<text>)。
首单词函数:
$(firstword <text>)
功能:取字符串<text>中的第一个单词。
返回:返回字符串<text>的第一个单词。
示例:$(firstword foo bar)返回值是“foo”。
备注:这个函数可以用word函数来实现:$(word 1,<text>)。、
取目录函数:
$(dir <names...>)
功能:从文件名序列<names>中取出目录部分。目录部分是指最后一个反斜杠(“/”)之前的部分。如果没有反斜杠,那么返回“./”。
返回:返回文件名序列<names>的目录部分。
示例: $(dir src/foo.c hacks)返回值是“src/ ./”。
取文件函数:
$(notdir <names...>)
功能:从文件名序列<names>中取出非目录部分。非目录部分是指最后一个反斜杠(“/”)之后的部分。
返回:返回文件名序列<names>的非目录部分。
示例: $(notdir src/foo.c hacks)返回值是“foo.c hacks”。
取后缀函数:
$(suffix <names...>)
功能:从文件名序列<names>中取出各个文件名的后缀。
返回:返回文件名序列<names>的后缀序列,如果文件没有后缀,则返回空字串。
示例:$(suffix src/foo.c src-1.0/bar.c hacks)返回值是“.c .c”。
取前缀函数:
$(basename <names...>)
功能:从文件名序列<names>中取出各个文件名的前缀部分。
返回:返回文件名序列<names>的前缀序列,如果文件没有前缀,则返回空字串。
示例:$(basename src/foo.c src-1.0/bar.c hacks)返回值是“src/foo src-1.0/bar hacks”。
加后缀函数:
$(addsuffix <suffix>,<names...>)
功能:把后缀<suffix>加到<names>中的每个单词后面。
返回:返回加过后缀的文件名序列。
示例:$(addsuffix .c,foo bar)返回值是“foo.c bar.c”。
加前缀函数:
$(addprefix <prefix>,<names...>)
功能:把前缀<prefix>加到<names>中的每个单词后面。
返回:返回加过前缀的文件名序列。
示例:$(addprefix src/,foo bar)返回值是“src/foo src/bar”。
连接函数:
$(join <list1>,<list2>)
功能:把<list2>中的单词对应地加到<list1>的单词后面。如果<list1>的单词个数要比<list2>的多,那么,<list1>中的多出来的单词将保持原样。如果<list2>的单词个数要比<list1>多,那么,<list2>多出来的单词将被复制到<list2>中。
返回:返回连接过后的字符串。
示例:$(join aaa bbb , 111 222 333)返回值是“aaa111 bbb222 333”。
foreach 函数:
$(foreach <var>,<list>,<text>)
foreach这个函数是用来做循环用的,这个函数的意思是,把参数<list>中的单词逐一取出放到参数<var>所指定的变量中,然后再执行<text>所包含的表达式。每一次<text>会返回一个字符串,循环过程中,<text>的所返回的每个字符串会以空格分隔,最后当整个循环结束时,<text>所返回的每个字符串所组成的整个字符串(以空格分隔)将会是foreach函数的返回值。(注意,foreach中的<var>参数是一个临时的局部变量,foreach函数执行完后,参数<var>的变量将不在作用,其作用域只在foreach函数当中。)
names := a b c d
files := $(foreach n,$(names),$(n).o)
上面的例子中,$(name)中的单词会被挨个取出,并存到变量“n”中,“$(n).o”每次根据“$(n)”计算出一个值,这些值以空格分隔,最后作为foreach函数的返回,所以,$(files)的值是“a.o b.o c.o d.o”。
if 函数:
语法是:
$(if <condition>,<then-part>)
或是
$(if <condition>,<then-part>,<else-part>)
if函数可以包含“else”部分,或是不含。即if函数的参数可以是两个,也可以是三个。<condition>参数是if的表达式,如果其返回的为非空字符串,那么这个表达式就相当于返回真,于是,<then-part>会被计算,否则<else-part>会被计算。
origin函数:
$(origin <variable>)
origin函数不像其它的函数,他并不操作变量的值,他只是告诉你你的这个变量是哪里来的。注意,<variable>是变量的名字,不应该是引用。所以你最好不要在<variable>中使用“$”字符。Origin函数会以其返回值来告诉你这个变量的“出生情况”,下面,是origin函数的返回值:
“undefined”
如果<variable>从来没有定义过,origin函数返回这个值“undefined”。
“default”
如果<variable>是一个默认的定义,比如“CC”这个变量,这种变量我们将在后面讲述。
“environment”
如果<variable>是一个环境变量,并且当Makefile被执行时,“-e”参数没有被打开。
“file”
如果<variable>这个变量被定义在Makefile中。
“command line”
如果<variable>这个变量是被命令行定义的。
“override”
如果<variable>是被override指示符重新定义的。
“automatic”
如果<variable>是一个命令运行中的自动化变量。关于自动化变量将在后面讲述。
ifdef bletch
ifeq "$(origin bletch)" "environment"
bletch = barf, gag, etc.
endif
endif
判断一下,如果变量来源于环境,那么我们就把之重定义了
shell函数:
shell函数也不像其它的函数。顾名思义,它的参数应该就是操作系统Shell的命令
files := $(shell echo *.c)
注意,这个函数会新生成一个Shell程序来执行命令,所以你要注意其运行性能,如果你的Makefile中有一些比较复杂的规则,并大量使用了这个函数,那么对于你的系统性能是有害的
makefile的命令行:
指定Makefile:
make –f hchen.mk
make --file hchen.mk
指定目标:
如果想要指定编译目标,直接make后面跟目标名字,比如 make clean。
有一个make的环境变量叫“MAKECMDGOALS”,这个变量中会存放你所指定的终极目标的列表,如果在命令行上,你没有指定目标,那么,这个变量是空值。如果指定了目标,那么“MAKECMDGOALS”的值就是你这个目标名
主要参数:
不让makefile中的规则执行起来,只是检查一下命令,或是执行的序列。
“-n”
“--just-print”
“--dry-run”
“--recon”
“-t”
“--touch”
相当于UNIX的touch命令,只是把目标的修改日期变成最新的,也就是阻止生成目标的命令运行。
“-q”
“--question”
不运行命令,也不输出。仅仅是检查所指定的目标是否需要更新。如果是0则说明要更新,如果是2则说明有错误发生。
这个参数的行为是找目标的意思,也就是说,如果目标存在,那么其什么也不会输出,当然也不会执行编译,如果目标不存在,其会打印出一条出错信息。
“-W <file>”
“--what-if=<file>”
“--assume-new=<file>”
“--new-file=<file>”
“-b”
“-m”
这两个参数的作用是忽略和其它版本make的兼容性。
“-B”
“--always-make”
认为所有的目标都需要更新(重编译)。
“-C <dir>”
“--directory=<dir>”
指定读取makefile的目录。如果有多个“-C”参数,make的解释是后面的路径以前面的作为相对路径,并以最后的目录作为被指定目录。如:“make –C ~hchen/test –C prog”等价于“make –C ~hchen/test/prog”。
“—debug[=<options>]”
输出make的调试信息。它有几种不同的级别可供选择,如果没有参数,那就是输出最简单的调试信息。下面是<options>的取值:
a —— 也就是all,输出所有的调试信息。(会非常的多)
b —— 也就是basic,只输出简单的调试信息。即输出不需要重编译的目标。
v —— 也就是verbose,在b选项的级别之上。输出的信息包括哪个makefile被解析,不需要被重编译的依赖文件(或是依赖目标)等。
i —— 也就是implicit,输出所以的隐含规则。
j —— 也就是jobs,输出执行规则中命令的详细信息,如命令的PID、返回码等。
m —— 也就是makefile,输出make读取makefile,更新makefile,执行makefile的信息。
“-d”
相当于“--debug=a”。
“-e”
“--environment-overrides”
指明环境变量的值覆盖makefile中定义的变量的值。
“-f=<file>”
“--file=<file>”
“--makefile=<file>”
指定需要执行的makefile。
“-h”
“--help”
显示帮助信息。
“-i”
“--ignore-errors”
在执行时忽略所有的错误。
“-I <dir>”
“--include-dir=<dir>”
指定一个被包含makefile的搜索目标。可以使用多个“-I”参数来指定多个目录。
“-j [<jobsnum>]”
“--jobs[=<jobsnum>]”
指同时运行命令的个数。如果没有这个参数,make运行命令时能运行多少就运行多少。如果有一个以上的“-j”参数,那么仅最后一个“-j”才是有效的。(注意这个参数在MS-DOS中是无用的)
“-k”
“--keep-going”
出错也不停止运行。如果生成一个目标失败了,那么依赖于其上的目标就不会被执行了。
“-l <load>”
“--load-average[=<load]”
“—max-load[=<load>]”
指定make运行命令的负载。
“-n”
“--just-print”
“--dry-run”
“--recon”
仅输出执行过程中的命令序列,但并不执行。
“-o <file>”
“--old-file=<file>”
“--assume-old=<file>”
不重新生成的指定的<file>,即使这个目标的依赖文件新于它。
“-p”
“--print-data-base”
输出makefile中的所有数据,包括所有的规则和变量。这个参数会让一个简单的makefile都会输出一堆信息。如果你只是想输出信息而不想执行makefile,你可以使用“make -qp”命令。如果你想查看执行makefile前的预设变量和规则,你可以使用“make –p –f /dev/null”。这个参数输出的信息会包含着你的makefile文件的文件名和行号,所以,用这个参数来调试你的makefile会是很有用的,特别是当你的环境变量很复杂的时候。
“-r”
“--no-builtin-rules”
禁止make使用任何隐含规则。
“-R”
“--no-builtin-variabes”
禁止make使用任何作用于变量上的隐含规则。
“-s”
“--silent”
“--quiet”
在命令运行时不输出命令的输出
“-S”
“--no-keep-going”
“--stop”
取消“-k”选项的作用。因为有些时候,make的选项是从环境变量“MAKEFLAGS”中继承下来的。所以你可以在命令行中使用这个参数来让环境变量中的“-k”选项失效。
“-v”
“--version”
输出make程序的版本、版权等关于make的信息。
“-w”
“--print-directory”
输出运行makefile之前和之后的信息。这个参数对于跟踪嵌套式调用make时很有用。
“--no-print-directory”
禁止“-w”选项。
“-W <file>”
“--what-if=<file>”
“--new-file=<file>”
“--assume-file=<file>”
假定目标<file>需要更新,如果和“-n”选项使用,那么这个参数会输出该目标更新时的运行动作。如果没有“-n”那么就像运行UNIX的“touch”命令一样,使得<file>的修改时间为当前时间。
makefile的一些命令的变量:
AR
函数库打包程序。默认命令是“ar”。
AS
汇编语言编译程序。默认命令是“as”。
CC
C语言编译程序。默认命令是“cc”。
CXX
C++语言编译程序。默认命令是“g++”。
CO
从 RCS文件中扩展文件程序。默认命令是“co”。
CPP
C程序的预处理器(输出是标准输出设备)。默认命令是“$(CC) –E”。
FC
Fortran 和 Ratfor 的编译器和预处理程序。默认命令是“f77”。
GET
从SCCS文件中扩展文件的程序。默认命令是“get”。
LEX
Lex方法分析器程序(针对于C或Ratfor)。默认命令是“lex”。
PC
Pascal语言编译程序。默认命令是“pc”。
YACC
Yacc文法分析器(针对于C程序)。默认命令是“yacc”。
YACCR
Yacc文法分析器(针对于Ratfor程序)。默认命令是“yacc –r”。
MAKEINFO
转换Texinfo源文件(.texi)到Info文件程序。默认命令是“makeinfo”。
TEX
从TeX源文件创建TeX DVI文件的程序。默认命令是“tex”。
TEXI2DVI
从Texinfo源文件创建军TeX DVI 文件的程序。默认命令是“texi2dvi”。
WEAVE
转换Web到TeX的程序。默认命令是“weave”。
CWEAVE
转换C Web 到 TeX的程序。默认命令是“cweave”。
TANGLE
转换Web到Pascal语言的程序。默认命令是“tangle”。
CTANGLE
转换C Web 到 C。默认命令是“ctangle”。
RM
删除文件命令。默认命令是“rm –f”。
ARFLAGS
函数库打包程序AR命令的参数。默认值是“rv”。
ASFLAGS
汇编语言编译器参数。(当明显地调用“.s”或“.S”文件时)。
CFLAGS
C语言编译器参数。
CXXFLAGS
C++语言编译器参数。
COFLAGS
RCS命令参数。
CPPFLAGS
C预处理器参数。( C 和 Fortran 编译器也会用到)。
FFLAGS
Fortran语言编译器参数。
GFLAGS
SCCS “get”程序参数。
LDFLAGS
链接器参数。(如:“ld”)
LFLAGS
Lex文法分析器参数。
PFLAGS
Pascal语言编译器参数。
RFLAGS
Ratfor 程序的Fortran 编译器参数。
YFLAGS
Yacc文法分析器参数。
makefile的自动化变量:
$@
表示规则中的目标文件集。在模式规则中,如果有多个目标,那么,“$@”就是匹配于目标中模式定义的集合。
$%
仅当目标是函数库文件中,表示规则中的目标成员名。例如,如果一个目标是“foo.a(bar.o)”,那么,“$%”就是“bar.o”,“$@”就是“foo.a”。如果目标不是函数库文件(Unix下是[.a],Windows下是[.lib]),那么,其值为空。
$<
依赖目标中的第一个目标名字。如果依赖目标是以模式(即“%”)定义的,那么“$<”将是符合模式的一系列的文件集。注意,其是一个一个取出来的。
$?
所有比目标新的依赖目标的集合。以空格分隔。
$^
所有的依赖目标的集合。以空格分隔。如果在依赖目标中有多个重复的,那个这个变量会去除重复的依赖目标,只保留一份。
$+
这个变量很像“$^”,也是所有依赖目标的集合。只是它不去除重复的依赖目标。
$*
这个变量表示目标模式中“%”及其之前的部分。如果目标是“dir/a.foo.b”,并且目标的模式是“a.%.b”,那么,“$”的值就是“dir/a.foo”。这个变量对于构造有关联的文件名是比较有较。如果目标中没有模式的定义,那么“$”也就不能被推导出,但是,如果目标文件的后缀是make所识别的,那么“$”就是除了后缀的那一部分。例如:如果目标是“foo.c”,因为“.c”是make所能识别的后缀名,所以,“$”的值就是“foo”。这个特性是GNU make的,很有可能不兼容于其它版本的make,所以,你应该尽量避免使用“$”,除非是在隐含规则或是静态模式中。如果目标中的后缀是make所不能识别的,那么“$”就是空值。
$(@D)
表示“$@”的目录部分(不以斜杠作为结尾),如果“$@”值是“dir/foo.o”,那么“$(@D)”就是“dir”,而如果“$@”中没有包含斜杠的话,其值就是“.”(当前目录)。
$(@F)
表示“$@”的文件部分,如果“$@”值是“dir/foo.o”,那么“$(@F)”就是“foo.o”,“$(@F)”相当于函数“$(notdir $@)”。
$(*D)
$(*F)
和上面所述的同理,也是取文件的目录部分和文件部分。对于上面的那个例子,“$(*D)”返回“dir”,而“$(*F)”返回“foo”
$(%D)
$(%F)
分别表示了函数包文件成员的目录部分和文件部分。这对于形同“archive(member)”形式的目标中的“member”中包含了不同的目录很有用。
$(<D)
$(<F)
分别表示依赖文件的目录部分和文件部分。
$(^D)
$(^F)
分别表示所有依赖文件的目录部分和文件部分。(无相同的)
$(+D)
$(+F)
分别表示所有依赖文件的目录部分和文件部分。(可以有相同的)
$(?D)
$(?F)
分别表示被更新的依赖文件的目录部分和文件部分。
makefile的传递变量:
make HOST_CFLAGS=-I
HOST_CFLAGS变量将会替换相应Makefile中的HOST_CFLAGS,也就是Makefile中的HOST_CFLAGS将被覆盖掉
参考链接