make函数¶
makefile 有系统提供的库函数,却本质上不支持自定义函数,但可以使用 define
定义具有类似函数特性的多行变量。
1 函数调用¶
- 函数调用语法形式
$(<function> <arguments>)
${<function> <arguments>}
OBJ=$(subst ee,EE,feet on the street)
all:
@echo $(OBJ)
上例中表示将 feet on the street
字符串中 ee
字符串替换为 EE
,echo 输出结果为 fEEt on the strEEt
。
2 define 自定义函数、call 调用自定义函数¶
使用 define
定义多行变量,具有函数特性,但与库函数调用还是有区别的,且需要通过 call
函数来调用
define func1
@echo "My name is $(0)"
endef
var := $(call func1)
3 库函数-字符串处理¶
- 函数调用形式:
$(fun par1,par2,..parN)
, 参数间由逗号分隔 详见参考资料
3.1 subst 字符串替换函数¶
- 语法形式:
$(subst <from>,<to>,<text>)
- 功能:把字串
<text>
中的<from>
字符串替换成<to>
。 - 返回:函数返回被替换过后的字符串
- 示例
## 将feet on the street中的ee替换成EE
$(subst ee,EE,feet on the street)
## return:fEEt on the strEEt
3.2 patsubst 模式字符串替换函数¶
- 语法形式:
$(patsubst <pattern>,<replacement>,<text>)
- 功能:查找
<text>
中的单词(单词以“空格”、“Tab”或“回车”“换行”分隔)匹配 pattern 部分替换成 replacement 部分 - 返回:函数返回被替换过后的字符串
- 示例
## 将x.c.c bar.c中以.c结尾部分替换成以.o结尾
$(patsubst %.c,%.o,x.c.c bar.c)
## return: x.c.o bar.o
3.3 strip 去掉开头结尾空格¶
- 语法形式:
$(strip <string>)
- 功能:去掉
<string>
字串中开头和结尾的空字符。 - 返回:返回被去掉空格的字符串值
- 示例
str1=" abc "
str2=$(strip $(str1))
## str1 != str2,因为str2没有首尾空格字符
3.4 findstring 查找字符串¶
- 语法形式:
$(findstring <find>,<in>)
- 功能:在字串
<in>
中查找<find>
字串 - 返回:如果找到,那么返回
<find>
,否则返回空字符串 - 示例
## 在a b c中查找a
$(findstring a,a b c)
## return:a
## 在b c中查找a,由于找不到,返回空
$(findstring a,b c)
## return:空字符串
3.5 filter 过滤字符串¶
- 语法形式:
$(filter <pattern...>,<text>)
- 功能:以
<pattern>
模式过滤<text>
字符串中的单词,保留符合模式<pattern>
的单词。可以有多个模式。 - 返回:返回符合模式
<pattern>
的字串。 - 示例
## 过滤以.c和.s结尾的字符串
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
3.6 filter-out 反过滤字符串¶
与 filter 过滤作用相反
- 语法形式:$(filter-out <pattern...>,<text>)
- 功能:以 <pattern>
模式过滤 <text>
字符串中的单词,去除符合模式 <pattern>
的单词。可以有多个模式。
- 返回:返回不符合模式 <pattern>
的字串。
- 示例
## 过滤掉匹配项
objects=main1.o foo.o main2.o bar.o
mains=main1.o main2.o
$(filter-out $(mains),$(objects))
## return foo.o bar.o
3.7 sort 按升序排序并排重¶
- 语法形式:
$(sort <list>)
- 功能:给字符串
<list>
中的单词排序(升序) - 返回:返回排序后的字符串
- 示例:$(sort foo bar lose) 返回 bar foo lose
- 备注:sort 函数会去掉
<list>
中相同的单词 - 示例
## 按升序排序并排重
$(sort foo bar lose foo)
## return bar foo lose
3.8 word 取字符串中某个单词¶
- 语法形式:
$(word <n>,<text>)
- 功能:取字符串
<text>
中第<n>
个单词。(从一开始) - 返回:返回字符串
<text>
中第<n>
个单词。如果<n>
比<text>
中的单词数要大,那么返回空字符串 - 备注:单词间是以空格或 tab 分割的
- 示例
## 获取foo bar baz中第2个单词bar
$(word 2, foo bar baz)
## return bar
3.9 wordlist 取字符串中区间单词列表¶
- 语法形式:
$(wordlist <start>,<end>,<text>)
- 功能:从字符串
<text>
中取从<start>
开始到<end>
的单词串。<start>
和<end>
是一个数字。 - 返回:返回字符串
<text>
中从<start>
到<end>
的单词字串。如果<start>
比<text>
中的单词数要大,那么返回空字符串。如果<end>
大于<text>
的单词数,那么返回从<start>
开始,到<text>
结束的单词串。 - 示例
## 获取foo bar lose中第2个到第3个单词bar baz
$(wordlist 2,3, foo bar baz)
## return bar baz
3.10 words 统计单词个数¶
- 语法形式:
$(words <text>)
- 功能:统计
<text>
中字符串中的单词个数。 - 返回:返回
<text>
中的单词数。 - 示例
## 统计单词数
$(words, foo bar baz)
## return 3
## 获取foo bar baz 中最后一个单词
$(word $(words foo bar baz),foo bar baz )
## return baz
3.11 lastword 取尾单词¶
- 语法形式:
$(lastword <text>)
- 功能:取字符串
<text>
中的最后一个单词。 - 返回:返回字符串
<text>
的最后一个单词。 - 示例
$(lastword, foo bar baz)
## return baz
3.12 firstword 取首单词¶
- 语法形式:
$(firstword <text>)
- 功能:取字符串
<text>
中的第一个单词。 - 返回:返回字符串
<text>
的第一个单词。 - 示例
$(firstword, foo bar baz)
## return foo
4 库函数-文件处理¶
4.1 dir 获取文件目录部分¶
- 语法形式:
$(dir <names...>)
- 功能:从文件名序列
<names>
中取出目录部分。目录部分是指最后一个反斜杠(/)之前的部分。如果没有反斜杠,那么返回 ./ 。 - 返回:返回文件名序列
<names>
的目录部分。 - 示例:
$(dir src/foo.c hacks)
## return src/ ./
4.2 notdir 获取文件名(非目录部分)¶
- 语法形式:
$(notdir <names...>)
- 功能:从文件名序列
<names>
中取出非目录部分。非目录部分是指最後一个反斜杠(/ )之后的部分。 - 返回:返回文件名序列
<names>
的非目录部分。 - 示例:
$(notdir src/foo.c hacks)
## return foo.c hacks
4.3 suffix 取文件扩展名¶
- 语法形式:
$(suffix <names...>)
- 功能:从文件名序列
<names>
中取出各个文件名的后缀。 - 返回:返回文件名序列
<names>
的后缀序列,如果文件没有后缀,则返回空字串,后缀是以最后一个. 之后的内容。 - 示例:
## 返回后缀.d而不是.c.d
$(notdir src/foo.c.d hacks)
## return .d
4.4 basename 取文件名前缀(包含目录部分)¶
- 语法形式:
$(basename <names...>)
- 功能:从文件名序列
<names>
中取出各个文件名的前缀部分。 - 返回:返回文件名序列
<names>
的前缀序列,如果文件没有前缀,则返回空字串 - 示例:
## 返回前缀src/foo.c hacks
$(notdir src/foo.c.d hacks)
## return src/foo.c hacks
4.5 addsuffix 添加文件后缀¶
- 语法形式:
$(addsuffix <suffix>,<names...>)
- 功能:后缀
<suffix>
加到<names>
中的每个单词后面。 - 返回:返回加过后缀的文件名序列。
- 示例:
$(addsuffix .c,foo bar)
## return foo.c bar.c
4.6 addprefix 添加文件前缀¶
- 语法形式:
$(addprefix <prefix>,<names...>)
- 功能:把前缀
<prefix>
加到<names>
中的每个单词后面。 - 返回:返回加过前缀的文件名序列。
- 示例:
$(addprefix src/,foo bar)
## return src/foo src/bar
4.7 join 拼接¶
- 语法形式:
$(join <list1>,<list2>)
- 功能:把
<list2>
中的单词对应地加到<list1>
的单词后面。如果<list1>
的单词个数要比<list2>
的多,那么,<list1>
中的多出来的单词将保持原样。如果<list2>
的单词个数要比<list1>
多,那么,<list2>
多出来的单词将被复制到<list1>
中。 - 返回:返回连接过后的字符串。
- 示例:
$(join a b,.c .o)
## return a.c b.o
## .i被输出
$(join a b,.c .o .i)
## return a.c b.o .i
## c原样输出
$(join a b c,.c .o)
## return a.c b.o c
4.8 wildcard 匹配通配符¶
- 语法形式:
$(wildcard pattern…)
- 功能:pattern 模糊匹配文件名,如
*.c
, 表示当前路径下所有 c 头文件文件 - 返回:返回所有匹配的文件名。
- 示例:
## wildcard返回当前目录下所有以.c的文件名,patsubst再将其替换以.o结尾的文件名
$(patsubst %.c,%.o,$(wildcard *.c))
4.9 realpath 返回文件的绝对路径¶
- 语法形式:
$(realpath names...)
- 功能:返回文件的绝对路径,绝对路径是不含. .. 等符号的文件路径,如果文件路径不存在,则返回空
- 返回:返回文件的相对路径
- 示例:
## 假设当前makefile在 /home/xx/test目录下
$(realpath ./)
## result /home/xx/test
4.10 abspath 返回文件的绝对路径¶
- 语法形式:
$(realpath names...)
- 功能:返回文件的绝对路径,绝对路径是不含. .. 等符号的文件路径,如果文件路径不存在,也会返回绝对路径,这是与 realpath 的区别
- 返回:返回文件的绝对路径
- 示例:
## 假设当前makefile在 /home/xx/test目录下
$(abspath ./)
## result /home/xx/test
5 条件函数¶
5.1 if¶
- 语法形式:
$(if condition,then-part[,else-part])
- 功能:如果 condition 是一个非空字符(即条件未真),执行 then-part 部分,否则执行 else-part 部分
- 返回:不返回数据,只执行条件对应的操作
- 示例:
## 由于var非空,条件为真,执行echo "true"
var:=1
all:
$(if $(var),echo "true",echo "false")
## result 执行echo "true"
5.2 or¶
- 语法形式:
$(or condition1[,condition2[,condition3…]])
- 功能:判断是否有一个条件为真
- 返回:从左往右判断条件是否为真,当有一个条件为真时,返回这个条件真的字符串;当所有条件都为假时,返回空字符
- 示例:
## 由于var非空,条件为真,执行echo "true"
## var1空字符,var2非空,返回第一个真的条件var2
var1:=
var2:=2
var3:=3
$(or $(var1),$(var2),$(var3))
## result 2
5.3 and¶
- 语法形式:
$(and condition1[,condition2[,condition3…]])
- 功能:判断所有条件是否为真
- 返回:从左往右判断条件是否为真,当有所有条件为真时,最后一个条件真的字符串;当有一个条件为假时,返回空字符
- 示例:
## 由于var非空,条件为真,执行echo "true"
## var1空字符,var2非空,返回第一个假的条件var1
var1:=
var2:=2
var3:=3
$(or $(var1),$(var2),$(var3))
## result 空字符
6 foreach¶
- 语法形式:
$(foreach var,list,text)
- 功能:遍历 list,放入 var 中,再执行 text 并返回
- 返回:返回 test 内容
- 示例:
dirs := a b c d
files := $(foreach dir,$(dirs),$(wildcard $(dir)/*))
#等价于
files := $(wildcard a/* b/* c/* d/*)
7 file 读写文件¶
- 语法形式:
$(file op filename[,text])
- 功能:读写文件
$(file > filename [test])
覆盖写$(file >> filename [test])
追加写$(file < filename)
读取文件,并返回文件内容- 返回:当都文件时,返回文件内容,写文件,返回空
- 示例:
program: $(OBJECTS)
$(file >$@.in,$^)
8 call 调用参数化函数 (自定义函数)¶
- 语法形式:
$(value variable)
- 功能:调用参数化函数,param 会被函数中 $(1)、$ (2)...$(n) 接收
- 返回:返回什么取决于 variable 所对应的参数化函数
- 示例:
## 交换参数值
reverse = $(2) $(1)
foo = $(call reverse,a,b)
## result foo=b a
9 value 取变量值¶
- 语法形式:
$(value variable)
- 功能:当 variable 也是引用一个变量时,$(variable) 不能正确得到结果,但 value 函数能避免这个问题
- 返回:返回 variable 引用的值
- 示例:第一个 echo 会把$P 当作变量,从而生成 ATH,第二个 echo 才能正确解析到环境变量值
FOO = $PATH
all:
@echo $(FOO)
@echo $(value FOO)
10 eval¶
- 参考
- 语法形式:
$(eval $(call ...))
- 功能:eval 通常用于当 call 一个自定义函数时,这个函数里是生成 makefile 代码,这时执行 eval,这段 makefile 代码才能生效。
- 返回:返回值是空
- 示例:
## eval将PROGRAM_template中定义的
PROGRAMS = server client
server_OBJS = server.o server_priv.o server_access.o
server_LIBS = priv protocol
client_OBJS = client.o client_api.o client_mem.o
client_LIBS = protocol
## Everything after this is generic
.PHONY: all
all: $(PROGRAMS)
define PROGRAM_template =
$(1): $$($(1)_OBJS) $$($(1)_LIBS:%=-l%)
ALL_OBJS += $$($(1)_OBJS)
endef
$(foreach prog,$(PROGRAMS),$(eval $(call PROGRAM_template,$(prog))))
$(PROGRAMS):
$(LINK.o) $^ $(LDLIBS) -o $@
clean:
rm -f $(ALL_OBJS) $(PROGRAMS)
11 orign 显示变量来源¶
- 语法形式:
$(origin variable)
- 功能:显示指定变量的来源,是否是环境变量,还是 makefie 定义的,还是未定义的等等
- 返回:返回值是变量来源,有以下几种
undefined
:没有定义的变量default
:默认定义的变量,比如 CC 定义成 cc,AR 定义成 arenvironment
:来自系统环境变量environment override
:来自系统环境变量,且 make 时带有-e 参数file
:makefile 定义的变量,包括如 MAKEFILE_LIST 这类变量command line
:命令行传过来的变量,比如执行make TEST=123
,TEST 就是这个override
:变量被 override 修饰的automatic
:自动化变量,如$@、$<
- 示例:
FOO=123
override AA=123
all:
echo $(origin @)
echo $(origin AA)
echo $(origin FOO)
echo $(origin MAKEFILE_LIST)
echo $(origin TEST)
echo $(value FOO)
echo $(origin PATH)
echo $(origin CC)
- 结果
## 执行make
$ make
echo automatic
automatic
echo override
override
echo file
file
echo file
file
echo undefined
undefined
echo 123
123
echo environment
environment
echo default
default
12 flavor 显示变量简单信息¶
- 语法形式:
$(flavor variable)
- 功能:显示指定变量是否定义,是否是重复扩展类型(=或 define 定义的变量),简单扩展类型(由:=定义的)
- 返回:返回值是变量来源,有以下几种
undefined
:没有定义的变量recursive
:由=
或define
定义的变量simple
:由:=定义的变量- 示例:
bar = $(ugh)
ugh := Huh?
FOO=123
override AA=123
all:
echo $(flavor bar)
echo $(flavor ugh)
echo $(flavor xxx)
- 结果
## 执行make
$ make
echo recursive
recursive
echo simple
simple
echo undefined
undefined
13 提示类型函数¶
13.1 error¶
- 语法形式:
$(error text...)
- 功能:终止 makefile 执行,打印 text
- 返回:返回值为空
- 示例:
ifdef ERROR1
$(error error is $(ERROR1))
endif
13.2 warning¶
- 语法形式:
$(warning text...)
- 功能:不终止 makefile 执行,但打印 text 到标准输出
- 返回:返回值为空
- 示例:
all:
$(warning warning...)
13.3 info¶
- 语法形式:
$(info text...)
- 功能:打印 text 到标准输出
- 返回:返回值为空
- 示例:
all:
$(info info...)
14 shell 函数执行 shell 指令¶
- 语法形式:
$(shell shell-command)
- 功能:执行 shell-command
- 返回:返回值是执行 shell 指令后得到的值
- 示例:
## 将foo文件内容赋给contents变量
contents := $(shell cat foo)