• Makefile编写规则(四)常用函数


    Makefile编写规则(四)常用函数

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

    $(<function> <arguments>)    或者是     ${<function> <arguments>}
    

    字符串处理函数

    1. 模式字符串替换函数,函数使用格式如下:

    $(patsubst <pattern>,<replacement>,<text>)
    

    函数说明:函数功能是查找 text 中的单词是否符合模式 pattern,如果匹配的话,则用 replacement 替换。返回值为替换后的新字符串。实例:

    OBJ=$(patsubst %.c,%.o,1.c 2.c 3.c)
    all:
        @echo $(OBJ)

    执行 make 命令,我们可以得到的值是 "1.o 2.o 3.o",这些都是替换后的值。

    2. 字符串替换函数,函数使用格式如下:

    $(subst <from>,<to>,<text>)
    

    函数说明:函数的功能是把字符串中的 form 替换成 to,返回值为替换后的新字符串。实例:

    OBJ=$(subst ee,EE,feet on the street)
    all:
        @echo $(OBJ)

    执行 make 命令,我们得到的值是“fEEt on the strEEt”。

    3. 去空格函数,函数使用格式如下:

    $(strip <string>)
    

    函数说明:函数的功能是去掉字符串的开头和结尾的字符串,并且将其中的多个连续的空格合并成为一个空格。返回值为去掉空格后的字符串。实例:

    OBJ=$(strip    a       b c)
    all:
        @echo $(OBJ)

    执行完 make 之后,结果是“a b c”。这个只是除去开头和结尾的空格字符,并且将字符串中的空格合并成为一个空格。

    4. 查找字符串函数,函数使用格式如下:

    $(findstring <find>,<in>)
    

    函数说明:函数的功能是查找  in 中的 find ,如果我们查找的目标字符串存在。返回值为目标字符串,如果不存在就返回空。实例:

    OBJ=$(findstring a,a b c)
    all:
        @echo $(OBJ)

    执行 make 命令,得到的返回的结果就是 "a"。

    5. 过滤函数,函数使用格式如下:

    $(filter <pattern>,<text>)
    

    函数说明:函数的功能是过滤出 text 中符合模式 pattern 的字符串,可以有多个 pattern 。返回值为过滤后的字符串。实例:

    OBJ=$(filter %.c %.o,1.c 2.o 3.s)
    all:
        @echo $(OBJ)

    执行 make 命令,我们得到的值是“1.c 2.o”

    6、反过滤函数,函数使用格式如下:

    $(filter-out <pattern>,<text>)
    

    函数说明:函数的功能是功能和 filter 函数正好相反,但是用法相同。去除符合模式  pattern 的字符串,保留符合的字符串。返回值是保留的字符串。实例:

    OBJ=$(filter-out 1.c 2.o ,1.o 2.c 3.s)
    all:
        @echo $(OBJ)

    执行 make 命令,打印的结果是“3.s”。

    7. 排序函数,函数使用格式如下:

    $(sort <list>)
    

    函数说明:函数的功能是将 <list>中的单词排序(升序)。返回值为排列后的字符串。sort会去除重复的字符串。实例:

    OBJ=$(sort foo bar foo lost)
    all:
        @echo $(OBJ)

    执行 make 命令,我们得到的值是“bar foo lost”

    8. 取单词函数,函数使用格式如下:

    $(word <n>,<text>)
    

    函数说明:函数的功能是取出函数<text>中的第n个单词。返回值为我们取出的第 n 个单词。实例:

    OBJ=$(word 2,1.c 2.c 3.c)
    all:
        @echo $(OBJ)

    执行 make 命令,我们得到的值是“2.c”。

    文件名操作函数

    1. 取目录函数,函数使用格式如下:

    $(dir <names>)
    

    函数说明:函数的功能是从文件名序列 names 中取出目录部分,如果没有 names 中没有 "/" ,取出的值为 "./" 。返回值为目录部分,指的是最后一个反斜杠之前的部分。如果没有反斜杠将返回“./”。实例:

    OBJ=$(dir src/foo.c hacks)
    all:
        @echo $(OBJ)

    执行 make 命令,我们可以得到的值是“src/ ./”。提取文件 foo.c 的路径是 "/src" 和文件 hacks 的路径 "./"。

    2. 取文件函数,函数使用格式如下:

    $(notdir <names>)
    

    函数说明:函数的功能是从文件名序列 names 中取出非目录的部分。非目录的部分是最后一个反斜杠之后的部分。返回值为文件非目录的部分。实例:

    OBJ=$(notdir src/foo.c hacks)
    all:
        @echo $(OBJ)

    执行 make 命令,我们可以得到的值是“foo.c hacks”。

    3. 取后缀名函数,函数使用格式如下:

    $(suffix <names>)
    

    函数说明:函数的功能是从文件名序列中 names 中取出各个文件的后缀名。返回值为文件名序列 names 中的后缀序列,如果文件没有后缀名,则返回空字符串。实例:

    OBJ=$(suffix src/foo.c hacks)
    all:
        @echo $(OBJ)

    执行 make 命令,我们得到的值是“.c ”。文件 "hacks" 没有后缀名,所以返回的是空值。

    4. 取前缀函数,函数使用格式如下:

    $(basename <names>)
    

    函数说明:函数的功能是从文件名序列 names 中取出各个文件名的前缀部分。返回值为被取出来的文件的前缀名,如果文件没有前缀名则返回空的字符串。实例:

    OBJ=$(notdir src/foo.c hacks)
    all:
        @echo $(OBJ)

    执行 make 命令,我们可以得到值是“src/foo hacks”。获取的是文件的前缀名,包含文件路径的部分。

    5. 添加后缀名函数,函数使用格式如下:

    $(addsuffix <suffix>,<names>)
    

    函数说明:函数的功能是把后缀 suffix 加到 names 中的每个单词后面。返回值为添加上后缀的文件名序列。实例:

    OBJ=$(addsuffix .c,src/foo.c hacks)
    all:
        @echo $(OBJ)

    执行 make 后我们可以得到“sec/foo.c.c hack.c”。我们可以看到如果文件名存在后缀名,依然会加上。

    6. 添加前缀名函数,函数使用格式如下:

    $(addperfix <prefix>,<names>)
    

    函数说明:函数的功能是把前缀 prefix 加到 names 中的每个单词的前面。返回值为添加上前缀的文件名序列。实例:

    OBJ=$(addprefix src/, foo.c hacks)
    all:
        @echo $(OBJ)

    执行 make 命令,我们可以得到值是 "src/foo.c src/hacks" 。我们可以使用这个函数给我们的文件添加路径。

    7. 链接函数,函数使用格式如下:

    $(join <list1>,<list2>)
    

    函数说明:函数功能是把 list2 中的单词对应的拼接到 list1 的后面。如果 list1 的单词要比 list2的多,那么,list1 中多出来的单词将保持原样,如果 list1 中的单词要比 list2 中的单词少,那么 list2 中多出来的单词将保持原样。返回值为拼接好的字符串。实例:

    OBJ=$(join src car,abc zxc qwe)
    all:
        @echo $(OBJ)

    执行 make 命令,我们可以得到的值是“srcabc carzxc qwe”。很显然<list1>中的文件名比<list2>的少,所以多出来的保持不变。

    8. 获取匹配模式文件名函数,命令使用格式如下:

    $(wildcard PATTERN)
    

    函数说明:函数的功能是列出当前目录下所有符合模式的 PATTERN 格式的文件名。返回值为空格分隔并且存在当前目录下的所有符合模式 PATTERN 的文件名。实例:

    OBJ=$(wildcard *.c  *.h)
    all:
        @echo $(OBJ)

    执行 make 命令,可以得到当前函数下所有的 ".c " 和  ".h"  结尾的文件。这个函数通常跟的通配符 "*" 连用,使用在依赖规则的描述的时候被展开(在这里我们的例子如果没有 wildcard 函数,我们的运行结果也是这样,"echo" 属于 shell 命令,在使用通配符的时通配符自动展开,我们这里只是相要说明一下这个函数在使用时,如果通过引用变量出现在规则中要被使用)。

    其他常用函数

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

    函数的功能是:把参数<list>中的单词逐一取出放到参数<var>所指定的变量中,然后再执行<text>所包含的表达式。每一次<text>会返回一个字符串,循环过程中,<text>的返所返回的每个字符串会以空格分割,最后当整个循环结束的时候,<text>所返回的每个字符串所组成的整个字符串(以空格分隔)将会是 foreach 函数的返回值。所以<var>最好是一个变量名,<list>可以是一个表达式,而<text>中一般会只用<var>这个参数来一次枚举<list>中的单词。

    实例:

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

    执行 make 命令,我们得到的值是“a.o b.o c.o d.o”。

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

    2、  $(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-partelse-part只会有一个被计算。

    实例:

    OBJ:=foo.c
    OBJ:=$(if $(OBJ),$(OBJ),main.c)
    all:
          @echo $(OBJ)

    执行 make 命令我们可以得到函数的值是 foo.c,如果变量 OBJ 的值为空的话,我们得到的 OBJ 的值就是main.c

    3、  $(call <expression>,<parm1>,<parm2>,<parm3>,...)

    call 函数是唯一一个可以用来创建新的参数化的函数。我们可以用来写一个非常复杂的表达式,这个表达式中,我们可以定义很多的参数,然后你可以用 call 函数来向这个表达式传递参数。
    当 make 执行这个函数的时候,expression参数中的变量$(1)、$(2)、$(3)等,会被参数parm1parm2parm3依次取代。而expression的返回值就是 call 函数的返回值。
    实例 1:
    reverse = $(1) $(2)
    foo = $(call reverse,a,b)
    all:
          @echo $(foo)

    那么,foo 的值就是“a b”。当然,参数的次序可以是自定义的,不一定是顺序的,
    实例 2:

    reverse = $(2) $(1)
    foo = $(call reverse,a,b)
    all:
          @echo $(foo)

    此时的 foo 的值就是“b a”。

    4、  $(origin <variable>)

    origin 函数不像其他的函数,它并不操作变量的值,它只是告诉你这个变量是哪里来的。

    注意: variable 是变量的名字,不应该是引用,所以最好不要在 variable 中使用“$”字符。origin 函数会员其返回值来告诉你这个变量的“出生情况”。

    下面是origin函数返回值:

    • “undefined”:如果<variable>从来没有定义过,函数将返回这个值。
    • “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,我们想去判断一下这个变量是不是环境变量,如果是我们就把它重定义了。如果是非环境变量,那么我们就不重新定义它。于是,我们在 Makefile 中,可以这样写

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

    当然,使用override关键字不就可以重新定义环境中的变量了吗,为什么需要使用这样的步骤?是的,我们用override是可以达到这样的效果的,可是override会把从命令行定义的变量也覆盖了,而我们只想重新定义环境传来的,而不是重新定义命令行传来的。

  • 相关阅读:
    数据结构-顺序表
    数据结构-概论
    社交网络图中结点的“重要性”计算 (30 分) C++解法
    面向对象程序设计--Java语言第二周编程题:有秒计时的数字时钟
    面向对象程序设计--Java语言第三周编程题:查找里程
    面向对象程序设计--Java语言第一周编程题:分数
    剑指Offer_#42_连续子数组的最大和
    vue--模态框背景不动解决方案
    redis(十七):Redis 安装,部署(WINDOWS环境下)
    redis(二十一):Redis 架构模式实现(哨兵)
  • 原文地址:https://www.cnblogs.com/jkin/p/13761882.html
Copyright © 2020-2023  润新知