说明
本来这一篇应该记录书写命令或者变量的使用或者条件判断,但是我打算把这几个先跳过并可能留到下次一起写,因为这两天趁课余时间把整本《跟我一起写Makefile》过了一遍,需要一点时间消化,因此挑选了比较简单的函数这一部分来写,当然,书写命令和条件判断也很简单,所以跟变量一起写,写这篇最主要是像列举函数用法,作为自己以后查阅的一处笔记。
函数
makefile中的函数调用跟普通的编程语言一样有很明显易懂的规则,而且跟本身的变量调用很像,由美元符号$、函数名、参数、圆括号或花括号组成,函数名与参数之间用空格间隔,参数之间用逗号间隔,举例:
$(func1 arg1,arg2)
${func2 arg1,arg2}
作者建议函数调用的括号和变量调用的括号保持一致以便阅读。
函数的介绍部分就到这里,接下来是函数列举
函数列举
字符串处理
subst-字符串替换
语法:
$(subst <from>,<to>,<text>)
功能:把字符串text中的from替换成to
返回:替换完成的字符串
patsubst-模式字符串替换
语法:
$(patsubst <pattern>,<replacement>,<text>)
功能:见名知意,在函数名前加了pat(pattern)。查找text中的单词匹配pattern的部分,并用replacement替换,若 replacement包含pattern中的模式变量通配符如%,则二者内容对应,替换时保持不变,如pattern=%.c而replacement=%.o则替换前后%位置内容不变。
返回:替换完成的字符串
strip-去前后空格
语法:
$(strip <text>)
功能:去除text前后的空格
返回:去除前后空格的字符串
findstring-查找字符串
语法:
$(findstring <find>,<in-text>)
功能:在in-text中查找find
返回:若找到,返回<find>(没错是返回这个find,而不是找到位置或者true),否则返回空字符串
filter-过滤
$(filter <pattern...>,<text>)
功能:以pattern模式过滤text中的单词,保留符合模式的单词,可以有多个模式
返回:符合模式的单词组成的字符串
filter-out-反过滤
语法:
$(filter-out <pattern...>,<text>)
功能:跟filter同理,但是保留不符合模式的单词
返回:不符合模式的单词组成的字符串
sort-排序
语法:
$(sort <word-list-string>)
功能:给word-list-string字符串中的单词按照首字母顺序升序排序,并去除重复单词
返回:排序后的字符串
word-取单词
语法:
$(word <n>,<text>)
功能:取字符串text中第n个单词(从1开始)
返回:若n小于text中单词的计数,返回取出的单词,否则返回空字符串
wordlist-取单词串
语法:
$(wordlist <start>,<end>,<text>)
功能:取字符串text中第start到end个单词
返回:记text中单词数量为n。若start<end<n,返回text中第start到end个单词组成的新字符串;若start<=n<=end,返回start到最后一个单词组成的新字符串;若start>n,返回空字符串
words-统计单词个数
语法:
$(words <text>)
功能:统计字符串text中一共有多少个单词
返回:text中的单词数
firstword-取首单词
语法:
$(firstword <text>)
功能:取字符串text中的第一个单词
返回:若text中有单词,返回第一个单词,否则返回空字符串
文件名操作
dir-取目录
语法:
$(dir <file-path...>)
功能:从file-path列表中取出每个文件名的文件夹部分(目录部分)
返回:返回以每个文件目录部分为新单词组成的新字符串,若文件没有目录部分,返回“./”。
示例:
run:
$(dir dir1/dir2/file1 file2)
return:
dir1/dir2/ ./
notdir-取文件
语法:
$(notdir <file-path...>)
功能:从file-path列表中取出每个文件名的文件部分
返回:返回以每个文件的文件本体部分为新单词组成的新字符串
示例:
run:
$(notdir dir1/dir2/file1 file2)
return:
file1 file2
suffix-取后缀
语法:
$(suffix <file-path...>)
功能:从file-path列表中取出每个文件名的文件后缀
返回:返回以每个文件的后缀为新单词组成的新字符串,若文件没有后缀则返回空字符串
示例:
run:
$(suffix dir1/dir2/file1.c file2.d file3)
return:
.c .d
basename-取前缀
语法:
$(basename <file-path...>)
功能:从file-path列表中取出每个文件名的文件前缀,即后缀前所有内容
返回:返回以每个文件的前缀为新单词组成的新字符串,若文件没有前缀则返回空字符串
示例:
run:
$(basename dir1/dir2/file1.c file2.d file3)
return:
dir1/dir2/file1 file2 file3
addsuffix-加后缀/addprefix-加前缀
语法:
$(addsuffix <suffix>,<file-path...>)
$(addprefix <prefix>,<file-path...>)
功能:把后缀/前缀加到file-path中每个单词的后面/前面
返回:添加完后/前缀的文件名序列
join-连接
语法:
$(join <word-list1>,<word-list2>)
功能:把word-list2中的单词按顺序拼接到word-list1中每个单词的后面,如果list2单词更多则多的单词单独存在
返回:拼接过后的字符串
示例:
run:
$(join aaa bbb ccc,111 222)
return:
aaa111 bbb222 ccc
run:
$(join aaa bbb,111 222 333)
return:
aaa111 bbb222 333
foreach函数
foreach函数与makefile支持的其他函数很不一样,但是跟编程语言的foreach函数非常相似。语法如下:
$(foreach <var>,<list>,<expression>)
它可用于做一些循环操作。其中var是每次循环按顺序从list中取出的单词,并且每次循环都会执行一次expression中的内容,最终当循环结束时返回每次执行expression之后得到的字符串按顺序拼接成的字符串。
示例:
list := a b c d
files := $(foreach n,$(list),$(n).o)
------------------------------------
return:
a.o b.o c.o
注意,var变量的作用域只在foreach函数中,这一点与编程语言一致。
if函数
同样,这个函数跟一般编程语言中的if语句非常相似,语法:
$(if <condition>,<then-part>,<else-part>)
其中else-part可以省略不写,代表如果不满足条件则不执行操作,默认返回空字符串。函数根据condition中的内容展开后是否为空字符串判断该返回then-part(非空)还是else-part(为空)。
call函数
call函数允许你自定义一个表达式并调用它,这点跟编程语言的自定义函数很像,这个表达式同样允许自定义参数。
语法:
$(call <expression>,<para1>,<para2>,...)
expression即自定义的表达式,para1等为参数。在定义表达式时可以用变量如$(1), $(2)来表示第1、2个接受的参数。
示例:
reverse = $(2) $(1)
foo = $(call reverse,a,b)
------------------------------------
foo = b a
origin函数
语法:
$(origin <variable>)
origin函数的功能比较特殊,它只会返回给定变量variable是从哪里来的,其可能的返回值和代表的意义我从书中搬运过来如下:
undefined
如果variable从来没有定义过,origin函数返回这个值undefined
default
如果variable是一个默认的定义,比如“CC”这个变量,这种变量我们将在后面讲述。
environment
如果variable是一个环境变量,并且当Makefile被执行时,-e参数没有被打开。
file
如果variable这个变量被定义在Makefile中。
command line
如果variable这个变量是被命令行定义的。
override
如果variable是被override指示符重新定义的。
automatic
如果variable是一个命令运行中的自动化变量。
shell函数
shell函数非常简单,就是运行操作系统的shell命令并将命令返回值作为函数返回值返回,语法:
$(shell <shell-script>)
注意,调用这个函数会生成一个新的shell程序以执行命令,因此需要考虑运行性能问题,尤其是当makefile中有比较复杂的规则且多次运用这个函数的时候。
控制make的函数
make提供了一些函数来控制make的运行。error函数和warning函数,语法如下:
$(error <text ...>)
$(warning <text ...>)
其中error函数会输出错误提示text并停止make的运行,而warning函数只输出警告信息,不会停止make执行
注意事项
注意到makefile中的参数、变量等与空格的适配不像普通编程语言那样好,比如在call函数中传参时第二个及之后的参数单词后的空格也会被视作参数的一部分,因此建议在确实没有传入空格作为参数一部分的需求时,调用函数时除了函数名和第一个参数之间的空格外不要轻易用空格。