Make--(3)函数

作者 by adtxl / 2021-02-04 / 暂无评论 / 471 个足迹

1. 用户自定义函数

用户自定义函数能够将命令序列存储在变量里,让我们得以在makefile中使用各种应用程序。

2.内置函数

make的内置函数可分类为:字符串操作、文件名操作、流程控制、用户自定义函数以及若干重要的杂项函数。

所有的函数都会具有如下形式:

$(function-name arg1[, argn])

$(之后是内置函数的名称,接着是函数的参数。第一个参数的前导空格会被删除,但是后续的任何参数若包含前导(当然也包括内置的和结尾的)空格则都会被保留下来。
函数的参数是以逗号为分隔符,所以只有一个参数的函数并不需要使用逗号。许多只接受一个函数的参数会把它的参数视为一串以空格隔开的单词。对这些函数而言,它们会以空格作为分隔符。

2.1 字符串函数

1. filter函数

名称:
过滤函数filter

格式:
$(filter <pattern...>,<text> )

返回:
返回符合模式<pattern>的字串。

功能:
<pattern>模式过滤<text>字符串中的单词,保留符合模式<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”。

2. filter-out函数

名称:
反过滤函数filter-out

格式:
$(filter-out <pattern...>,<text> )

返回:
返回不符合模式<pattern>的字串。

功能:
<pattern>模式过滤<text>字符串中的单词,去除符合模式<pattern>的单词。可以有多个模式。存在多个模式时,模式表达式之间使用空格分割。

实例:

objects=main1.o foo.o main2.o bar.o
mains=main1.o main2.o

$(filter-out $(mains),$(objects)) 返回值是“foo.o bar.o”。

3. findstring函数

名称:
查找字符串函数

格式:
$(findstring <find>,<in> )

返回:
如果找到,那么返回<find>,否则返回空字符串。

功能:
在字串<in>中查找<find>字串。

实例:

str1 := a b c
str2 := b c

第一个函数返回“a”字符串,第二个返回空字符串
all:
    @echo $(findstring a,$(str1))
    @echo $(findstring a,$(str2))

4. subst函数

名称:
字符串替换函数

格式:
$(subst <search-string>, <replace-string>, <text>)

返回:
函数返回被替换过后的字符串。

功能:
把字串<text>中的<from>字符串替换成<to>,不具备通配符能力,它最常被用来在文件名列表中将一个扩展名替换成另一个扩展名。

实例:

$(subst a,the,There is a big tree)
把“There is a big tree”中的“a”替换成“the”,返回结果是“There is the big tree”。

5. patsubst函数

名称:
模式字符串替换函数

格式:
$(patsubst <search-pattern>,<replace-pattern>,<text> )

返回:
函数返回被替换过后的字符串,具备通配符能力。此处的模式只可以包含一个%字符。

功能:
查找<text>中的单词(单词以“空格”、“Tab”或“回车”“换行”分隔)是否符合模式<search-pattern>,如果匹配的话,则以<replace-pattern>替换。这里,<search-pattern>可以包括通配符“%”,表示任意长度的字串。如果<replace-pattern>中也包含“%”,那么,<replace-pattern>中的这个“%”将是<search-pattern>中的那个“%”所代表的字串。(可以用“\”来转义,以“\%”来表示真实含义的“%”字符)

实例:

$(patsubst %.c,%.o,x.c.c bar.c)
把字串“x.c.c bar.c”符合模式[%.c]的单词替换成[%.o],返回结果是“x.c.o bar.o”

6. words函数

名称:返回单词数量
格式:$(words text)
返回:text中的单词数量
功能:返回text中单词数量。其中,$(word n,text)返回text中的第n个单词,第一个单词的编号是1.如果n的值大于text中单词的个数,则此函数将返回空值
实例:

current := $(word $(words $(MAKEFILE_LIST)),$(MAKEFILE_LIST))

通过这种方式可以获得列表中的最后一个单词,在这里将返回最近读取的makefile的文件名。

7. firstword函数

名称:
格式:$(firstword text)
返回:
功能:此函数返回text中的第一个单词。此功能等效于$(word 1,text)
实例:

8. wordlist函数

名称:
格式:$(wordlist start,end,text)
返回:返回text中范围从start(含)到end(含)的单词。如果start的值大于单词的个数,返回空值。如果end的值大于单词的个数,则函数返回从start开始的所有单词。
功能:
实例:

2.2 重要的杂项函数

1. sort函数

名称:sort函数
格式:$(sort list)
返回:返回按照字典编纂顺序排列的不重复的单词列表,并以空格作为分隔符。
功能:sort函数会排序它的list参数并移除重复的项目。此外,sort函数还会删除前导以及结尾的空格。
实例:

2. shell函数

名称:
shell函数

格式:
$(shell <fun>)

返回:
shell函数的返回值。输出中所出现的一系列换行符号会被缩减成单一空格符号,任何接在后面的换行符号都会被删除。标准错误以及任何程序的结束状态都不会被返回。

功能:
为了使用shell的函数

实例:

例如files := $(shell echo *.c)

2.3 文件名函数

makefile的编写者通常会花许多时间在文件的处理上。

1. wildcard函数

名称:
通配符展开函数

格式:
$(wildcard PATTERN...)

返回:
如果被扩展的模式找不到相符的文件,则会返回空字符串。
功能:
在Makefile规则中,通配符会被自动展开。但在变量的定义和函数引用时,通配符将失效。这种情况下如果需要通配符有效,就需要使用函数“wildcard”

实例:
一般我们可以使用“$(wildcard *.c)”来获取工作目录下的所有的.c文件列表。复杂一些用法;可以使用“$(patsubst %.c,%.o,$(wildcard *.c))”,首先使用“wildcard”函数获取工作目录下的.c文件列表;之后将列表中所有文件名的后缀.c替换为.o。这样我们就可以得到在当前目录可生成的.o文件列表。

2. dir函数

名称:
格式:$(dir list...)
返回:
功能:dir函数返回list中每个单词的目录部分。
实例:

3. notdir函数

名称:
格式:$(notdir name...)
返回:
功能:notdir函数返回文件路径的文件名部分。
实例:

4. suffix函数

名称:
格式:$(suffix name...)
返回:
功能:suffix函数会返回它的参数中每个单词的后缀(即文件扩展名)
实例:

5. basename函数

名称:
格式:$(basename name...)
返回:
功能:
实例:

6. addsuffix函数

名称:
格式:
返回:
功能:
实例:

7. addprefix函数

名称:
格式:
返回:
功能:
实例:

8. join函数

名称:
格式:
返回:
功能:
实例:

2.4 流程控制

4. foreach函数

名称:
循环替换函数

格式:
$(foreach <var>,<list>,<text> )

返回:
返回循环<text>语句最终执行的结果

功能:
把参数<list>中的单词逐一取出放到参数<var>所指定的变量中, 然后再执行<text>所包含的表达式。每一次<text>会返回一个字符串,循环这个过程。

实例:

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'

当这个foreach函数被执行时,它会反复扩展循环主体$(letter),并且将循环控制变量letter的值依次设定成a、b、c、d。每次扩展所得到的文本会被累积起来,并以空格为分隔符。

2.5 较不重要的杂项函数

7. strip函数

名称:
去空字符函数

格式:
$(strip <string> )

返回:
返回被去掉空格的字符串值。

功能:
去掉<string>字串中开头和结尾的空字符,并将中间的多个连续空字符(如果有的话)合并为一个空字符

实例:

str1 := abc
str2 := abc
str3 := a     b     c

all:
@echo $(strip $(str1))
@echo $(strip $(str2))
@echo $(strip $(str3))

输出结果:
abc
abc
a b c

10. call函数

名称:
call函数是唯一一个可以创建定制化参数函数的引用函数。支持对自定义函数的引用;

格式:
$(call VARIABLE,PARAM,PARAM,...)

返回:
VARIABLE展开后的表达式的值

功能:
在执行时,将它的参数"PARAM"依次赋给临时变量"(1)","(2)".
call对参数的数目没有限制,也可以没有参数值。最后再对VARIABLE展开后的表达式进行处理.
说明:

  1. 变量VARIABLE在定义时最好定义为递归展开式;
  2. call函数中对VARIABLE的调用,直接给函数或变量名就好了,不要用"$";
  3. 多个PARAM使用逗号分割开,且逗号和PARAM之间不能有空格,否则会导致解析异常;

实例:
(1)变量的引用

变量定义为直接展开式
如果这里将VARIABLE1定义为直接展开式,最终调用call函数后,返回值为空
我的理解是,直接展开式在定义时将(1)和(2)展开,而此时它们的值为空,所以变量的值为空.当执行到call函数时,尽管带上了需要传递的参数,但PARAM((1)和(2))之前已经被展开了,故此时已经取不到传递进来的参数值.

VARIABLE1 := $(2) $(1)

$(info 1-$(VARIABLE1))

aa=$(call VARIABLE1,hello,world)

$(info 1-$(aa))

all:
    @echo Done

定义为递归展开式

VARIABLE1 = $(2) $(1)

$(info 2-$(VARIABLE1))

aa=$(call VARIABLE1,hello,world)

$(info 2-$(aa))

all:
    @echo Done

(2)函数的引用

不带参数的函数引用

define FUNC1
$(info echo 3-"hello")
endef
$(call FUNC1)
all:
    @echo Done

带参数的函数引用

define FUNC1
$(info echo 4-$(1) $(2))
endef

$(call FUNC1,hello,wolrd)

all:
    @echo Done

1. patsubst函数

名称:
格式:
返回:
功能:
实例:

1. patsubst函数

名称:
格式:
返回:
功能:
实例:
1. patsubst函数

名称:
格式:
返回:
功能:
实例:

1. patsubst函数

名称:
格式:
返回:
功能:
实例:

1. patsubst函数

名称:
格式:
返回:
功能:
实例:

1. patsubst函数

名称:
格式:
返回:
功能:
实例:
1. patsubst函数

名称:
格式:
返回:
功能:
实例:

1. patsubst函数

名称:
格式:
返回:
功能:
实例:

1. patsubst函数

名称:
格式:
返回:
功能:
实例:

1. patsubst函数

名称:
格式:
返回:
功能:
实例:

独特见解