【六】 makefile常用函式總結
函式的呼叫語法
- 函式使用“$”呼叫:
$(function arguments)
${function arguments}
例如:
$(subst .c, .o, test1.c test2.c)
還是來看一個示例:
#$(comma)值是一個逗號 comma= , $(empty)值是空 empty= $(space)值是空格, 如果直接賦值空格會被忽略,這裡巧妙的使用空變數$(empty) space= $(empty) $(empty) foo= a b c #$(comma)和$(foo)緊跟‘,’不能有空格,否則結果不正確,也不能使用雙引號 #$(bar)的值為 a,b,c bar= $(subst $(space),$(comma),$(foo))
subset是一個替換函式,引數1是搜尋的子字串,引數2是被替換子字串,引數3
是執行替換操作的字串。$(bar)的值 a,b,c。
常用字串函式介紹
- subst
功能:字串替換
示例:
#目標字串中的ee變成大寫的EE
$(subst ee,EE,feet on the street)
- patsubst
功能:字串替換,支援萬用字元
示例:
#符合模式[%.c]的子串替換成[%.o], 返回“x.c.obar.o”,貪婪匹配
$(patsubst %.c,%.o,x.c.c bar.c)
與變數的替換功能相似,例如:
#定義變數objects
objects=foo.o bar.o baz.o
#.o會被替換成.c,
$(objects:.o=.c)
- strip
功能:將字串中多個空格變成一個空格
示例:
data =" a b c "
#data1沒有使用雙引號,a前的空格和c後空格都會被忽略
data1= a b c
dataprint:
#輸出“ a b c ”,c之後還有一個空格
@echo $(strip $(data))
輸出“a b c”
@echo $(strip $(data1))
- findstring
功能:在字串中查詢子串。
返回:如果找到,返回,否則返回空字串。
示例:
#返回a
$(findstring a,a b c)
#返回空串
$(findstring a,b c)
- filter
功能:在字串中查詢子串。
返回:如果找到符合模式子串,返回子串,否則返回空串。
示例:
sources= foo.c foo.h bar.s
foo: $(sources)
#返回“foo.c bar.s”
cc $(filter %.c %.s,$(sources)) -o foo
- filter-out
功能:符合模式的被刪除,保留不符合模式的子串。
返回:符合模式的被刪除,保留不符合模式的子串。
示例:
objects=main1.o foo.o main2.o bar.o
mains=main1.o main2.o
#返回值是“foo.o bar.o”。
$(filter-out $(mains),$(objects))
- sort
功能:給字串中的單詞排序(升序)。
返回:返回排序後的字串,去除重複字串。
示例:
#輸出“bar foo lose”
@echo $(sort foo lose foo bar)
- word
函式功能:取字串“TEXT”中第“N”個單詞(“N”的值從 1開始)。
返回值:返回字串“TEXT”中第“N”個單詞。
函式說明:如果“N”值大於“TEXT”中單詞的數目,返回空串。如果“N”為 0,出錯!
示例:
#返回值為“bar”
$(word 2, foo bar baz)
- wordlist
$(wordlist S,E,TEXT)
函式功能:從字串“TEXT”中取出從“S”開始到“E”的單詞串。 “S”和“E”表示單詞在字串中位 置的數字。
返回值:字串“TEXT”中從第“S”到“E”(包括“E”)的單詞字串。
函式說明:“S”和“E”都是從1開始的數字。 當“S”比“TEXT”中的字數大時,返回空。如果“E”大於“TEXT”字數,返回從“S”開始,到“TEXT”結束的單詞串。如果“S”大於“E”,返回空。
示例:
#返回值為:“bar baz”。
$(wordlist 2, 3, foo bar baz)
- words
功能:統計字串包含的單詞個數
示例:
#返回值為:4。
$(words foo bar foo baz)
- firstword
功能:去字串的首個單詞。
示例:
#返回值為:foo 。
$(firstword foo bar foo baz)
- 綜合示例
make使用“VPATH”變數來指定“依賴檔案”的搜尋路徑。於是,我們可以利用這個搜尋路徑來指定編譯器對標頭檔案的搜尋路徑引數CFLAGS,如:
override CFLAGS += $(patsubst %,-I%,$(subst :, ,$(VPATH)))
如果我們的“$(VPATH)”值是“include:../common”,經過函式處理後將返回“-Iinclude -I../common”,這正是搜尋標頭檔案路徑的引數。
檔名操作函式
下面我們要介紹的函式主要是處理檔名的。每個函式的引數字串都會被當做一個或是一系列的檔名來對待。
- wildcard
作用:尋找檔案
功能:尋找指定模式的檔案,返回成以空格隔開的一整行字元
示例:
$(wildcard *.c)
- dir
名稱:取目錄函式。
功能:從檔名序列中取出目錄部分。目錄部分是指最後一個反斜槓(“/”)之前的部分。如果沒有反斜槓,那麼返回“./”。
返回:返回檔名序列的目錄部分。
示例:
#返回值是“src/ ./”。
$(dir src/foo.c hacks)
- notdir
名稱:取檔案函式。
功能:從檔名序列中取出非目錄部分。非目錄部分是指最後一個反斜槓(“/”)之後的部分。
返回:返回檔名序列的非目錄部分。
示例:
#返回值是“foo.c hacks”。
$(notdir src/foo.c hacks)
- suffix
名稱:取字尾函式——suffix。
功能:從檔名序列中取出各個檔名的字尾。
返回:返回檔名序列的字尾序列,如果檔案沒有後綴,則返回空字串。
示例:
#返回值是“.c .c”。
$(suffix src/foo.c src-1.0/bar.c hacks)
- basename
名稱:取字首函式——basename。
功能:從檔名序列中取出各個檔名的字首部分。
返回:返回檔名序列的字首序列,如果檔案沒有字首,則返回空字串。
示例:
#返回值是“src/foo src-1.0/bar hacks”。
$(basename src/foo.c src-1.0/bar.c hacks)
- addsuffix
名稱:加字尾函式。
功能:把字尾加到中的每個單詞後面。
返回:返回加過後綴的檔名序列。
示例:
#返回值是“foo.c bar.c”。
$(addsuffix .c,foo bar)
- addprefix
名稱:加字首函式。
功能:把字首加到中的每個單詞後面。
返回:返回加過字首的檔名序列。
示例:
#返回值是“src/foo src/bar”。
$(addprefix src/,foo bar)
- join
名稱:連線函式。
功能:把中的單詞對應地加到的單詞後面。如果的單詞個數要比的多,那麼,中的多出來的單詞將保持原樣。如果的單詞個數要比多,那麼,多出來的單詞將被複制到中。
返回:返回連線過後的字串。
示例:
#返回aaa111 bbb222 ccc333
@echo $(join aaa bbb ccc,111 222 333)
#返回aaa111 bbb222 333
@echo $(join aaa bbb,111 222 333)
#返回aaa111 bbb222 ccc
@echo $(join aaa bbb ccc,111 222)
- foreach函式
名稱:foreach 函式用來執行迴圈的,語法類似shell指令碼中for語句。
功能:把引數中的單詞逐一取出放到引數所指定的變數中,然後再執行
示例:
#輸出值“a.o b.o c.o d.o”
files := $(foreach n,$(names),$(n).o)
$(name)中的單詞會被挨個取出,並存到變數“n”中,“$(n).o”每次根據“$(n)”計算出一個值,這些值以空格分隔作為函式的返回值。注意,foreach中的引數是一個臨時的區域性變數,foreach函式執行完後,引數的變數將不在作用,其作用域只在 foreach 函式當中。
- if函式
語法:$(if CONDITION,THEN-PART[,ELSE-PART])
功能:第一個引數“CONDITION” ,在函式執行時忽略其前導和結尾空字元,如果包含對其他變數或者函式的引用則進行展開。如果“CONDITION”的展開結果非空,則條件為真,就將第二個引數“THEN_PATR”作為函式的計算表示式;“CONDITION”的展開結果為空,將第三個引數“ELSE-PART”作為函式的表示式,函式的返回結果為有效表示式的計算結果。
返回值:根據條件決定函式的返回值是第一個或者第二個引數表示式的計算結果。當不存在第三個引數“ELSE-PART” ,並且“CONDITION”展開為空,函式返回空。
函式說明:函式的條件表示式“CONDITION”決定了函式的返回值只能是“THEN-PART”或者“ELSE-PART”兩個之一的計算結果。
示例:
SUBDIR += $(if $(SRC_DIR),$(SRC_DIR),/home/src)
函式的結果是:如果“SRC_DIR”變數值不為空,則將變數“SRC_DIR”指定的目錄作為一個子目錄;否則將目錄“/home/src”作為一個子目錄。
- call函式
call函式用來呼叫非常複雜的表示式,同時向表示式中傳遞引數。
語法:$(call <expression>,<parm1>,<parm2>,<parm3>,...)
功能:這個call函式時<expression>中的引數(如$(1),$(2),$(3)等)會被引數< parm1>,<parm2>,<parm3>依次取代。而<expression>的返回值就是 call函式的返回值。
注意:
1. call函式中對VARIABLE的呼叫,直接給函式或變數名就好了,不要用"$";
2. 多個PARAM使用逗號分割開,且逗號和PARAM之間不能有空格,否則會導致解析異常;
示例1:
define FUNC1
$(info echo 1-"hello")
endef
define FUNC2
$(info echo 2-$(1) $(2))
endef
$(call FUNC1)
$(call FUNC2,hello,world)
$(call FUNC2, hello, world)
all:
@echo Done
輸出:
echo 1-"hello"
echo 2-hello world
echo 2- hello world
Done
示例2
VARIABLE1 := $(2) $(1) #立即賦值變數值為0
VARIABLE2 = $(2) $(1) #遞迴賦值
call-test:
輸出:
#輸出為空
@echo $(call VARIABLE1,hello,world)
#輸出 b,a
@echo $(call VARIABLE2 ,a,b)
- origin函式
語法:$(origin 變數名)
作用:顯示這個變數是哪裡
返回值:
- “undefined” 表示變數未定義。
- “default” 如果是一個預設的定義,比如“CC”這個變數
- “environment” 如果是一個環境變數,且當Makefile被執行時,“-e”引數沒有被開啟。
- “file” 如果這個變數被定義在Makefile中。
- “command line” 如果這個變數是被命令列定義的。
- “override” 如果是被override指示符重新定義的。
- “automatic” 如果是一個命令執行中的自動化變數。關於自動化變數將在後面講述。
這些資訊對於我們編寫Makefile是非常有用的,例如,假設我們有一個Makefile其包了一個定義檔案Make.def,在Make.def中定義了一個變數“bletch”,而我們的環境中也有一個環境變數“bletch”,此時,我們想判斷一下,如果變數來源於環境,那麼我們就把之重定義了,如果來源於Make.def或是命令列等非環境的,那麼我們就不重新定義它。於是,在我們的Makefile中,我們可以這樣寫:
ifdef bletch
ifeq "$(origin bletch)" "environment"
bletch = barf, gag, etc.
endif
endif
當然,你也許會說,使用override關鍵字不就可以重新定義環境中的變量了嗎?為什麼需要使用這樣的步驟?是的,我們用override是可以達到這樣的效果,可是override過於粗暴,它同時會把從命令列定義的變數也覆蓋了,而我們只想重新定義環境傳來的,而不想重新定義命令列傳來的。
- shell函式
shell 函式的引數應該就是作業系統 Shell 的命令。它和反引號“`”是相同的功能。這就是說,shell函式把執行作業系統命令後的輸出作為函式返回。於是,我們可以用作業系統命令以及字串處理命令awk,sed等等命令來生成一個變數,如:
contents := $(shell cat foo)
files := $(shell echo *.c)
注意,這個函式會新生成一個Shell程式來執行命令,所以你要注意其執行效能,如果你的Makefile中有一些比較複雜的規則,並大量使用了這個函式,那麼對於你的系統性能是有害的。特別是Makefile的隱晦的規則可能會讓你的shell函式執行的次數比你想像的多得多。