Makefile中常用到的函数总结
目录
一、字符串操作函数
1.字符串处理函数 subst
2.模式字符串替换函数 patsubst
3.去空格函数 strip
4.查找字符串函数 findstring
5.过滤函数 filter
6.反过滤函数 filter-out
7.排序函数 sort
8.取单词函数 word
9.取单词串函数 wordlist
10.单词个数统计函数 words
11.首单词函数 firstword
二、文件名操作函数
1.取目录函数 dir
2.取文件函数 notdir
3.取后缀函数 suffix
4.取前缀函数 basename
5.加后缀函数 addsuffix
6.连接函数 join
三、foreach 函数
四、call函数
五、origin函数
六、shell函数
七、控制make的函数
一、字符串操作函数
1.字符串处理函数 subst
英文中sub有替补的意思,subst的函数形式
$(subst <from>,<to>,<text>)
名称:字符串替换函数——
subst
。
功能:把字串<text>
中的<from>
字符串替换成<to>
。
返回:函数返回被替换过后的字符串。
举例:
$(subst ee,EE,feet on the street)
返回值为:(将ee替换为EE)
fEEt on the strEEt
2.模式字符串替换函数 patsubst
$(patsubst <pattern>,<replacement>,<text>)
名称:模式字符串替换函数——
patsubst
。
功能:查找<text>
中的单词(单词以“空格”、“Tab”或“回车”“换行”分隔)是否符合模式<pattern>
,如果匹配的话,则以<replacement>
替换。这里,<pattern>
可以包括通配符%
,表示任意长度的字串。如果<replacement>
中也包含%
,那么,中的这个%
将是<pattern>
中的那个%
所代表的字串。(可以用/
来转义,以/%
来表示真实含义的%
字符)
返回:函数返回被替换过后的字符串。
举例:
$(patsubst %.c,%.o,x.c.c bar.c)
返回结果是
x.c.o bar.o
将字串
x.c.c bar.c
符合模式%.c
的单词替换成%.o
3.去空格函数 strip
$(strip <string>)
名称:去空格函数——
strip
。
功能:去掉<string>
字串中开头和结尾的空字符。
返回:返回被去掉空格的字符串值。
举例:
$(strip a b c )
把字串
a b c
去到开头和结尾的空格,返回结果是a b c
4.查找字符串函数 findstring
$(findstring <find>,<in>)
名称:查找字符串函数——
findstring
。
功能:在字串<in>
中查找<find>
字串。
返回:如果找到,那么返回<find>
,否则返回空字符串。
举例:
$(findstring a,a b c)
返回
a
字符串$(findstring a,b c)
返回“”字符串(空字符串)
5.过滤函数 filter
$(filter <pattern...>,<text>)
名称:过滤函数——
filter
。
功能:以<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
6.反过滤函数 filter-out
$(filter-out <pattern...>,<text>)
名称:反过滤函数——
filter-out
。
功能:以<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``
7.排序函数 sort
$(sort <list>)
名称:排序函数——
sort
。
功能:给字符串<list>
中的单词排序(升序)。
返回:返回排序后的字符串。
sort
函数会去掉<list>
中相同的单词。
举例:
$(sort foo bar lose)
返回值为:
bar foo lose
$(sort foo bar lose foot)
返回值为:bar foo foot lose
$(sort foo bar lose foo)
返回值为:
bar foo lose #去掉了相同的单词
8.取单词函数 word
$(word <n>,<text>)
名称:取单词函数——
word
。
功能:取字符串<text>
中第<n>
个单词。(从一开始)
返回:返回字符串<text>
中第<n>
个单词。如果<n>
比<text>
中的单词数要大,那么返回空字符串。
举例:
$(word 2, foo bar baz)
返回值是
bar
9.取单词串函数 wordlist
$(wordlist <s>,<e>,<text>)
名称:取单词串函数——
wordlist
。
功能:从字符串<text>
中取从<s>
开始到<e>
的单词串。<s>
和<e>
是一个数字。
返回:返回字符串<text>
中从<s>
到<e>
的单词字串。如果<s>
比<text>
中的单词数要大,那么返回空字符串。如果<e>
大于<text>
的单词数,那么返回从<s>
开始,到<text>
结束的单词串。
举例:
$(wordlist 2, 3, foo bar baz)
返回值是
bar baz
10.单词个数统计函数 words
$(words <text>)
名称:单词个数统计函数——
words
。
功能:统计<text>
中字符串中的单词个数。
返回:返回<text>
中的单词数。
举例:
$(words, foo bar baz)
返回值是
3
。如果要取
<text>
中最后的一个单词,可以这样:$(word $(words <text>),<text>)
text = foo bar baz
$(word $(words $(text)),$(text))
返回值
baz
11.首单词函数 firstword
$(firstword <text>)
名称:首单词函数——
firstword
。
功能:取字符串<text>
中的第一个单词。
返回:返回字符串<text>
的第一个单词。
举例:
$(firstword foo bar)
返回值是
foo
也函数可以用
word
函数来实现:$(word 1,<text>)
二、文件名操作函数
1.取目录函数 dir
$(dir <names...>)
名称:取目录函数——
dir
。
功能:从文件名序列<names>
中取出目录部分。目录部分是指最后一个反斜杠(/
)之前的部分。如果没有反斜杠,那么返回./
。
返回:返回文件名序列<names>
的目录部分。
举例:
$(dir src/foo.c hacks)
返回值是
src/ ./
2.取文件函数 notdir
$(notdir <names...>)
名称:取文件函数——
notdir
。
功能:从文件名序列<names>
中取出非目录部分。非目录部分是指最后一个反斜杠(/
)之后的部分。
返回:返回文件名序列<names>
的非目录部分。
举例:
$(notdir src/foo.c hacks)
返回值是
foo.c hacks
3.取后缀函数 suffix
$(suffix <names...>)
名称:取后缀函数——
suffix
。
功能:从文件名序列<names>
中取出各个文件名的后缀。
返回:返回文件名序列<names>
的后缀序列,如果文件没有后缀,则返回空字串。
举例:
$(suffix src/foo.c src-1.0/bar.c hacks)
返回值是
.c .c
4.取前缀函数 basename
$(basename <names...>)
名称:取前缀函数——
basename
。
功能:从文件名序列<names>
中取出各个文件名的前缀部分。
返回:返回文件名序列<names>
的前缀序列,如果文件没有前缀,则返回空字串。
举例:
$(basename src/foo.c src-1.0/bar.c hacks)
返回值是
src/foo src-1.0/bar hacks
5.加后缀函数 addsuffix
$(addsuffix <suffix>,<names...>)
名称:加后缀函数——
addsuffix
。
功能:把后缀<suffix>
加到<names>
中的每个单词后面。
返回:返回加过后缀的文件名序列。
举例:
$(addsuffix .c,foo bar)
返回值是
foo.c bar.c
6.连接函数 join
$(join <list1>,<list2>)
名称:连接函数——
join
。
功能:把<list2>
中的单词对应地加到<list1>
的单词后面。如果<list1>
的单词个数要比<list2>
的多,那么,<list1>
中的多出来的单词将保持原样。如果<list2>
的单词个数要比<list1>
多,那么,<list2>
多出来的单词将被复制到<list2>
中。
返回:返回连接过后的字符串
举例:
$(join aaa bbb , 111 222 333)
返回值是
aaa111 bbb222 333
三、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)
$(name)
中的单词会被挨个取出,并存到变量n
中,$(n).o
每次根据$(n)
计算出一个值,这些值以空格分隔,最后作为foreach
函数的返回,所以,$(files)
的值是a.o b.o c.o d.o
四、call函数
$(call <expression>,<parm1>,<parm2>,<parm3>...)
call
函数是唯一一个可以用来创建新的参数化的函数。你可以写一个非常复杂的表达式,这个表达式中,你可以定义许多参数,然后你可以用call
函数来向这个表达式传递参数。当
make
执行这个函数时,<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
五、origin函数
$(origin <variable>)
他并不操作变量的值,他只是告诉你你的这个变量是哪里来的?
<variable>
是变量的名字,不应该是引用。所以你最好不要在<variable>
中使用$
字符。Origin
函数会以其返回值来告诉你这个变量的“出生情况”
下面,是origin
函数的返回值:
- undefined
如果从来没有定义过,origin函数返回这个值undefined
。 - default
如果<variable>
是一个默认的定义,比如CC
这个变量,这种变量我们将在后面讲述。 - environment
如果<variable>
是一个环境变量,并且当Makefile
被执行时,-e
参数没有被打开。 - file
如果<variable>
这个变量被定义在Makefile
中。 - command line
如果<variable>
这个变量是被命令行定义的。 - override
如果<variable>
是被override
指示符重新定义的。 - automatic
如果<variable>
是一个命令运行中的自动化变量。关于自动化变量将在后面讲述。
这些信息对于我们编写Makefile
是非常有用的,例如,假设我们有一个Makefile
其包了一个定义文件Make.def
,在Make.def
中定义了一个变量bletch
,而我们的环境中也有一个环境变量bletch
,此时,我们想判断一下,如果变量来源于环境,那么我们就把之重定义了,如果来源于Make.def
或是命令行等非环境的,那么我们就不重新定义它。于是,在我们的Makefile
中,我们可以这样写:
ifdef bletch
ifeq "$(origin bletch)" "environment"
bletch = barf, gag, etc.
endif
endif
当然,你也许会说,使用override
关键字不就可以重新定义环境中的变量了吗?为什么需要使用这样的步骤?是的,我们用overrid
e是可以达到这样的效果,可是override
过于粗暴,它同时会把从命令行定义的变量也覆盖了,而我们只想重新定义环境传来的,而不想重新定义命令行传来的。
六、shell函数
它的参数应该就是操作系统Shell的命令。它和反引号`
是相同的功能。这就是说,shell
函数把执行操作系统命令后的输出作为函数返回。于是,我们可以用操作系统命令以及字符串处理命令awk
,sed
等等命令来生成一个变量,如:
contents := $(shell cat foo)
files := $(shell echo *.c)
注意,这个函数会新生成一个Shell
程序来执行命令,所以你要注意其运行性能,如果你的Makefile
中有一些比较复杂的规则,并大量使用了这个函数,那么对于你的系统性能是有害的。特别是Makefile
的隐晦的规则可能会让你的shell
函数执行的次数比你想像的多得多。
七、控制make的函数
make
提供了一些函数来控制make
的运行。通常,你需要检测一些运行Makefile
时的运行时信息,并且根据这些信息来决定,你是让make
继续执行,还是停止。
$(error <text ...>)
产生一个致命的错误,<text ...>
是错误信息。注意,error
函数不会在一被使用就会产生错误信息,所以如果你把其定义在某个变量中,并在后续的脚本中使用这个变量,那么也是可以的。例如:
示例一:
ifdef ERROR_001
$(error error is $(ERROR_001))
endif
示例二:
ERR = $(error found an error!)
.PHONY: err
err: ; $(ERR)
示例一会在变量ERROR_001定义了后执行时产生error调用,而示例二则在目录err被执行时才发生error调用。
$(warning <text ...>)
这个函数很像error
函数,只是它并不会让make
退出,只是输出一段警告信息,而make
继续执行
注:本文是根据陈皓,文章来源于他的CSDN专栏(1条消息) 编程语言_haoel的博客-CSDN博客