如何编写Makefile(6)-使用函数(二)

目录

一、foreach函数

二、if函数

三、call函数

四、origin函数

五、shell函数

六、控制make的函数


        我们继续Makefile函数使用的学习,上一节可查看:↓传送门↓

如何编写Makefile(6)-使用函数(一)-CSDN博客icon-default.png?t=O83Ahttps://blog.csdn.net/L_peanut/article/details/144341412?spm=1001.2014.3001.5501

一、foreach函数

        foreach函数和其它函数不同,这个函数是用来做循环使用的,Makefile中的foreach函数几乎是按照Unix标准Shell的for语句或者是C-Shell中的foreach语句构建的,语法是:

$(foreach <var>,<list>,<text>)

        意义是将参数<list>中的单词逐一取出放到参数<var>所指定的变量中,然后再执行<text>所包含的表达式。每一次<text>会返回一个字符串,循环过程中,<text>的所返回的每个字符串会以空格分隔,最后当整个循环结束时,<text>所返回的每个字符串所组成的整个字符串就是foreach函数的返回值。

        所以<var>最好是一个变量名,<list>可以是一个表达式,<text>中一般会使用<var>这个参数来依次枚举<list>中的单词,如:

names:=a b c d
files:=$(foreach n,$(names),$(n).o)

        例中,$(names)中的单词被依次取出,并存到变量n中,$(n).o每次依据$(n)计算出一个值,这些值以空格分隔,最后作为foreach函数的返回。所以,$(files)的值是a.o b.o c.o d.o。

        foreach中的<var>参数是一个临时的局部变量,foreach函数执行完成后,参数<var>的变量将不再作用,作用域只在foreach函数当中。

二、if函数

        if函数类似于GNU的make所支持的条件语句--ifeq,if函数的语法是:

$(if <condition>,<then-part>)

或者

$(if <condition>,<then-part>,<else-part>)

        可见if函数还可以包含“else”部分,或者不包含。if函数的参数可以是两个,也可以是三个。<condition>参数是if的表达式,如果其返回的为非空字符串,那么这个表达式就相当于返回真,于是<then-part>会被计算,否则<else-part>会被计算。

        if函数的返回值是,如果<condition>为真(非空字符串),那么<then-part>会是这个函数的返回值,如果<condition>为假(空字符串),那么<else-part>会是整个函数的返回值。此时如果<else-part>没有被定义,那么整个函数返回空字串。

        所以<then-part>和<else-part>只有一个会被计算。

三、call函数

        call函数是唯一一个可以用来创建新的参数化的函数,语法是:

$(call <expression>,<parm1>,<parm2>,...,<parmn>)

        当make执行这个函数时,<expression>参数中的变量,如$(1)、$(2)等,会被参数<parm1>、<parm2>……<parmn>依次取代,而<expression>的返回值就是call函数的返回值。例如:

reverse=$(1) $(2)

foo=$(call reverse,a,b)

        foo的值就是a b。参数的次序是可以自定义的,不一定是顺序的,如:

reverse=$(2) $(1)

foo=$(call reverse,a,b)

        此时foo的值是b a。

        在向call函数传递参数时要注意空格的使用,call函数在处理参数时,第2个及其之后的参数中的空格会被保留,可能会造成奇怪的结果,所以在向call函数提供参数时,最安全的做法是去除所有多余的空格。

四、origin函数

        origin函数不操作变量,其作用是告诉你这个变量的来源,语法如下:

$(origin <variable>)

        这里的<variable>是变量名字,不应该是引用。所以最好不要在<variable>中使用$字符。

        下面是origin函数的返回值:

①undefined

        如果<variable>从来没有定义过,origin函数返回这个值undefined。

②default

        如果<variable>是一个默认的定义,比如“CC”这个变量。

③environment

        如果<variable>是一个环境变量,并且当Makefile被执行时,-e参数没有被打开。

④file

        如果<variable>这个变量被定义在Makefile中。

⑤command line

        如果<variable>这个变量是被命令行定义的。

⑥override

        如果<variable>是被override指示符重新定义的。

⑦automatic

        如果<variable>是一个命令行运行中的自动化变量。

        这些信息对我们编写Makefile是非常有用的,假设我们有一个Makefile,其包含了一个定义文件Make.def,在Make.def中定义了一个变量“bletch”,而我们的环境中也有一个环境变量“bletch”,此时我们需要判断一下,如果变量来源于环境,这样做将会重新定义这个变量。如果来源于Make.def或者是命令行等非环境的,我们就不会重新定义。于是我们在Makefile中可以这样写:

ifdef bletch
    ifeq "$(origin bletch)" "environment"
        bletch = barf, gag, etc.
    endif
endif

五、shell函数

        shell函数的参数是操作系统Shell的命令,它和反引号“ ‘ ”是相同的功能。shell函数把执行操作系统命令后的输出作为函数返回。我们可以用操作系统命令以及字符串处理命令awk、sed等命令来生成一个变量,如:

contents:=$(shell cat foo)
files:=$(shell echo *.c)

        这个函数会新生成一个Shell程序来执行命令,如果你的Makefile中有一些比较复杂的规则,并且大量使用了这个函数,这样做对系统性能影响很大。尤其是Makefile的隐晦规则可能会让你的shell函数执行的次数比你想象的多很多。

六、控制make的函数

        make提供了一些函数来控制make的运行,通常你需要检测一些运行Makefile时的运行时信息,并且根据这些信息来决定make继续执行还是停止。

$(error <text...>)

        产生一个致命错误,<text...>是错误信息,error函数不会在被使用时就立即产生错误信息,所以如果将其定义在某个变量中,并在后续的脚本中使用这个变量,也是可以的。例如:

#例1

ifdef ERROR_001
    $(error error is $(ERROR_001))
endif
#例2

ERR=$(error found an error!)

.PHONY: err
    err:$(ERR)

        例1会在变量ERROR_001定义之后执行时产生error调用,例2在目录err被执行时才发生error调用。

$(warning <text...>)

        这个函数与error类似,只是它不会让make退出,只是输出一段警告信息,而make继续执行。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

猿核试Bug愁

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值