(1)Makefile中,函数的调用和变量的引用格式很像,变量引用的格式为$(变量名),而函数调用的格式如下:
- $(<function> <arguments>) 或者 ${<function> <arguments>}
- function 是函数名,arguments 是函数的参数。
- 参数之间要用逗号分隔开。
- 参数和函数名之间使用空格分开。
- 调用函数的时候要使用字符“$”,后面可以跟小括号或者大括号。
(2)关于Shell函数,见:Shell函数。
(1)使用格式
- $(patsubst <pattern>,<replacement>,<text>)
- 函数名的pat是pattern(模式)的缩写,而subst是substitute(替换)的缩写。
- 该函数查找text 中的单词是否符合模式 pattern,如果匹配则用 replacement 替换。
- 如果test是列表,则其成员间以空格隔开。
- 返回值为替换后的新字符串。
(2)举例说明
- xjh@ubuntu:~/iot/tmp$ cat Makefile
- OBJ = $(patsubst %.c,%.o,1.c 2.c 3.c)
- all:
- @echo $(OBJ)
- xjh@ubuntu:~/iot/tmp$ make
- 1.o 2.o 3.o
- xjh@ubuntu:~/iot/tmp$
(1)使用格式
- $(subst <from>,<to>,<text>)
- 该函数把字符串text中的 form 替换成 to,返回值为替换后的新字符串。
(2)举例说明
- xjh@ubuntu:~/iot/tmp$ cat Makefile
- OBJ=$(subst ee,EE,feet on the street)
- all:
- @echo $(OBJ)
- xjh@ubuntu:~/iot/tmp$ make
- fEEt on the strEEt
- xjh@ubuntu:~/iot/tmp$
(1)使用格式
- $(strip <string>)
- 该函数将字符串多个连续的空格合并成为一个空格,返回值为合并空格后的字符串。
(2)举例说明
- xjh@ubuntu:~/iot/tmp$ cat Makefile
- OBJ = $(strip " a b c")
- all:
- @echo -n $(OBJ)
- xjh@ubuntu:~/iot/tmp$ make
- a b cxjh@ubuntu:~/iot/tmp$ #字符串开头的几个空格被合并为一个,内部的空格也如此
- xjh@ubuntu:~/iot/tmp$
- xjh@ubuntu:~/iot/tmp$ cat Makefile
- OBJ = $(strip " a b c ")
- all:
- @echo -n $(OBJ)
- xjh@ubuntu:~/iot/tmp$ make
- a b c xjh@ubuntu:~/iot/tmp$ #字符串结尾的几个空格被合并为一个,内部的空格也如此
- xjh@ubuntu:~/iot/tmp$ cat Makefile
- OBJ = $(strip "a b c ")
- all:
- @echo -n $(OBJ)
- xjh@ubuntu:~/iot/tmp$ make
- a b c xjh@ubuntu:~/iot/tmp$
(1)使用格式
- $(findstring <string>,<text>)
- 该函数在text中查找string,如果字符串存在则返回该字符串,否则返回空。
(2)举例说明
- OBJ=$(findstring abc,abcdef hahahahb dddd)
- all:
- @echo $(OBJ)
- xjh@ubuntu:~/iot/tmp$ make
- abc
- xjh@ubuntu:~/iot/tmp$
(1)使用格式
- $(filter <pattern>,<text>)
- 该函数从 text 中查找符合模式 pattern 的字符串,可以有多个 pattern 。
- 返回值为符合模式pattern 的字符串。
(2)举例说明
- xjh@ubuntu:~/iot/tmp$ cat Makefile
- OBJ=$(filter %.c %.o,1.c 2.o 3.s)
- all:
- @echo $(OBJ)
- xjh@ubuntu:~/iot/tmp$ make
- 1.c 2.o
- xjh@ubuntu:~/iot/tmp$
(1)使用格式
- $(filter-out <pattern>,<text>)
- 该函数去除符合模式 pattern的字符串,保留余下的字符串内容。
- 返回值是保留的字符串。
(2)举例说明
- xjh@ubuntu:~/iot/tmp$ cat Makefile
- OBJ=$(filter-out %.c %.o,1.o 2.c 3.s)
- all:
- @echo $(OBJ)
- xjh@ubuntu:~/iot/tmp$ make
- 3.s
- xjh@ubuntu:~/iot/tmp$
(1)使用格式
- $(sort <list>)
- 该函数将list中的单词排序(升序),返回值为排列后的字符串。
- 该函数会去除list中重复的字符串,然后再进行排序。
(2)举例说明
- xjh@ubuntu:~/iot/tmp$ cat Makefile
- OBJ=$(sort foo bar foo lost)
- all:
- @echo $(OBJ)
- xjh@ubuntu:~/iot/tmp$ make
- bar foo lost
- xjh@ubuntu:~/iot/tmp$
(1)使用格式
- $(word <n>,<text>)
- 该函数取出text中的第n个字符串,返回值为所取出的第 n 个字符串。
- 注意这里不是指text中的第n个字符,而是指以空格隔开的整体。
(2)举例说明
- xjh@ubuntu:~/iot/tmp$ cat Makefile
- OBJ=$(word 2,1.c 2.c 3.c)
- all:
- @echo $(OBJ)
- xjh@ubuntu:~/iot/tmp$ make
- 2.c #不是指第二个字符“.”,而是指第二个字符串2.c
- xjh@ubuntu:~/iot/tmp$
有时我们需要对文件名进行操作,比如获取文件的路径、去除文件的路径、取出文件前缀或后缀。Makefile 提供了相应的函数来实现文件名的操作,它们的使用格式与举例如下所示。
(1)使用格式
- $(dir <names>)
- 该函数从文件名序列 names 中取出目录部分。
- 返回值为目录部分,指的是最后一个反斜杠之前的部分,如果没有反斜杠将返回“./”。
(2)举例说明
- xjh@ubuntu:~/iot/tmp$ cat Makefile
- OBJ = $(dir src/foo.c hacks)
- all:
- @echo $(OBJ)
- xjh@ubuntu:~/iot/tmp$ make
- src/ ./
- xjh@ubuntu:~/iot/tmp$
(1)使用格式
- $(notdir <names>)
- 该函数从文件名序列 names 中取出非目录的部分,即最后一个反斜杠之后的部分。
- 返回值为文件非目录的部分,即最后一个反斜杠之后的部分。
- 如果没有反斜杠,说明这个names就是文件,则返回names。
(2)举例说明
- xjh@ubuntu:~/iot/tmp$ cat Makefile
- OBJ = $(notdir src/foo.c hacks)
- all:
- @echo $(OBJ)
- xjh@ubuntu:~/iot/tmp$ make all
- foo.c hacks
- xjh@ubuntu:~/iot/tmp$
(1)使用格式
- $(suffix <names>)
- 该函数从文件名序列中 names 中取出各个文件的后缀名。
- 返回值为文件名序列 names 中的后缀序列,如果文件没有后缀名,则返回空字符串。
(2)举例说明
- xjh@ubuntu:~/iot/tmp$ cat Makefile
- OBJ=$(suffix src/foo.c hacks doo.s)
- all:
- @echo $(OBJ)
- xjh@ubuntu:~/iot/tmp$ make
- .c .s
- xjh@ubuntu:~/iot/tmp$
(1)使用格式
- $(basename <names>)
- 该函数从文件名序列 names 中取出各个文件名的前缀部分(包括文件路径)。
- 返回值是被取出来的文件的前缀名,如果文件没有前缀名则返回空的字符串。
(2)举例说明
- xjh@ubuntu:~/iot/tmp$ cat Makefile
- OBJ = $(notdir src/foo.c hacks)
- all:
- @echo $(OBJ)
- xjh@ubuntu:~/iot/tmp$ make
- foo.c hacks
- xjh@ubuntu:~/iot/tmp$
(1)使用格式
- $(addsuffix <suffix>,<names>)
- 该函数把后缀 suffix 加到 names 中的每个字符串后面。
- 如果文件本来就存在后缀名,依然会加上后缀
- 返回值为添加上后缀的文件名序列。
(2)举例说明
- xjh@ubuntu:~/iot/tmp$ cat Makefile
- OBJ = $(addsuffix .c,src/foo.c hacks)
- all:
- @echo $(OBJ)
- xjh@ubuntu:~/iot/tmp$ make
- src/foo.c.c hacks.c
- xjh@ubuntu:~/iot/tmp$
(1)使用格式
- $(addperfix <prefix>,<names>)
- 把前缀 prefix加到 names中的每个单词的前面。
- 返回值为添加上前缀的文件名序列。
- 我们可以使用这个函数给文件添加路径。
(2)举例说明
- xjh@ubuntu:~/iot/tmp$ cat Makefile
- OBJ=$(addprefix src/, foo.c hacks)
- all:
- @echo $(OBJ)
- xjh@ubuntu:~/iot/tmp$ make
- src/foo.c src/hacks
- xjh@ubuntu:~/iot/tmp$
(1)使用格式
- $(join <list1>,<list2>)
- 该函数把 list2 中的单词对应位置地拼接到 list1 的后面,并返回拼接好的字符串。
- 如果list1与list2中字符串的数目不相同,多出来的部分保持不变。
(2)实例说明
- xjh@ubuntu:~/iot/tmp$ cat Makefile
- OBJ1 = $(join src car,abc zxc qwe)
- OBJ2 = $(join abc zxc qwe,src car)
- all:
- @echo $(OBJ1)
- @echo $(OBJ2)
- xjh@ubuntu:~/iot/tmp$ make
- srcabc carzxc qwe
- abcsrc zxccar qwe
- xjh@ubuntu:~/iot/tmp$
(1)使用格式
- $(wildcard PATTERN)
- 该函数列出当前目录下所有符合PATTERN 模式的文件名。
- 返回值为当前目录下所有符合PATTERN 模式的文件名,它们以空格分隔。
- 该函数通常与通配符 "*" 连用,一般使用在依赖规则的描述中。
(2)举例说明
- xjh@ubuntu:~/iot/tmp$ ls
- 1.c 1.h 2.o 2.s Makefile
- xjh@ubuntu:~/iot/tmp$ cat Makefile
- OBJ=$(wildcard *.c *.h)
- all:
- @echo $(OBJ)
- xjh@ubuntu:~/iot/tmp$ make
- 1.c 1.h
- xjh@ubuntu:~/iot/tmp$
Makefile中提供了两个控制 make 运行方式的函数:error函数、warnning函数。当 make 执行过程中检测到某些错误时,这些函数可以为用户提供消息,控制 make 执行过程是否继续。
(1)使用格式
- $(error TEXT)
- 该函数将产生致命错误,并提示TEXT信息给用户,退出 make 的执行。
- 该函数返回值为空。
- error函数在被调用时才会提示信息并结束 make 进程,因此如果error函数出现在命令中或者一个递归的变量定义时,读取 Makefile 时不会出现错误。当包含着error函数的命令被执行时,或者包含着error函数的递归变量被展开时,才会提示TEXT并退出make。
(2)举例说明
- xjh@ubuntu:~/iot/tmp$ cat Makefile
- ERROR = 1234
- all:
- ifdef ERROR
- $(error error is $(ERROR1))
- endif
- @echo $(ERROR) #因为前面报错退出了,这个语句不会被执行
- xjh@ubuntu:~/iot/tmp$ make
- Makefile:5: *** error is . Stop.
- xjh@ubuntu:~/iot/tmp$
- xjh@ubuntu:~/iot/tmp$ cat Makefile
- ERR = $(error found an error!)
- .PHONY:err
- err:
- $(ERR)
- #在make读取Makefile时不会出现致命错误。
- #只有"err" 作为目标被执行时才会出现。
- xjh@ubuntu:~/iot/tmp$ make
- Makefile:5: *** found an error!. Stop.
- xjh@ubuntu:~/iot/tmp$
- $(warning TEXT...)
- 该函数类似于error函数,展开过程相同,返回值也为空。
- 该函数不会导致致命错误,只是提示TEXT信息,make 的执行过程继续。
(1)使用格式
- $(foreach <var>,<list>,<text>)
- 把list中的单词逐一取出放到参数var这个变量中(即赋值给var),然后再执行text所包含的表达式。
- 每一次text都会返回一个字符串,循环过程中,text返回的每个字符串会以空格分割,最后当整个循环结束的时候,由text所返回的每个字符串所组成的整个字符串(以空格分隔)将会是 foreach 函数的返回值。
- var最好是一个变量名,list可以是一个表达式,而text中一般会只用var这个参数来枚举list中的单词。
- 注意,foreach 中的var参数是一个临时的局部变量,foreach 函数执行完后,参数var的变量将不再起作用,其作用域只在 foreach 函数当中。
(2)举例说明
- xjh@ubuntu:~/iot/tmp$ cat Makefile
- names := a b c d
- files := $(foreach n,$(names),$(n).o)
- all:
- @echo $(files)
- @echo "ABC$(n)D" #n只在foreach函数中起作用,因此这里是没有定义,所以输出为空
- xjh@ubuntu:~/iot/tmp$ make
- a.o b.o c.o d.o
- ABCD
- xjh@ubuntu:~/iot/tmp$
(1)使用格式
- $(if <condition>,<then-part>,<else-part>)
- 参数condition是 if表达式,如果其返回值是非空字符串,则condition为真,于是then-part就会被计算,否则else-part会被计算。
- 如果condition为真,则then-part是整个函数的返回值。
- 如果condition为假(空字符串),则else-part是这个函数的返回值。此时如果else-part没有被定义,则函数返回空字串符。
(2)举例说明
- xjh@ubuntu:~/iot/tmp$ cat Makefile
- OBJ0 := #这种方式就相当于没有这条语句
- OBJ1 := foo.c
- OBJ2 := $(if $(OBJ0),$(OBJ1),main.c)
- OBJ3 := $(if $(OBJ1),$(OBJ1),main.c)
- all:
- @echo $(OBJ2)
- @echo $(OBJ3)
- xjh@ubuntu:~/iot/tmp$ make
- main.c
- foo.c
- xjh@ubuntu:~/iot/tmp$
(1)使用格式
- $(call <expression>,<parm1>,<parm2>,<parm3>,...)
- 表达式expression中的变量$(1)、$(2)、$(3),会被parm1、parm2、parm3依次取代。
- 表达式expression的返回值就是call函数的返回值。
- 我们可以写一个非常复杂的表达式,在这个表达式中,我们可以定义很多的参数,然后使用call函数来向这个表达式传递参数。
(2)举例说明
- xjh@ubuntu:~/iot/tmp$ cat Makefile
- reverse = $(1) $(2)
- foo = $(call reverse,a,b)
- all:
- @echo $(foo)
- xjh@ubuntu:~/iot/tmp$ make
- a b
- xjh@ubuntu:~/iot/tmp$
- xjh@ubuntu:~/iot/tmp$ cat Makefile
- reverse = $(2) $(1) #参数的次序可以是自定义的,不一定是顺序的
- foo = $(call reverse,a,b)
- all:
- @echo $(foo)
- xjh@ubuntu:~/iot/tmp$ make
- b a
- xjh@ubuntu:~/iot/tmp$
(1)使用格式
- $(origin <variable>)
- 这里的variable是变量的名字,不是变量的引用,因此不要在 variable 前使用“$”字符。
- 该函数通过返回值告知使用者这个变量是哪里来的。比如有一个 Makefile文件,定义了一个变量bletch,而环境变量中也有一个环境变量bletch,我们可以通过这个函数的返回值判断该变量是不是环境变量。具体见举例说明。
(2)函数返回值
- “undefined”:如果<variable>从来没有定义过,函数将返回这个值。
- “default”:如果<variable>是一个默认的定义,比如说“CC”这个变量。
- “environment”:如果<variable>是一个环境变量并且当Makefile被执行的时候,“-e”参数没有被打开。
- “file”:如果<variable>这个变量被定义在Makefile中,将会返回这个值。
- “command line”:如果<variable>这个变量是被命令执行的,将会返回这个值。
- “override”:如果<variable>是被override指示符重新定义的。
- “automatic”:如果<variable>是一个命令运行中的自动化变量。
(2)举例说明
- xjh@ubuntu:~/iot/tmp$ cat Makefile
- var = xxx
- ifdef var
- ifeq "$(origin var)" "environment"
- OBJ=fromenvir
- endif
- ifeq "$(origin var)" "file"
- OBJ=fromfile
- endif
- ifeq "$(origin var)" "command line"
- OBJ=fromcmdline
- endif
- endif
- ALL:
- @echo $(OBJ)
- xjh@ubuntu:~/iot/tmp$ make
- fromfile
- xjh@ubuntu:~/iot/tmp$ make var=abc
- fromcmdline
- xjh@ubuntu:~/iot/tmp$