Makefile經常使用的函數

Makefile定義了一系列的規則來指定項目中哪些源文件須要先編譯,哪些文件後編譯,哪些文件須要從新編譯,甚至更復雜的操做。一旦寫好,只須要一個make命令,整個工程按照Makefile中寫好的規則自動完成編譯,這樣極大的提升了軟件開發效率。寫好的Makefile文件是被make解釋器解析的,make解析器除了解析Makefile文件中編譯規則外,還提供了一些特定功能的函數,這些函數能夠在編寫Makefile中直接使用。掌握其中的一些經常使用函數,有助於咱們更好編寫Makefile來管理咱們的工程。app

1、函數的調用語法函數

在正式介紹這些函數的詳細功能前,咱們先來看下Makefile中函數的調用語法。函數的調用其實和變量的使用差很少,也是使用「$」符號來標識的,其語法以下:spa

$(<function> <arguments>)

 或者是code

${<function> <arguments>}

其中 function 表明函數名稱,arguments 表明函數參數。函數名和參數之間是以「空格」分割開的,一個函數可能有多個參數,不一樣的參數之間經過「逗號」來分割開。blog

下面來經過一個例子,來看函數是怎麼調用的ip

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

上面第二條語句$(subst \, /, $(DIR))就是對函數的調用,subst是函數名, 後面‘\’, ‘/’,‘$(DIR)’表明是傳給這個函數的三個參數,$(DIR)表明使用DIR這個變量。好了,咱們已經對函數的調用格式作了簡單介紹,至於subst這個函數的功能,咱們在後面內容中會進行詳細解釋。開發

2、經常使用函數介紹字符串

根據功能劃分,能夠將Makefile中函數分爲不一樣的類型,下面根據功能進行分類,對Makefile中的經常使用函數進行介紹字符串處理

一、字符串處理函數string

  • 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」)

二、文件名操做函數

  • 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」

三、循環、選擇函數

  • 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

3、總結

這裏介紹了一些Makefile中經常使用的函數,經過例子演示,展現了這些函數是如何使用的。Makefile中還有一些其它的函數可供咱們去使用,後續接觸到時再對本文的內容進行補充!

相關文章
相關標籤/搜索