您当前的位置:首页 > 计算机 > 编程开发 > 编译原理

Makefile中的函数(各类型函数使用格式与举例)

时间:03-25来源:作者:点击数:

一、Makefile中的函数格式

(1)Makefile中,函数的调用和变量的引用格式很像,变量引用的格式为$(变量名),而函数调用的格式如下:

$(<function> <arguments>)  或者  ${<function> <arguments>}
  • function 是函数名,arguments 是函数的参数。
  • 参数之间要用逗号分隔开。
  • 参数和函数名之间使用空格分开。
  • 调用函数的时候要使用字符“$”,后面可以跟小括号或者大括号。

(2)关于Shell函数,见:Shell函数

二、常用字符串处理函数

1、模式字符串替换函数:patsubst

(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$

2、字符串替换函数:subst

(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$ 

3、去空格函数:strip

(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$

4、查找字符串函数:findstring

(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$

5、过滤函数:filter

(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$ 

6、反过滤函数:filter-out

(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$ 

7、排序函数:sort

(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$ 

8、取单词函数:word

(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

(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$

2、取文件函数:notdir

(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$ 

3、取后缀名函数:suffix

(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$

4、取前缀函数:basename

(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$ 

5、添加后缀名函数:addsuffix

(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$ 

6、添加前缀名函数:addperfix

(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$ 

7、链接函数:join

(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$ 

8、获取匹配模式文件名函数:wildcard

(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函数

(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$ 

2、wanning函数

$(warning TEXT...)
  • 该函数类似于error函数,展开过程相同,返回值也为空。
  • 该函数不会导致致命错误,只是提示TEXT信息,make 的执行过程继续。

五、其他常用函数

1、foreach函数

(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$ 

2、if函数

(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$ 

3、call 函数

(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$ 

4、origin函数

(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$
方便获取更多学习、工作、生活信息请关注本站微信公众号城东书院 微信服务号城东书院 微信订阅号
推荐内容
相关内容
栏目更新
栏目热门