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”)
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 = https://www.cnblogs.com/053179hu/archive/2020/12/30/$(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
三、總結
這里介紹了一些Makefile中常用的函式,通過例子演示,展示了這些函式是如何使用的,Makefile中還有一些其它的函式可供我們去使用,后續接觸到時再對本文的內容進行補充!
轉載請註明出處,本文鏈接:https://www.uj5u.com/caozuo/242662.html
標籤:其他
