• Makefile常用的函数


    Makefile定义了一系列的规则来指定项目中哪些源文件需要先编译,哪些文件后编译,哪些文件需要重新编译,甚至更复杂的操作。一旦写好,只需要一个make命令,整个工程按照Makefile中写好的规则自动完成编译,这样极大的提高了软件开发效率。写好的Makefile文件是被make解释器解析的,make解析器除了解析Makefile文件中编译规则外,还提供了一些特定功能的函数,这些函数可以在编写Makefile中直接使用。掌握其中的一些常用函数,有助于我们更好编写Makefile来管理我们的工程。

    一、函数的调用语法

    在正式介绍这些函数的详细功能前,我们先来看下Makefile中函数的调用语法。函数的调用其实和变量的使用差不多,也是使用“$”符号来标识的,其语法如下:

    $(<function> <arguments>)

    或者是

    ${<function> <arguments>}

    其中 function 代表函数名称,arguments 代表函数参数。函数名和参数之间是以“空格”分割开的,一个函数可能有多个参数,不同的参数之间通过“逗号”来分割开。

    下面来通过一个例子,来看函数是怎么调用的

    DIR = D:\MinGW\mingw64\bin
    DIR_N = $(subst \,/,$(DIR))

    上面第二条语句$(subst \, /, $(DIR))就是对函数的调用,subst是函数名, 后面‘’, ‘/’,‘$(DIR)’代表是传给这个函数的三个参数,$(DIR)代表使用DIR这个变量。好了,我们已经对函数的调用格式做了简单介绍,至于subst这个函数的功能,我们在后面内容中会进行详细解释。

    二、常用函数介绍

    根据功能划分,可以将Makefile中函数分为不同的类型,下面根据功能进行分类,对Makefile中的常用函数进行介绍

    1、字符串处理函数

    • subst函数

    subst是一个字符串替换函数,函数使用格式如下:

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

    <from> 是被替换字串,<to> 是替换字串,<text> 是替换操作作用的字符串,函数返回的结果是替换完成后的字符串。

    示例:

    DIR = D:\MinGW\mingw64\bin
    DIR_N = $(subst \,/,$(DIR))
    all:
      @echo $(DIR)
      @echo $(DIR_N)

    使用subst函数,将DIR变量表示的字符串里的‘’替换成‘/’,替换结果赋值给 DIR_N 变量。执行之后,DIR_N 变量内容为“D:/MinGW/mingw64/bin”

    • patsubst函数

    patsubst也是一个字符串替换函数,与subst函数不同的是它是以模式进行匹配替换的。函数使用格式如下:

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

    patsubst函数查找字符串中以空格分开的单词,是否符合模式部分,如果匹配的话,则将其替换成指定内容。<pattern> 是被替换模式,<replacement> 是替换形式,<text> 是替换操作作用的字符串,函数返回的结果是替换完成后的字符串。

    示例:

    SRC_FILE = main.c bsp_led.c bsp_uart.c
    OBJ_FILE = $(patsubst %.c, %.o, $(SRC_FILE))
    all:
      @echo $(SRC_FILE)
      @echo $(OBJ_FILE)

    通配符“%”,表示通配任意长度的字符串。$(patsubst %.c, %.o, $(SRC_FILE))即将SRC_FILE中所有的以.c为后缀的单词替换成以.o为后缀。执行之后,OBJ_FILE变量内容为“main.o bsp_led.o bsp_uart.o

    (注:%默认情况下被转义,如果想匹配字符串中'%'字符,可以用“”来转义,“\%”来表示真实含义的“%”字符)

    • strip函数

    strip是一个去除空格函数,函数的使用格式如下:

    $(strip <text>)

    strip函数去掉字符串的开头和结尾的空格字符串,并且将其中的多个连续的空格合并成为一个空格。<text>表示被操作的字符串,函数返回值为去掉空格后的字符串

    示例:

    obj_space = Hello     World      !
    obj = $(strip $(obj_space))
    all:
      @echo $(obj_space)
      @echo $(obj)

    将obj_space变量中多个连续的空格合并成为一个空格,结果赋值给obj变量,obj变量内容为“Hello World!”

    • findstring函数

    findstring是一个查找字符串函数,函数的使用格式如下:

    $(findstring <find>,<in>)

    findstring函数有两个参数,<find> 表示目标字符串,<in> 表示源字符串。如果在源字符串中查找到目标字符串,就返回目标字符串,否则返回空

    示例:

    src_obj = Hello Makefile
    find_obj = $(findstring Makefile, $(src_obj))
    all:
        @echo $(find_obj)

    src_obj变量中有“Makefile”字符串,所以返回结果是“Makefile”,find_obj变量内容为“Makefile”

    • filter函数

    filter函数是一个过滤函数,函数的使用格式如下:

    $(filter <pattern>,<text>)

    filter函数有两个参数,<pattern> 传入的是过滤的模式,<text> 传入的是源字符串,函数过滤出text中符合pattern模式(可以有多个pattern)的字符串。函数返回值为过滤出的字符串。

    示例:

    SRC_FILE = main.c led.c readme.txt start.S
    OBJ_FILE = $(filter %.c %.S, $(SRC_FILE))
    all:
        @echo $(OBJ_FILE)

    从SRC_FILE变量中过滤出所有的.c文件和所有的.S文件,过滤的结果赋值给变量OBJ_FILE。SRC_FILE变量中.c文件有main.c 、led.c,.S文件有start.S,所以使用filter函数过滤之后OBJ_FILE变量内容“main.c led.c start.S”

    (注:还有个和filter函数功能相反的函数——filter-out,两个函数参数一致,filter-out是过滤掉<text>中符合<pattern>的内容,返回剩下的内容。如:上例中filter换成filter-out,执行结果为“readme.txt”)

    • words函数

    words函数是一个通过单词个数的函数,函数的使用格式如下:

    $(words <text>)

    words函数有一个参数,<text> 传入的是源字符串,函数返回<text> 传入的源字符串中单词的个数

    示例:

    OBJS = apple orange banana
    all: @echo $(words $(OBJS))

    统计OBJS变量中单词的个数,OBJS中有三个单词,返回结果是3

    2、文件名操作函数

    • wildcard函数

    wildcard函数获取满足匹配模式的文件名,函数的使用格式如下:

    $(wildcard PATTERN)

    wildcard函数列出当前目录下所有符合PATTERN格式(可以有多个pattern)的文件名。返回值为当前文件夹下所有符合模式 PATTERN 的文件名,返回的字符串中各文件名之间使用空格分隔。

    示例:

    OBJS = $(wildcard %.c)
    all:
        @echo $(OBJS)
    • dir函数

    dir函数是一个获取目录函数,使用格式如下:

    $(dir <names>)

    dir函数从文件名序列<names>中取出目录部分,如果<names>中没有 "/",取出的值为"./" (当前目录)。返回值为目录部分,指的是最后一个反斜杠之前的部分。如果没有反斜杠将返回“./”。

    示例:

    OBJS = driver/led.c mmt
    all:
      @echo $(dir $(OBJS))

    取出OBJS变量内容的目录部分,执行结果为“driver/ ./”

    • notdir函数

    notdir函数和dir函数功能刚好相反,函数使用格式如下:

    $(notdir <names>)

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

    示例:

    OBJS = driver/led.c mmt
    all:
      @echo $(notdir $(OBJS))

    取出OBJS变量内容的非目录部分,执行结果为“led.c nmt”

    • suffix函数

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

    $(suffix <names>)

    suffix函数从文件名序列<names>中取出各个文件的后缀名。返回值为文件名序列<names>中的后缀序列,如果文件没有后缀名,则返回空字符串。

    示例:

    OBJS = driver/led.c mmt
    all:
      @echo $(suffix $(OBJS))

    取出OBJS变量内容中的各文件后缀名,执行结果为“.c”

    • basename函数

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

    $(basename <names>)

    basename函数是从文件名序列<names>中取出各个文件名的前缀部分。返回值为被取出来的文件的前缀名,如果文件没有前缀名则返回空的字符串。

    示例:

    OBJS = driver/led.c mmt
    all:
      @echo $(basename $(OBJS))

    取出OBJS变量内容中的各文件前缀名,执行结果为“driver/led mmt”

    • addsuffix函数

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

    $(addsuffix <suffix>,<names>)

    addsuffix函数是把后缀<suffix>添加到<names>中的每个单词后面。返回值为添加上后缀的文件名序列。

    示例:

    OBJS = driver/led mmt
    all:
      @echo $(addsuffix .c, $(OBJS))

    给OBJS变量内容中的各单词添加后缀名,执行结果为“driver/led.c mmt.c”

    • addprefix

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

    $(addperfix <prefix>,<names>)

    addprefi函数是把前缀prefix加到names中的每个单词的前面。返回值为添加上前缀的文件名序列。

    示例:

    OBJS = led.c uart
    all:
      @echo $(addprefix driver/, $(OBJS))

    给OBJS变量内容中的各单词添加前缀driver/,执行结果为“driver/led.c 、driver/uart”

    3、循环、选择函数

    • foreach函数

    循环函数,函数使用格式如下:

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

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

    示例:

    src = $(wildcard *.c)
    
    objs:=$(foreach var, $(basename $(src)), $(var).o)
    all:
        @echo $(objs)

    先使用wildcard函数获取当前文件夹下所有的.c文件名,然后调用foreach函数将保留存在当前文件名的字符串中每个.c单词换成.o

    • if函数

    选择结构函数,函数使用格式如下:

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

    if函数可以包含else部分,也可以不包含else部分。即if函数的参数可以是两个,也可以是三个。如果<condition>部分返回的是非空字符串,那么if条件成立,<then-part>部分被执行,否则<else-part>被执行。

    示例:

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

    OBJ变量为非空字符串,if条件成立,返回的是OBJ变量内容,OBJ变量被返回,OBJ变量仍为app.c

    4、其他

    • origin函数

    origin函数有其他函数功能不同,它并不操作变量的值,而是告诉我们变量的信息,尤其是变量从哪里来。函数的使用格式如下:

    $(origin <text>)

    返回结果

    1) 如果该变量未定义,origin函数返回的是"undefined"

    2) 如果该变量是环境变量,origin函数返回的是"environment"

    3) 如果该变量在Makefile文件中定义,origin函数返回的是"file"

    4) 如果该变量来源于命令行传入,origin函数返回的是"command line"

    5) 如果该变量该变量被override重新定义过,那么返回的是"override"

    6) 如果变量是自动化变量,那么返回的是"automatic"

    7) 如果变量是默认变量,那么返回的是"default"

    示例:

    Uboot的Makefile中使用origin判断V变量是否是通过命令行传入,例如执行make V=XXX,此时ifeq成立,下面语句执行

    ifeq ("$(origin V)", "command line")
      KBUILD_VERBOSE = $(V)
    endif

    三、总结

    这里介绍了一些Makefile中常用的函数,通过例子演示,展示了这些函数是如何使用的。Makefile中还有一些其它的函数可供我们去使用,后续接触到时再对本文的内容进行补充!

  • 相关阅读:
    333333
    钢镚儿冲刺一周期第六天
    钢镚儿冲刺一周期第五天
    钢镚儿冲刺一周期第四天
    钢镚儿冲刺一周期第三天
    钢镚儿冲刺一周期第二天
    钢镚儿冲刺一周期第一天
    软件工程第九周总结
    CVPR论文的爬取
    构建之法读后感第五
  • 原文地址:https://www.cnblogs.com/053179hu/p/14209672.html
Copyright © 2020-2023  润新知