在 Makefile 中可以使用函数来处理文本,从而让我们的命令或规则更为灵活和智能。make 所支持的函数也不算很多,不过已经足够我们使用了。函数调用后,函数的返回值可以当做变量来使用。
1.函数调用语法
$(<function> <arguments>)
#或
${<function> <arguments>}
函数调用以$
开头,以圆括号或花括号把函数名和参数括起,像是对一个变量的引用,函数中的参数可以使用变量。其中<function>
为函数名,<arguments>
为函数参数,由空白符(空格、Tab)分隔,如果有多个参数,则使用逗号隔开。
为了统一风格,建议函数和变量统一使用圆括号,如使用$(subst a,b,$(x))
这样的形式,而不是$(subst a,b,${x})
的形式。
2.字符串替换与分析函数
2.1 subst
- 原型
$(subst <from>,<to>,<text>)
- 功能
将字符串text中的from变为to。
- 示例
$(subst ee,EE,feet on the street)
返回 fEEt on the strEEt。
2.2 patsubst
- 原型
$(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
。
2.3 strip
- 原型
$(strip <string>)
- 功能
去掉string字符串中开头和结尾的空白字符(空格、Tab)。
- 示例
$(strip a b c )
把字串“a b c ”去到开头和结尾的空格,结果是“a b c”。
2.4 findstring
- 原型
$(findstring <FIND>,<IN>)
- 功能
从字符串<IN>
中查找指定的字符串<FIND>
,找到返回<FIND>
,找不到返回空。
- 示例
$(findstring a,a b c)
$(findstring a,b c)
第一个函数结果是字符串是“a”,第二个返回空字符。
2.5 filter
- 原型
$(filter <pattern...>,<text>)
- 功能
以<pattern>
模式过滤<text>
字符串中的单词,保留符合模式<pattern>
的单词。可以有多个模式。
- 示例
sources := foo.c bar.c baz.s ugh.h
result := $(filter %.c %.s,${sources})
result 是“foo.c bar.c baz.s”。
2.6 filter-out
- 原型
$(filter-out <pattern...>,<text>)
- 功能
以<pattern>
模式过滤<text>
字符串中的单词,去除符合模式<pattern>
的单词。可以有多个模式。
- 示例
objects=main1.o foo.o main2.o bar.o
mains=main1.o main2.o
result := $(filter-out $(mains),$(objects))
result 是 “foo.o bar.o”。
2.7 sort
- 原型
$(sort <list> )
- 功能
给字符串<list>
中的单词排序(升序)。注意:sort函数会去掉<list>
中相同的单词
- 示例
$(sort foo bar lose)
返回 “bar foo lose” 。
2.8 word
- 原型
$(word <n>,<text>)
- 功能
取字符串<text>
中第<n>
个单词。下标从 1 开始,如果比
字符串。
- 示例
$(word 2, foo bar baz)
返回 bar。
2.9 wordlist
- 原型
$(wordlist <s>,<e>,<text> )
- 功能
从字符串<text>
中取从<s>
开始到<e>
的单词串。<s>
和<e>
是一个数字下标,下标从1开始。如果<s>
比<text>
中的单词数要大,那么返回空字符串。如果<e>
大于<text>
的单词数,那么返回从<s>
开始,到<text>
结束的单词串。
- 示例
$(wordlist 2, 3, foo bar baz)。
返回 “bar baz”。
2.10 words
- 原型
$(words <text> )
- 功能
统计字符串<text>
中的单词个数。
- 示例
$(words, foo bar baz)
返回 3。
- 拓展
如果我们要取<text>
中最后的一个单词,可以这样:
$(word $(words <text> ),<text> )
2.11 firstword
- 原型
$(firstword <word...>)
其中 <word…> 为多个空格分隔的单词。
- 功能
取word…中的第一个单词。
- 示例
$(firstword a b c)
返回 a。
2.12 lastword
- 原型
$(lastword <word...>)
其中word…为多个空白符(空格、Tab)分隔的单词。
- 功能
作用与 firstword 函数相反,取 word… 中的最后一个单词。
- 示例
$(firstword a b c)
返回 c。
3.文件名称处理函数
3.1 dir
- 原型
$(dir <names...>)
- 功能
从多个以空白符分隔的文件列表中获取文件目录。目录部分是指最后一个反斜杠 / 之
前的部分。如果没有反斜杠,那么返回 “./”。
示例:
$(dir src/foo.c hacks)
返回 “src ./”。
3.2 notdir
- 原型
$(notdir <names...>)
- 功能
从多个以空白符分隔的文件列表中获取非目录部分。非目录部分是指最后一个反斜杠 / 之后的内容。
- 示例
$(notdir src/foo.c hacks)
返回 “foo.c hacks”。
3.3 suffix
- 原型
$(suffix <names…>)
- 功能
文件名序列<names>
中取出各个文件名的后缀。如果文件没有后缀,则返回空字串。
- 示例
$(suffix src/foo.c src-1.0/bar.c hacks)
返回 “.c .c”。
3.4 basename
- 原型
$(basename <names...>)
- 功能
从文件名序列<names>
中取出各个文件名的前缀部分。如果文件没有前缀,则返回空字串。
- 示例
$(basename src/foo.c src-1.0/bar.c hacks)
返回 "src/foo src-1.0/bar hacks”。
3.5 addsuffix
- 原型
$(addsuffix <suffix>,<names...> )
- 功能
把后缀<suffix>
加到<names>
中的每个单词后面。
- 示例
$(addsuffix .c,foo bar)
返回 “foo.c bar.c”。
3.6 addprefix
- 原型
$(addprefix <prefix>,<names...> )
- 功能
把前缀加到中的每个单词后面。
- 示例
$(addprefix src/,foo bar)
返回值是 “src/foo src/bar”。
3.7 join
- 原型
$(join <list1>,<list2> )
- 功能
把<list2>
中的单词对应地加到<list1>
的单词后面。如果<list1>
的单词个数与比< list2>
不同,则原样输出。
- 示例
res1 = $(join a b,.c .cpp .go)
res2 = $(join a b c,.c .cpp)
res1 是 “a.c b.cpp .go”,res2 是 “a.c b.cpp c”。
3.8 wildcard
- 原型
$(wildcard <pattern...>)
- 功能
扩展通配符函数用于获取匹配此模式的所有文件列表,文件名以空格分隔。如果不存在任何符合此模式的文件,返回空。
示例:
$(wildcard *.cpp *.c)
返回 make 工作目录下的所有以 .cpp 和 .c 为后缀的文件名。
4.控制函数
控制函数控制 make 运行的方式。通常,它们用于向生成文件的用户提供信息,或者在检测到某种环境错误时使 make 停止。
4.1 info
- 原型
$(info <text>)
- 作用
向标准输出打印文本<text>
,用于输出调试信息。
- 示例
$(info some debug info)
标准输出打印 “some debug info”。
4.2 warning
- 原型
$(warning <info>)
- 功能
向标准输出打印文本<text>
,用于输出警告信息。make继续执行。
- 示例
$(warning some warning info)
标准输出打印 “some warning info”。
4.3 error
- 原型
$(error <text>)
- 功能
向标准错误输出打印文本<text>
,用于输出指明错误信息。make停止执行。
- 示例
ERROR="can't find commad g++"
ifdef ERROR
$(error error is $(ERROR1))
endif
因为 ERROR 值非空,所以输出错误信息如下错误信息,并停止 make 的执行。
makefile:3: *** error is "can't find commad g++". Stop.
5.其它函数
5.1 foreach
- 原型
$(foreach <var>,<list>,<text>)
- 功能
把参数 list 中的单词逐一取出放到参数 var 所指定的变量中,然后再执行 text 所包含的表达式。每一次 text 会返回一个字符串,循环过程中,text 的所返回的每个字符串会以空格分隔,最后当整个循环结束时,text 所返回的每个字符串所组成的整个字符串(以空格分隔)将会是 foreach 函数的返回值。
所以,var 是一个变量名,list 是一个元素列表,而 text 中会使用 var 这个参数依次枚举 list 中的元素。
- 示例
names := a b c d
files := $(foreach n,${names},$(n).o)
files 的结果为a.o b.o c.o d.o
。
5.2 call
- 原型
$(call <expression>,<parm1>,<parm2>,<parm3>,...)
- 功能
call 函数是唯一一个可以用来创建新的参数化函数。你可以写一个非常复杂的表达式,这个表达式中,你可以定义许多参数,然后你可以用 call 函数来向这个表达式传递参数。当 make 执行 call 函数时,自定义表达式 expression 中的参数,如$(1),$(2),$(3)
等,会被参数<parm1>,<parm2>,<parm3>
依次取代。expression 的返回值就是 call 函数的返回值。
- 示例
reverse = $(1) $(2)
foo = $(call reverse,a,b)
foo 的值是 “a b”。当然,参数的次序是可以自定义的,不一定是顺序的,如:
reverse = $(2) $(1)
foo = $(call reverse,a,b)
此时的 foo 的值就是b a
。
5.3 eval
- 原型
$(eval <text>)
- 功能
eval 函数是一个比较特殊的函数,其将<text>
作为 makefile 的一部分而被 make 解析执行。
注意:该函数在执行时会对它的参数进行两次展开,第一次展开是由 eval 函数本身完成,第二次是函数展开后的结果作为 makefile 内容时由 make 解析时展开。
- 返回值
无返回值。
- 示例
假设有以下 makefile。
define MA
ALL:
@echo hello world
endef
$(info $(MA))
$(info ----------------------)
$(eval $(MA))
执行 make 命令将会输出如下内容:
ALL:
@echo hello world
----------------------
hello world
可以看出,$(eval $(MA))
的执行相当于 make 命令执行了如下指令:
ALL:
@echo hello world
即执行 Shell 命令echo hello world
。
5.4 shell
- 原型
$(shell <shell_command>)
- 功能
shell 函数不像其它的函数,顾名思义,它的参数是操作系统的 Shell 命令,shell 函数把执行 Shell 命令后的输出作为函数返回。
- 示例
$(shell cat foo)
返回 foo。
参考文献
[1] Makefile经典教程(掌握这些足够)
[2] GNU make manual