Makefile函数
内置函数
所有的函数具有如下的形式:
$(function-name arg1[, argn])
1.call
$(call macro-name[, param1 ...])
call
是一个内置于make
的函数,call
会扩展它的第一个参数并把其余参数依次替换到出现$1
$2
…的地方。macro-name
可以是任意的宏或者变量。
2.filter filter-out
$(filter pattern ...,text)
$(filter-out pattern...,text)
filter
函数会将text
视为一系列被空格隔开的单词,与pattern
比较之后,接着会返回相符者。filter
可以接受多个(被空格隔开的)格式。格式必须是整个单词,才可以将相符的单词放到输出列表中。
模式中只可以包含一个%字符。如果模式中包含了额外的%字符,那么除了第一个字符都会被视为文字字符(literal character)。
filter-out
函数与filter刚好相反,用来选出与模式不相符的每个单词。
3.findstring
usage:`$(findstring string...,text)`
此函数将会在text
里搜索string
。如果该字符串被找到了,此函数就会返回string
;否则,他会返回空值。
注意:此函数返回的只是“搜索字符串”,而不是它所要找到的包含该字符串的单词。其次,“搜索字符串”无法包含通配符。
4.subst patsubst
$(subst search-string,replace-string,text)
$(patsubst search-pattern,replace-pattern,text)
引用替换:$(variable:serach=replace)
subst
是一个不具有通配符能力的搜索与替换函数。常被用来在文件名列表中将一个扩展名替换成另一个扩展名。
patsubst
具有通配符能力。照例,此处的模式只可以包含一个%字符。切记,search-pattern
必须与text
的整个值进行匹配。
引用替换可移植。其中search
可以是一个简单的字符串,如果是这样的话,只要该字符串出现在一个单词的末尾,就会被替换成replace
。此外,search
可以包含一个代表统配字符%,如果是这样的话,make
会依照patsub
的规则进行搜索和替换的操作。
5.words word firstword wordlist
$(words text)
$(word n,text)
$(firstword text)
$(wordlist start,end,text)
说明:words
返回text
中单词的数量
word
返回text
中的地n
各单词,第一个单词的编号是1.如果n
大于text
中单词个数,则返回空。
firstword
返回text
中的第一个单词。等效于$(word 1,text)
。
wordlist
返回text
中范围从start
(含)到end
(含)的单词。编号规则同word
。
6.sort
$(sort list)
sort
函数会排序它的list
参数并且移除重复的项目。按照字典顺序排序,以空格分割,删除前导以及结尾的空格。
6.shell
$(shell command)
shell
函数的参数会被扩展(就像所有其他的参数)并且传递给subshell来执行。然后make
会读取command
的标准输出,并将之返回成函数的值。输出中所出现的一系列换行符会被缩减成单一空格号,任何接在后面的换行符号都会被删除。标准错误以及任何程序的结束状态都不会被返回。
文件名函数
1.wildcard
$(wildcard pattern...)
说明:wildcard
函数的参数是一份模式列表,他会对列表中的每个模式进行扩展的动作。如果被扩展的模式找不到相符的文件,则会返回空字符串。
2.dir nodir
$(dir list...)
$(notdir name...)
dir
函数会返回list
中每个单词的目录部分。下面的用户函数会返回包含C源文件的每个子目录:
source-dirs:=$(sort $(dir $(shell find . -name '*.c')))
notdir
函数会返回文件路径的文件名部分。下面的用户函数会从一个Java源文件返回Java的类名:
get-java-class-name=$(notdir $(subst .java,,$1))
3.suffix basename addsuffix addprefix join
$(suffix name...)
$(basename name...)
$(addsuffix
suffix,name
...)
$(addprefix
prefix,name
...)
$(join
prefix-list,suffix-list)
join
是dir
和notdir
的反函数。它会把两个列表的对应元素连接在一起。可以用来重建被dir
和notdir
分解的列表。
3.流程控制
1.if
$(if
condition,then-part,else-part)
if
函数会根据条件表达式的求值结果,从两个宏中选择一个进行扩展。如果condition
扩展之后包含任何字符(即使是空格),那么它的求值结果为真,于是会对then-part
惊醒扩展的动作;否则,如果condition
扩展之后空无一物,那么它的求值结果为假,于是会对else-part
进行扩展的动作。
2.error
$(error
text)
error
函数用来输出错误信息。在此函数输出信息之后make
会以2这个结束状态终止运行。输出中包含当前makefile
的名称、当前的行号以及消息正文。下面实现assert
编程结构:
# $(call assert,condition,message)
define assert
$(if $1,,$(error Assertion failed: $2))
endef
# $(call assert-file-exists,wildcard-pattern)
define assert-file-exists
$(call assert,$(wildcard $1),$1 dose not exist)
endef
# $(call assert-not-null,make-variable)
define assert-not-null
$(call assert,$($1),The variable "$1" is null)
endef
error-exit:
$(call assert-not-null,NON_EXISTENT)
3.foreach
$(foreach
variable,list,body)
这个函数可以让你在反复扩展文本的时候,将不同的值替换进去。(这和你使用不同的参数反复执行函数的状况是不一样的,尽管结果一样)。例如:
letters:=$(foreach letter,a b c d,$(letter))
show-words:
#letters has $(words $(letters)) words: '$letters)'
$ make
# letters has 4 words: 'a b c d'
较不重要的杂项函数
1.strip
$(strip
text)
strip
函数将会从text
中移除所有的前导和接在后面的空格,并以单一空格来替换内部所有空格。此函数常用来清理条件表达式中所使用的变量。
2.origin
$(origin
variable)
origin
函数将会返回描述变量来自何处的字符串。这个变量可以协助你决定如何使用一个变量的值。比如,如果一个变量来自环境,或许你想要忽略该变量的值;如果该变量来自命令行,你就不会这么做。
# $(call asert-defined,variable-name)
define assert-define
$(call assert, \
$(filter-out undefined,$(origin $1)), \
'$1' is undefined)
endef
origin
的返回值包括:
undefined: 变量尚未定义
default: 变量的定义来自make的内置数据库。如果你改变了内置变量的值,origin所返回的是最近一次的定义来自何处
environment:变量的定义来自环境(未使用–environment-overrides)
environment override:变量的定义来自环境(使用了–environment-overrides)
file:变量的定义来自makefile
command line:变量的定义来自命令行
override:变量的命令来自override指令
automatic:这个变量是make所定义的自动变量
3.warnig
$(warning
text)
warning
函数与error
类似,不过warning
不会导致make
结束运行。其他特点相同。
$(if $(wildcard $(JAVAC)),,\
$(warning The java compiler variable,JAVAC ($(JAVAC)),\
is not properly set.))
高级的用户自定义函数
call
函数将会把它的每个参数依次绑定到$1
、$2
等编号变量。你可以为call
函数指定任意多个参数,你还可以通过$0
来访问当前所执行的函数的名称(即变量名称)。使用这个信息,我们可以编写一对调试函数来追踪宏的扩展过程:
# $(debug-enter)
debug-enter = $(if $(debug_trace),\
$(warning Entering $0($(echo-args))))
# $(debug-leave)
debug-leave = $(if $(debug_trace),$(warning Leaving $0))
comma := ,
echo-args = $(subst ' ','$(comma) ',\
$(foreach a,1 2 3 4 5 6 7 8 9,'$($a)'))
如果我们要查看函数a
和b
是如何被调用的,可以:
debug_trace = 1
define a
$(debug-enter)
@echo $1 $2 $3
$(debug-leave)
endef
define b
$(debug-enter)
$(call a,$1,$2,hi)
$(debug-leave)
endef
trace-macro:
$(call b,5,$(MAKE))
对这个makefile
执行make
后会有如下输出:
$ make
makefile:14: Entering b( ‘5’, ‘make’, ”, ”, ”, ”, ”, ”, ”)
makefile:14: Entering a( ‘5’, ‘make’, ‘hi’, ”, ”, ”, ”, ”, ”)
makefile:14: Leaving a
makefile:14: Leaving b
5 make hi
1.eval与value函数
TODO