一、执行make程序
make的退出状态:
0 --- 表示执行成功
1 --- 表示执行make时使用了“-q”参数,而且当前工程中存在过时的目标文件
2 --- 执行过程中出现了错误,同时会提示错误信息
1 指定makefile文件
执行make时,使用选项“-f”“--file”“--makefile”选项来指定所要执行的makefile文件。例如:“make –f altmake”
当在make的命令行选项中出现多个“-f”参数时,所有通过“-f”指定的文件都将被作为make解析执行的makefile文件。
默认情况下,如果没有使用“-f”“--file”“--makefile”指定文件,则make会在当前工作目录中依次搜索名为“GNUmakefile”“makefile”“Makefile”的文件。
2 指定终极目标
默认情况下,终极目标就是makefile中,除了以“.”开始的第一个规则中的第一个目标。但是也可以指定具体执行哪个目标,格式为:“make TARGET_NAME”。
make在执行时设置了一个特殊变量“MAKECMDGOALS”,记录了命令行参数指定的终极目标列表,没有通过命令行参数指定终极目标时,此变量为空。注:此变量仅用于特殊场合,在makefile中不要对它进行重新定义。
部分约定的伪目标和空目标命令如下:
all |
makefile的顶层目标,一般此目标作为默认的终极目标 |
clean |
删除所有由make创建的文件 |
mostlyclean |
类似于clean |
distclean |
... |
realclean |
... |
clobber |
... |
install |
将make成功创建的可执行文件拷贝到shell环境变量“PATH”指定的某个目录中。典型地,可执行文件被拷贝到“/usr/local/bin”,库文件被拷贝到“/usr/local/lib” |
|
打印出所有被更改的源文件列表 |
tar |
创建一个tar文件 |
shar |
创建一个源代码的shell文档 |
dist |
创建源文件发布的压缩包 |
TAGS |
创建当前目录下的所有源文件的符号信息文件,该文件可以被vim使用 |
check |
检查make最终生成的文件 |
test |
... |
3 替代命令的执行
所谓的替代,就是替代make默认动作的执行,包括:
-n --just-print --dry-run --recon |
只打印出重建过期目标所需执行的命进行重建令,而并不对目标 |
-t --touch |
更新所有目标文件的时间戳,并不更新内容 |
-q --question |
不执行任何命令,并且不打印任何输出信息,只检查所指定的目标是否已经是最新的。如果最新,返回0;否则,返回1。根据其返回值来判断是否需要执行目标更新的操作 |
-W FILE --what-if=FILE --assume-new=FILE --new-file=FILE |
将当前系统时间作为指定文件FILE的时间戳。更改文件的时间戳后,执行make时,由于依赖文件的时间戳已更新,因此目标将会被重建。通过这种方式并结合“-n”,可以在修改一个文件后检查本次修改操作会造成哪些目标需要被更新,但并不执行更新的命令,只是打印命令; 与“-t”结合,make将忽略其他规则的命令,只对依赖于“-W”指定文件的目标执行“touch”命令,在没有使用“-s”时,可以看到哪些文件执行了“touch”。 与“-q”结合,由于将当前时间作为指定文件的时间戳,而目标文件相对于系统当前时间是过时的,因此make的返回状态在没有错误发生时为1,存在错误时为2 |
4 防止特定文件重建
有时修改工程中的某一个文件,并不希望重建那些依赖于这个文件的目标,比如说我们在一个头文件中加入了一个宏定义、或者增加一个函数声明,这些修改不会对已经编译完成的程序产生任何的影响,此时,不需要进行重建操作。为了避免重新编译整个工程,可以如下处理:
1> 使用make对特定目标进行重建操作
2> 使用“make –o HEADERFILE”可以避免依赖于头文件HEADERFILE的目标被重建。可以使用多个“-o HEADERFILE”指定多个这样的头文件。但是注意:“-o”的这种用法仅限于.h头文件。
3> 使用“make -t”命令来改变已存在的所有目标文件的时间戳,将其时间修改到系统当前时间。
5 替换变量定义
执行make时,命令行参数的格式为“V=X”,表示定义变量V,值为X,并用这个变量替换makefile中的同名变量。通常用这种方式传递一个公共变量给make。例如,使用“CFLAGS”指定编译参数:
cc –c $(CFLAGS) foo.c
这样就可以通过改变“CFLAGS”的值来控制编译选项。我们可以在makefile中为它指定值,如:
CFLAGS = -g,如此编译语句变为:cc –c –g foo.c
为了防止命令行参数的定义覆盖makefile中的同名定义,可以在makefile中使用指示符“override”声明这个变量。
6 make的命令行选项
-b |
忽略,提供其它版本make的兼容性 |
||||||||||||
-m |
... |
||||||||||||
-B |
强制重建所有规则的目标 |
||||||||||||
--always-make |
... |
||||||||||||
-C DIR |
将工作目录切换到“DIR”之后执行make;如果存在多个“-C”选项,那么make的最终工作目录是第一个指定的目录。 |
||||||||||||
--directory=DIR |
... |
||||||||||||
-d |
make执行过程中打印出所有的调试信息,包括make构造依赖关系链、重建目标过程的所有信息,等价于“—debug = a” |
||||||||||||
--debug[=OPTIONS] |
make执行过程中打印出调试信息,使用“OPTIONS”控制调试信息级别,默认是“OPTIONS = b”,其可选值如下所示:
|
||||||||||||
-e |
使用系统环境变量覆盖makefile中同名的环境变量 |
||||||||||||
--environment-overrides |
... |
||||||||||||
-f=FILE |
执行make执行的makefile文件FILE |
||||||||||||
--file=FILE |
... |
||||||||||||
--makefile=FILE |
... |
||||||||||||
-h |
打印帮助信息 |
||||||||||||
--help |
... |
||||||||||||
-i |
执行过程中忽略规则命令执行的错误 |
||||||||||||
--ignore-errors |
... |
||||||||||||
-I DIR |
指定被包含makefile文件的搜索目录 |
||||||||||||
--include-dir=DIR |
... |
||||||||||||
-j [JOBS] |
指定可同时执行的命令数目 |
||||||||||||
--jobs[=JOBS] |
... |
||||||||||||
-k |
执行规则命令出现错误时不终止make的执行,make将尽最大可能地执行所有的命令,直到出现致命错误才终止 |
||||||||||||
--keep-going |
... |
||||||||||||
-I LOAD |
如果系统负荷超过“LOAD指定的浮点数”,那么make将不再启动新的任务 |
||||||||||||
--load-average[=LOAD] |
... |
||||||||||||
--max-load[=LOAD] |
... |
||||||||||||
-n |
只打印出所要执行的命令,而不真正执行 |
||||||||||||
--just-print |
... |
||||||||||||
--dry-run |
... |
||||||||||||
--recon |
... |
||||||||||||
-o FILE |
指定“FILE”文件不需要被重建,同时依赖“FILE”的目标也不需要重建 |
||||||||||||
--old-file=FILE |
... |
||||||||||||
--assume-old=FILE |
... |
||||||||||||
-p |
执行make命令前,打印出make读取的所有makefile的数据,同时打印出make的版本信息。如果只是需要打印这些信息而不执行命令,可以使用“make -qp”;查看make执行前的预设规则和变量,可以使用“make –p –f /dev/null” |
||||||||||||
--print-data-base |
... |
||||||||||||
-q |
不执行任何命令,也无任何输出。make只是返回一个查询状态,0表示没有目标需要重建;1表示存在需要重建的目标;2表示发生错误 |
||||||||||||
--question |
... |
||||||||||||
-r |
取消所有内嵌的隐含规则,但不取消make内嵌的隐含变量 |
||||||||||||
--no-builtin-rules |
... |
||||||||||||
-R |
取消所有内嵌的隐含变量,同时取消所有内嵌的隐含规则,因此默认会打开“-r”选项 |
||||||||||||
--no-builtin-variables |
... |
||||||||||||
-s |
取消命令执行过程的打印 |
||||||||||||
--silent |
... |
||||||||||||
--quiet |
... |
||||||||||||
-S |
取消“-k”选项。在递归的make过程中,子make通过“MAKEFLAGS”变量继承上层的命令行选项,使用“-S”选项会取消上层传递的“-k” |
||||||||||||
--no-keep-going |
... |
||||||||||||
--stop |
... |
||||||||||||
-t |
更新所有目标文件的时间戳为当前系统时间,防止make对所有过期目标文件的重建 |
||||||||||||
--touch |
... |
||||||||||||
-v |
查看make版本信息 |
||||||||||||
--version |
... |
||||||||||||
-w |
在make进入一个目录读取makefile之前打印出工作目录信息 |
||||||||||||
--print-directory |
... |
||||||||||||
--no-print-directory |
取消“-w”选项 |
||||||||||||
-W FILE |
设定“FILE”文件的时间戳为系统当前时间,但是并不改变该文件实际的最后修改时间,主要是为了实现对所有依赖于文件“FILE”的目标的强制重建 |
||||||||||||
--what-if=FILE |
... |
||||||||||||
--new-file=FILE |
... |
||||||||||||
--assume-file=FILE |
... |
||||||||||||
--warn-undefined-variables |
使用makefile中没有定义的变量时给出警告信息 |
二、makefile相关函数
1 函数的调用
格式:
$(FUNCTION ARGUMENTS)
或者
${FUNCTION ARGUMENTS}
FUNCTION为调用的内部函数名【用户自定义的函数需要通过call来调用】;ARGUMENTS为函数的参数,多个参数之间不能以逗号“,”或者空格作为分隔符,这是因为“,”已被作为多个参数的分隔符,而前置空格会被忽略掉。如果需要在函数参数中使用“,”或者空格作为分隔符,必须先将其赋给一个变量,然后再使用变量来分割,如下:
comma := ,
empty :=
space := $(empty) $(empty)
foo := a b c
bar := $(subst $(space), $(comma), $(foo))
表示bar := a,b,c
2 文本处理函数
2.1 $(subst, FROM, TO, TEXT)
函数名:subst --- 字符串替换
函数功能:将字符串“TEXT”中的“FROM”替换为“TO”。
返回值:替换后的字符串
实例:
$(subst, ee, EE, feet on the street)
返回字符串:“fEEt on the strEEt”
2.2 $(patsubst PATTERN, REPLACEMENT, TEXT)
函数名:patsubst --- 模式替换
函数功能:在“TEXT”中搜索以空格分割的单词,将符合模式“PATTERN”的部分替换为“REPLACEMENT”。在“PATTERN”和“REPLACEMENT”中,只有第一个出现的%会被作为模式字符来处理,之后出现的%只作为一个普通字符;如果参数中需要将第一个出现的%也当作普通字符处理,只需要使用“\”进行转义即可。
返回值:替换后的字符串
实例:
$(patsubst %.c, %.o, x.c.c bar.c)
返回字符串:x.c.o bar.o
2.3 $(strip STRINT)
函数名:strip --- 去除空格
函数功能:去除字符串开头和结尾的空格;合并字符串之间的多个空格为一个空格
返回值:去除多余空格后的字符串
实例:
STR = A B C
LOSTR = $(strip $(STR))
返回字符串:“A B C”
2.4 $(findstring FIND, IN)
函数名:findstring --- 查找字符串
函数功能:在字符串“IN”中查找“FIND”。
返回值:若找到则返回“FIND”,否则返回空。
实例:
$(findstring a, a b c)
返回字符串:“a”
2.5 $(filter PATTERN, TEXT)
函数名:filter --- 过滤函数
函数功能:过滤掉“TEXT”中所有不符合模式“PATTERN”的单词;若有多个“PATTERN”,则以空格隔开。
返回值:“TEXT”中与“PATTERN”匹配的字符串。
实例:
sources := foo.c bar.c baz.s ugh.h
foo : $(sources)
cc $(filter %.c %s, $(sources)) –o foo
2.6 $(filter-out PATTERN, TEXT)
函数名:filter-out --- 反过滤函数
函数功能:与filter的功能刚好相反。
2.7 $(sort LIST)
函数名:sort --- 排序
函数功能:对LIST中的单词以首字母进行排序,同时去掉重复的单词
返回值:排好序的字符串
实例:
$(sort foo bar lose foo)
返回字符串:“bar foo lose”
2.8 $(word N, TEXT)
函数名:word --- 取单词
函数功能:返回“TEXT”中的第N个单词,N从1开始计数。
返回值:第N个单词或者空。
实例:
$(word 2, foo bar baz)
返回字符串:“bar”
2.9 $(wordlist S, E, TEXT)
函数名:wordlist --- 取子串
函数功能:返回“TEXT”中第S个~第E个单词组成的子串。
返回值:第S~E个单词或者返回空。
实例:
$(wordlist 2, 3, foo bar baz)
返回字符串:“bar baz”
2.10 $(words TEXT)
函数名:words --- 统计单词个数
函数功能:计算“TEXT”中的单词个数
返回值:单词个数
实例:
$(words, foo bar)
返回值:2
2.11 $(firstword NAMES)
函数名:firstword --- 取首单词
函数功能:返回“NAMES”中的第一个单词
返回值:第一个单词
实例:
$(firstword foo bar baz)
返回字符串:“foo”
3 文件名处理函数
3.1 $(dir NAMES)
函数名:dir --- 取目录
函数功能:从文件名列表“NAMES”中取出各个文件名的目录部分,就是包含在文件名中的最后一个斜线\之前的部分。
返回值:返回目录部分列表。如果文件名中没有目录部分,那么认为当前文件的目录为“./”。
实例:
$(dir src/foo.c hacks)
返回字符串:“src. ./”
3.2 $(notdir NAMES)
函数名:notdir --- 取文件名
函数功能:从文件名列表“NAMES”中取出各个文件的文件名部分,就是包含在文件名中的最后一个斜线\之后的部分。
返回值:文件名列表。
实例:
$(notdir src/foo.c hacks)
返回字符串为:“foo.c hacks”
3.3 $(suffix NAMES)
函数名:suffix --- 取后缀
函数功能:从“NAMES”列表中取出各个文件名的后缀,就是文件名中最后一个“.”之后的部分。
返回值:文件后缀列表。如果文件名没有后缀,则返回空。
实例:
$(suffix src/foo.c src-1.0/bar.c hacks)
返回字符串:“.c .c”
3.4 $(basename NAMES)
函数名:basename --- 取前缀
函数功能:从“NAMES”序列中取出各个文件名的前缀部分,指的是文件名中最后一个点号“.”之前的部分。
返回值:前缀序列或空字符串。
实例:
$(basename src/foo.c src-1.0/bar.c /home/jack/.font.cache-1 hacks)
返回字符串:“src/foo src-1.0/bar /home/jack/.font hacks”
3.5 $(addsuffix SUFFIX, NAMES)
函数名:addsuffix --- 加后缀
函数功能:为“NAMES”列表中的每个文件加上后缀“SUFFIX”。
返回值:加上后缀的文件名列表。
实例:
$(addsuffix .c, foo bar)
返回字符串:“foo.c bar.c”
3.6 $(addprefix PREFIX, NAMES)
函数名:addprefix --- 加前缀
函数功能:为“NAMES”列表中的每个文件加上前缀“PREFIX”。
返回值:加上前缀的文件名列表。
实例:
$(addprefix src/, foo bar)
返回字符串:“src/foo src/bar”
3.7 $(join LIST1, LIST2)
函数名:join --- 对应单词拼接
函数功能:将字符串LIST2中的第一个单词拼接到字符串LIST1中第一个单词之后合并为一个单词;将字符串LIST2中的第二个单词拼接到字符串LIST1中第二个单词之后合并为一个单词;...,依次类推。
返回值:拼接后的字符串。如果LIST1中和LIST2中的数目不同,则二者中多余的部分也将被返回。
实例:
$(join a b, .c .o)
返回字符串:“a.c b.o”
3.8 $(wildcard PATTERN)
函数名:wildcard --- 获取符合某个模式的文件名
函数功能:列出当前目录下所有符合模式“PATTERN”格式的文件名。
返回值:返回当前目录下所有符合模式“PATTERN”的文件名。
实例:
$(wildcard *.c)
返回字符串:“当前目录下所有.c文件的列表”
4 其他函数
4.1 foreach函数
格式:$(foreach VAR, LIST, TEXT)
函数功能:执行时,将“LIST”列表中使用空格分隔的单词依次取出赋值给变量“VAR”,然后执行“TEXT”表达式。重复直到“LIST”中的最后一个单词为止。“TEXT”中的变量或函数引用在执行时才被展开,因此如果在“TEXT”中存在对“VAR”的引用,那么“VAR”的值在每一次展开时将会得到不同的值。
返回值:以空格分隔的多次表达式“TEXT”的计算结果。
实例:
dirs := a b c d
files := $(foreach dir, $(dirs), $(wildcard $(dir)/*))
a b c d是四个目录,展开过程依次如下:
第一次:“$(wildcard a/*)”
第二次:“$(wildcard b/*)”
第三次:“$(wildcard c/*)”
...
此函数所实现的功能等价于如下语句:
files := $(wildcard a/* b/* c/* d/*)
注:此函中的“VAR”是一个临时变量,其在“foreach”函数的上下文中有效,它的定义不会影响其他部分定义的同名“VAR”变量的值,在函数的执行过程中是一个“直接展开”式的变量。
# 列出上级目录中的文件名和目录名
dirs := ..
files := $(foreach dir, $(dirs), $(wildcard $(dir)/*)) demo2 :
@echo $(notdir $(files))
4.2 if函数
格式:$(if CONDITION, THEN-PART[, ELSE-PART])
函数功能:如果“CONDITION”非空,就将“THEN-PART”作为函数的计算表达式;如果“CONDITION”为空,就将“ELSE-PART”作为函数的计算表达式。
4.3 call函数
格式:$(call VARIABLE, PARAMS)
函数功能:使用call可以实现对用户自定义函数的引用。我们可以将一个变量定义为一个复杂的表达式,用“call”函数根据不同的参数对它进行展开来获得不同的结果。在执行时,将参数"PARAMS"中的变量值依次赋值给临时变量"$(1)"、"$(2)"、"$(3)",执行时,变量VARIABLE被展开为在函数上下文中有效的临时变量,变量中定义的"$(1)"作为其第一个参数,依次类推。变量"$(0)"代表"VARIABLE"本身。之后,计算变量“VARIABLE”定义的表达式。
注:"VARIABLE"不能定义为直接展开式,只能定义为递归展开式。
实例:
reverse = $(2) $(1)
foo = $(call reverse, a, b)
变量“foo”的值为“ba”。
4.4 value函数
格式:
$(value VARIABLE)
函数功能:不对变量“VARIABLE”进行任何展开操作,直接返回变量“VARIABLE”的值。这里的“VARIABLE”是一个变量名,一般不包含“$”。
返回值:变量“VARIABLE”所定义的文本值。
4.5 eval函数
eval函数用于在makefile中构建一个可变的规则结构关系。eval函数执行时会对它的参数进行两次展开。第一次展开过程由函数本身完成;第二次展开过程是在make解析时完成。
4.6 origin函数
函数功能:origin用于获取变量的定义类型:"$(origin VARIABLE)","VARIABLE"通常是一个变量名而不是一个引用,因此一般不包含"$"。
返回值:“VARIABLE”的定义类型,主要包括如下几种:
undefined |
无定义 |
default |
内部变量,比如“CC”“MAKE”“RM”等 |
environment |
系统环境变量,并且make没有使用命令行选项“-e” |
environment override |
系统环境变量,并且make使用了命令行选项“-e”,即使用环境变量的值替换makefile中定义的同名变量值 |
file |
makefile文件中定义的变量 |
command line |
命令行变量 |
override |
使用override声明的在makefile中定义的变量 |
automatic |
自动化变量 |
4.7 shell函数
传入一个shell命令,返回shell的执行结果。如:
contents := $(shell cat foo)
将变量文件foo的内容赋值给变量contents,文件中的换行符在变量中使用空格代替。
demo2 :
contents := $(shell cat ../install.log.syslog)
@echo $(contents)
5 控制函数
控制函数用于在make执行过程中检测到错误时,为用户提供消息,并且控制make过程是否继续。
5.1 $(error TEXT)
函数功能:产生致命错误,提示用户“TEXT”,并退出make的执行。需要说明的是:error函数一般不出现在直接展开式的变量定义中,否则在make读取makefile时将会提示致命错误并退出。
返回值:空。
实例:如下...
5.2 $(warning TEXT)
函数功能:只提示用户“TEXT”信息,而不会退出make。
返回值:空
实例:如下...
foo = control function demo2 :
ifdef foo
$(error error : $(foo))
else
$(warning : $(foo))
endif # makefile:5: *** error : control function. Stop.
foo = control function demo2 :
ifndef foo
$(error error : $(foo))
else
$(warning : $(foo))
endif # makefile:7: : control function
# make: `demo2' is up to date.