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 <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也是一個字符串替換函數,與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 <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 <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 <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 PATTERN)
wildcard函數列出當前目錄下全部符合PATTERN格式(能夠有多個pattern)的文件名。返回值爲當前文件夾下全部符合模式 PATTERN 的文件名,返回的字符串中各文件名之間使用空格分隔。
示例:
OBJS = $(wildcard %.c)
all:
@echo $(OBJS)
dir函數是一個獲取目錄函數,使用格式以下:
$(dir <names>)
dir函數從文件名序列<names>中取出目錄部分,若是<names>中沒有 "/",取出的值爲"./" (當前目錄)。返回值爲目錄部分,指的是最後一個反斜槓以前的部分。若是沒有反斜槓將返回「./」。
示例:
OBJS = driver/led.c mmt
all:
@echo $(dir $(OBJS))
取出OBJS變量內容的目錄部分,執行結果爲「driver/ ./」
notdir函數和dir函數功能恰好相反,函數使用格式以下:
$(notdir <names>)
notdir函數的功能是從文件名序列<names>中取出非目錄的部分。非目錄的部分是最後一個反斜槓以後的部分。返回值爲文件非目錄的部分。
示例:
OBJS = driver/led.c mmt
all:
@echo $(notdir $(OBJS))
取出OBJS變量內容的非目錄部分,執行結果爲「led.c nmt」
獲取後綴名函數,函數使用格式以下:
$(suffix <names>)
suffix函數從文件名序列<names>中取出各個文件的後綴名。返回值爲文件名序列<names>中的後綴序列,若是文件沒有後綴名,則返回空字符串。
示例:
OBJS = driver/led.c mmt
all:
@echo $(suffix $(OBJS))
取出OBJS變量內容中的各文件後綴名,執行結果爲「.c」
獲取前綴函數,函數使用格式以下:
$(basename <names>)
basename函數是從文件名序列<names>中取出各個文件名的前綴部分。返回值爲被取出來的文件的前綴名,若是文件沒有前綴名則返回空的字符串。
示例:
OBJS = driver/led.c mmt
all:
@echo $(basename $(OBJS))
取出OBJS變量內容中的各文件前綴名,執行結果爲「driver/led mmt」
添加後綴函數,函數使用格式以下:
$(addsuffix <suffix>,<names>)
addsuffix函數是把後綴<suffix>添加到<names>中的每一個單詞後面。返回值爲添加上後綴的文件名序列。
示例:
OBJS = driver/led mmt
all:
@echo $(addsuffix .c, $(OBJS))
給OBJS變量內容中的各單詞添加後綴名,執行結果爲「driver/led.c mmt.c」
添加前綴函數,函數使用格式以下:
$(addperfix <prefix>,<names>)
addprefi函數是把前綴prefix加到names中的每一個單詞的前面。返回值爲添加上前綴的文件名序列。
示例:
OBJS = led.c uart
all:
@echo $(addprefix driver/, $(OBJS))
給OBJS變量內容中的各單詞添加前綴driver/,執行結果爲「driver/led.c 、driver/uart」
三、循環、選擇函數
循環函數,函數使用格式以下:
$(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 <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中還有一些其它的函數可供咱們去使用,後續接觸到時再對本文的內容進行補充!