Makefile中可以使用函数来处理变量,从而让我们的命令或者规则更加灵活。函数调用之后,函数返回值可以当做变量使用
使用函数
在Makefile中可以使用函数来处理变量,从而使我们的命令或者规则更为灵活。make所支持的函数并不多,基本使用方法如下
$(<function><arguments>)
#或者
${<function><arguments>}
function是函数名,arguments是参数,多个参数用,
隔开,函数名和参数之间用空格隔开。
字符串处理函数
subst
$(subst <from>,<to>,<text>)
名称:字符串替换函数
功能:将字符串text中的from字符替换成to
返回:函数返回被替换过的字符串
例子
ss := $(subst ee,EE,feet on the street)
运行之后的结果是fEEt on the strEEt
patsubst
$(patsubst <pattern>,<replacement>,<text>)
名称:模式字符串替换函数
功能:查找text中的单词(单词以空格
,Tab键
,回车键
)是否符合模式pattern
,如果匹配成功,则以replacement
替换。这里的pattern
中可以包括通配符%
,表示任意长度的字符,如果replacement
中也包含%
,那么replacement
中的%
将和pattern
中的%
表示的是听一个对象。同时可以使用转义符"/"
返回:函数返回被替换过的字符串
例子
ss := $(patsubst %.c,%.o,x.c.c bar.c)
运行之后的结果是x.c.o bar.o
$(var:<pattern> = <replacement>)
#相当于
$(patsubst <pattern>,<replacement>,$(var))
strip
$(strip <string>)
名称:去空格函数
功能:去掉string
字符串中开头和结尾的空字符
返回:返回被去掉空格的字符串值
例子
ss := $(strip a b c)
返回:a b c
findstring
$(findstring <find>,<in>)
名称:查找字符串函数
功能:在字符串in
中查找find
字符串
返回:如果能找到返回find
,否则就返回空字符串
例子
$(findstring a,a b c)
$(findstring a,b c d)
返回:第一个返回a b c
第二个返回”“(空)
filter
$(filter <pattern...>,<text>)
名称:过滤函数
功能:以pattern
模式过滤text
字符串中的单词,保留符合模式pattern
的单词,可以有多个模式
返回:返回符合模式pattern
的字符串
例子:
sources := foo.c bar.c baz.s ugh.h
foo: $(sources)
gcc $(filter %.c $.s,$(sources)) -o foo
其中$(filter %.c $.s,$(sources))
的返回值是foo.c bar.c baz.s
filter-out
$(filter-out <pattern...>,<text>)
名称:反过滤函数
功能:以pattern
模式过滤text
字符串中的单词,去除符合模式pattern
的单词,可以多个模式
返回:返回不符合模式pattern
的字符串
例子:
objects = main1.o foo.o main2.o bar.o
mains = main1.o main2.o
$(filter-out $(mains),$(objects))
返回:foo.o bar.o
这里字符串也可以当做过滤参数
sort
$(sort <list>)
名称:排序函数
功能:给字符串list
中的单词排序(升序)
返回:返回排序之后的字符串
例子
$(sort foo bar lose)
返回:bar foo lose
注意:sort会去掉list中重复的单词
word
$(word <n>,<next)
名称:取单此函数
功能:去字符串text
中的第n
个单词(从1开始)
返回:返回字符串text
中的第n
个单词,如果n
比text
中的单词数要大,那么返回空字符串
例子
$(word 3,foo bar baz)
返回:baz
wordlist
$(words <text>)
名称:单词个数统计函数
功能:统计text
中字符串单词的个数
返回:返回text
中单词数
例子
$(words bar util main foo)
返回:4
如果我们想要去字符串中最后一个单词可以这样用$(word $(words <text>),<text)
wordlist
$(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
firstword
$(firstword <text>)
名称:首单词函数
功能:去字符串text
的第一个单词
返回:返回字符串text
的第一个单词
例子
$(firstword foo bar)
返回:foo
文件名操作函数
下面的函数主要是用来处理文件名,每个函数的参数字符串都会被当做一个或者一系列的文件名来对待
dir
$(dir <names...>)
名称:取目录函数
功能:从文件名序列names
中取出目录部分。目录部分是指最后一个反斜杠/
之前的部分,如果没有反斜杠,那么直接返回./
返回:返回文件名序列的目录部分
例子:
$(dir src/main.c /paul/works/Libreoffices/Makefile text.txt)
返回的结果:src
/paul/works/Libreoffices
./
notdir
$(notdir <names...>)
名称:取文件函数
功能:从文件名序列names
中取出非目录的部分,非目录部分是指最后一个反斜杠/
之后的部分
返回:返回文件名序列names
的费目录部分
例子:
$(notdir src/main.c /paul/works/Libreoffices/Makefile text.txt)
返回的结果是:main.c
Makefile
text.txt
suffix
$(suffix <names...>)
名称:去后缀名函数
功能:从文件名序列names
的后缀序列,如果文件没有后缀,直接返回空字符串
返回:文件名序列names
的后缀序列
例子:
$(suffix src/foo.c src-1.0/bar.c text.txt)
返回的结果是:.c
.c
.txt
basename
$(basename <names...>)
名称:取前缀函数
功能:从文件名序列names
中取各个文件名的前缀部分
返回:返回前缀名
例子:
$(basename src/foo.c src-1.0/bar.c text.text)
返回结果是:src/foo
src-1.0/bar
text
addsuffix
$(addsuffix <suffix>,<names...>)
名称:后缀名函数
功能:吧后缀suffix
加到names
中的每个单词后面
返回:返回加过的后缀文件名序列
例子:
$(addsuffix .c,test foo util main.c)
返回结果是:test.c
foo.c
util.c
main.c.c
addprefix
$(addprefix <prefix>,<names...>)
名称:加前缀函数
功能:把前缀prefix
加到names
中的每个单词后面
返回:返回加过前缀的文件名序列
例子:
$(addprefix src/,foo util main)
返回结果是:src/foo
src/util
src/main
join
$(join <list1>,<list2>)
名称:链接函数
功能:把list2
中的单词对应的加入到list1
中单词的后面,如果list1
的单词个数要比list2
的多,那么list1
中多处来的单词保持原样,如果list2
的单词个数比list1
多,则list2
多出来的单词会被复制到list2
中
返回:返回链接过的字符串
例子:
$(join aaa bbb ccc,111 222 333)
返回结果是:aaa111 bbb222 ccc333
如果是:
$(join aaa bbb,111 222 333)
返回结果:aaa111 bbb222 333
如果是:
$(join aaa bbb ccc,111 222)
返回结果是: aaa111 bbb222 ccc
foreach函数
foreach函数和别的函数非常不一样,因为这个函数是用来做循环的,如果之前学过java,我们会知道,java刚好有这个一个循环语句,Makefile中的foreach函数几乎是仿照UNIX标准Shell的for语句实现的。基本语法是
$(foreach <var>,<list>,<text>)
这个函数的意思是,把参数list
中的单词逐一取出放在参数var
所指定的变量中,然后在执行text
所包含的表达式。每次text
都会返回一个字符串,循环过程中,text
的所返回的每个字符串会以空格分割,最后当整个循环结束是,text
所返回的每个字符串所组成的整个字符串(以空格分隔)将会是foreache函数的返回值
所以var
最好是一个变量名,list
可以是一个表达式,text
中一般会使用var
变量,例如:
names := a b c d
files := $(foreach n,$(names),$(n).o)
这里面,变量names
中的每一个对象都会被取出来,然后分别赋值给n
,然后由变量n
执行最后一句话,将所有的内容后面加上.o
,所以输出的最后结果是a.o b.o c.o d.o
注意:foreach
中的var
是一个局部变量,临时的,函数执行完之后,没有意义了
if函数
if函数很像GNU的make所支持的条件语句-ifeq,if函数的语法是
$(if <condition>,<then-part>)
#或者是
$(if<condition>,<then-part>,<else-part>)
call函数
call函数是唯一一个可以用来创建新的参数化的函数,我们可以写一个非常复杂的表达式,在表达式中,我们可以定义很多参数,然后你可以用call函数来向这个表达式传递参数,基本语法是:
$(call <expression>,<parm1>,<parm2>,<parm3>...)
当make执行这个函数时,expression
参数中的变量,如$(1)
,$(2)
,$(3)
等,会被参数,,一次取代,而expression
的返回值是call函数的返回值,例如:
reverse = $(1) $(2)
foo = $(call reverse ,a ,b)
那么foo的值就是a b
。当然参数的次序是可以自定义的,不一定是顺序的,如:
reverse = $(2) $(1)
foo = $(call reverse,a,b)
这是foo的值就是b a
origin函数
origin函数不像其他的函数,他并不操作的值,他只是告诉你这个变量是哪里来的?语法是:
$(origin <variable>)
注意variable
是变量的名字,不应该是引用,所以最好不要再variable
中使用$
字符,origin函数会以其返回值来告诉你这个变量的”出生情况”,origin函数的返回值是undefined
,如果variable
从来没有定义过,origin函数返回这个值undefined