makefile函数

函数

GNUmake支持内置函数和用户自定义函数。函数调用看起来像是变量引用,只不过多了用逗号隔开的参数而已。所有的函数都具有相同的形式:$(function-namearg1[, argn])$之后是函数的名称,接着是函数的参数,参数之间以逗号隔开。

内置函数

内置函数是内嵌于make程序内的函数,可以直接使用。

字符串函数
  • $(filterpattern ..., text)

filter函数将text视为一系列以空格隔开的单词,与pattern比较之后,返回符合的单词(模式必须与单词相匹配,而不能只匹配一部分)。模式可以有多个,只要符合其中一个就会被匹配。模式中采用%作为通配符,当有多个%出现在一个模式中,只有第一个作为通配符,其他的作为字面值。

  • $(filter-outpattern ..., text)

filter-out函数刚好与filter相反,用来选出与模式不相符的每个单词

text = apple pear banana watermelon orange pineapple
filtered = $(filter %apple pear %ge,$(text))
not_filtered = $(filter-out %apple pear %.ge, $(text))

all :
    @echo $(filtered)
    @echo $(not_filtered)

$ make
apple pear orange pineapple
banana watermelon orange
  • $(findstringstring...,text)

此函数将会从text里搜索string。如果找到了就返回该字符串,否则返回空string没有模式匹配功能。

  • $(subst search-string,replace-string,text)

这是一个不具有模式匹配的搜索替换函数search-stringreplace-string不必是整个单词。

  • $(patsubst search-string,replace-string,text)

这个替换函数具有模式匹配功能。同样的,只能用一个%

sources = hello.c lib.c main.c tom_hello.c tom_lib.c
objects = $(subst .c,.o, $(sources))
has_main.c = $(findstring main.c, $(sources))
has_main = $(findstring main, $(sources))
no_domain = $(findstring domain, $(sources))
patsubsted = $(patsubst tom%,jerry%, $(sources))

all:
    @echo $(objects)
    @echo $(has_main.c)
    @echo $(has_main)
    @echo $(no_domain)
    @echo $(patsubsted)

$ make
hello.o lib.o main.o tom_hello.o tom_lib.o
main.c
main

hello.c lib.c main.c jerry_hello.c jerry_lib.c
  • $(wordstext)

此函数返回text中单词的数量。

  • $(wordn,text)

此函数返回text中的第n个单词。第一个单词编号为1,如果n的值大于单词的总数,返回空值。

  • $(firstwordtext)

返回text中的第一个单词。等效与$(word 1,text)

  • $(wordlist start,end,text)

此函数返回text中范围从start(含)到end(含)的单词。

  • $(sort list)

sort函数会排序它的list参数并且移除重复的单词。此函数会返回按照字典顺序的不重复的单词列表,以空格分隔。而且,sort还会删除前导和结尾的空格。这里的sortmake内部实现的函数,不是shell里的程序。

  • $(shellcommand)

shell的参数会被扩展(就像所有其他参数)并且传递给subshell执行。然后make读取command的标准输出,并将之作为函数的返回值。输出中所出现的一系列换行符会被缩减成单一的空格,任何末尾的换行被删除。标准错误并不会被返回。

  • $(wildcardpattern...)

wildcard的参数是一个模式列表,他会对每个模式进行扩展。如果扩展的模式找不到符合的文件,返回空字符串。该模式为shell的glob匹配
如果想要判断某个文件是否存在,就可以使用wildcard
dot-emacs-exists := $(wildcard ~/.emacs)

  • $(dirlist...)

dir函数返回list中每个单词的目录部分。

  • $(notdirname...)

返回每个单词的文件名部分。

  • $(suffixname...)

返回由每个单词的扩展名构成的单词列表

  • $(basenamename...)

返回由每个单词的非扩展名部分组成的单词列表

  • $(addsuffix, suffix,name...)

返回由name单词列表中的每个单词前加上suffix前缀构成的新的单词表。

  • $(addprefix,prefix,name...)

  • $(joinprefix-list,suffix-list)

join函数把prefix-list的第i个单词与suffix-list的第i个单词连在一起构成新序列的第i个单词。

流程控制函数
  • $(ifcondition,then-part,else-part)

if函数(可不是条件指令ifne,ifeq,ifdef等)会根据条件表达式的求值结果,从两个宏中选择一个进行扩展。
如果condition扩展之后包含任何字符(包括空格),求值结果为真,会对then-part进行扩展;否则,如果condition扩展之后为空,会对else-part进行扩展。
makecondition求值时,首先会移除前导及末尾的空格。

  • $(errortext)

error函数会使make输出text错误信息和当前makefile的名称行号之后以2这个状态结束运行。

  • $(warntext)
    error类似,输出text的内容,但并不退出。扩展结果为空串。

  • $(foreach variable,list,body)
    foreach函数执行的时候,它将list中的每个单词作为body中的variable进行操作,返回操作的结果。

sources = fat32.c format.c alloca.c main.c
dirs = src bin inc
objects = $(foreach var,$(sources), $(subst .c,.o, $(var)))
full_path = $(foreach var, $(sources), $(addprefix src/, $(var)))
do_mkdirs = $(foreach var, $(dirs), $(shell mkdir -p $(var)))

all:
    @echo $(objects)
    @echo $(full_path)
    @echo $(do_mkdirs)

$ make
fat32.o format.o alloca.o main.o
src/fat32.c src/format.c src/alloca.c src/main.c
                #产生了三个文件夹
eval函数
  • $(evalcontents)

这个函数很重要。它用来将它后面的文本直接放入make解析器。

首先make会扫描eval的参数并对其中的变量进行扩展,然后make会解析文本进行求值的动作(这里也包含了一次扩展动作,因为普通的在makefile中的文本也会扩展一次),就好像它是输入的文本一样。

eval函数经常用与含有多行文本的宏的展开。一个解析器顶层的宏被扩展成多行文本是不合法的,但是用eval函数可以将展开后的宏直接当做输入的文本,再展开一次之后就放入数据库中了。而eval函数本身的展开结果为空。

注意:定义复杂的宏时要考虑二次展开的问题,然后用eval函数引用这个宏。

用户自定义函数

可以用define定义一个自定义的宏:

define macor-name
    contents
endef

用户自定义函数是带有参数的宏,宏定义中的$1$2...是函数的形参,宏的定义就是函数的定义。

调用一个自定义函数的形式是:

  • $(callmacro-name[,param1 ...])

call是一个内置函数,call扩展它的第一个参数并把其他参数依次替换到宏定义中的$1$2...的地方。macro-name之后是宏的参数,以逗号隔开。在函数的内部可以使用$0来访问函数名。

call的参数传递机制很简单。调用时可以为call指定任意个参数。如果宏定义内引用了$n,但是调用时并未指定相应的参数,那么该变量就为空值。如果call的参数比宏的$n引用还多,则被忽略。

注意使用函数是不要随意加前导空格,否则可能回产生难以排查的错误。(但降低了可读性)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值