Linux下編譯c/c++源碼須要編寫makefile文件,文章參看
http://blog.sina.com.cn/s/blog_4c4d6e74010009jr.htmlhtml
在Makefile中可使用函數來處理變量,從而讓咱們的命令或是規則更爲的靈活和具備智能。make所支持的函數也不算不少,不過已經足夠咱們的操做了。函數調用後,函數的返回值能夠當作變量來使用。c++
函數調用,很像變量的使用,也是以「$」來標識的,其語法以下: $(<function> <arguments>)
或是 ${<function> <arguments>}
shell
這裏 function 就是函數名,make支持的函數很少。* arguments*是函數的參數,參數間以逗號「,」分隔,而函數名和參數之間以「空格」分隔。函數調用以「$」開頭,以圓括號或花括號把函數名和參數括起。感受很像一個變量,是否是?函數中的參數可使用變量,爲了風格的統一,函數和變量的括號最好同樣,如使用"$(subst a,b,$(x))"
這樣的形式,而不是"$(subst a,b,${x})"
的形式。由於統一會更清楚,也會減小一些沒必要要的麻煩。
仍是來看一個示例:api
comma:= , empty:= space:= $(empty) $(empty) foo:= a b c bar:= $(subst $(space),$(comma),$(foo))
在這個示例中,$(comma)
的值是一個逗號。$(space)
使用了$(empty)
定義了一個空格,$(foo)
的值是"abc"
,$(bar)
的定義用,調用了函數"subst"
,這是一個替換函數,這個函數有三個參數,第一個參數是被替換字串,第二個參數是替換字串,第三個參數是替換操做做用的字串。這個函數也就是把$(foo)
中的空格替換成逗號,因此$(bar)
的值是"a,b,c"
。ssh
$(subst <from>,<to>,<text>)
名稱:字符串替換函數——subst。 功能:把字串<text>中的<from>字符串替換成<to>。 返回:函數返回被替換事後的字符串。
$(subst ee,EE,feet on the street),
把feet on the street
中的「ee」
替換成「EE」
,返回結果是「fEEt on the strEEt」
。ide
$(patsubst <pattern>,<replacement>,<text>)
名稱:模式字符串替換函數——patsubst。 功能:查找<text>中的單詞(單詞以「空格」、「Tab」或「回車」「換行」分隔)是否符合模式<pattern>,若是匹配的話,則以<replacement>替換。這裏,<pattern>能夠包括通配符「%」,表示任意長度的字串。若是 <replacement>中也包含「%」,那麼,<replacement>中的這個「%」將是< pattern>中的那個「%」所表明的字串。(能夠用「\」來轉義,以「\%」來表示真實含義的「%」字符) 返回:函數返回被替換事後的字符串。 示例: $(patsubst %.c,%.o,x.c.c bar.c) 把字串「x.c.c bar.c」符合模式[%.c]的單詞替換成[%.o],返回結果是「x.c.o bar.o」 備註: 這和咱們前面「變量章節」說過的相關知識有點類似。如: 「$(var:<pattern>=<replacement>)」 至關於 「$(patsubst <pattern>,<replacement>,$(var))」, 而「$(var: <suffix>=<replacement>)」 則至關於 「$(patsubst %<suffix>,%<replacement>,$(var))」。 例若有:objects = foo.o bar.o baz.o, 那麼,「$(objects:.o=.c)」和「$(patsubst %.o,%.c,$(objects))」是同樣的。
$(strip <string>)
名稱:去空格函數——strip。 功能:去掉<string>字串中開頭和結尾的空字符。 返回:返回被去掉空格的字符串值。 示例: $(strip a b c ) 把字串「a b c 」去到開頭和結尾的空格,結果是「a b c」。
$(findstring <find>,<in>)
名稱:查找字符串函數——findstring。 功能:在字串<in>中查找<find>字串。 返回:若是找到,那麼返回<find>,不然返回空字符串。 示例: $(findstring a,a b c) $(findstring a,b c) 第一個函數返回「a」字符串,第二個返回「」字符串(空字符串)
$(filter <pattern...>,<text>)
名稱:過濾函數——filter。 功能:以<pattern>模式過濾<text>字符串中的單詞,保留符合模式<pattern>的單詞。能夠有多個模式。 返回:返回符合模式<pattern>的字串。 示例: sources := foo.c bar.c baz.s ugh.h foo: $(sources) cc $(filter %.c %.s,$(sources)) -o foo $(filter %.c %.s,$(sources))返回的值是「foo.c bar.c baz.s」。
$(filter-out <pattern...>,<text>)
名稱:反過濾函數——filter-out。 功能:以<pattern>模式過濾<text>字符串中的單詞,去除符合模式<pattern>的單詞。能夠有多個模式。 返回:返回不符合模式<pattern>的字串。 示例: objects=main1.o foo.o main2.o bar.o mains=main1.o main2.o $(filter-out $(mains),$(objects)) 返回值是「foo.o bar.o」。
$(sort <list>)
名稱:排序函數——sort。 功能:給字符串<list>中的單詞排序(升序)。 返回:返回排序後的字符串。 示例:$(sort foo bar lose)返回「bar foo lose」 。 備註:sort函數會去掉<list>中相同的單詞。
$(word <n>,<text>)
名稱:取單詞函數——word。 功能:取字符串<text>中第<n>個單詞。(從一開始) 返回:返回字符串<text>中第<n>個單詞。若是<n>比<text>中的單詞數要大,那麼返回空字符串。 示例:$(word 2, foo bar baz)返回值是「bar」。
$(wordlist <s>,<e>,<text>)
名稱:取單詞串函數——wordlist。 功能:從字符串<text>中取從<s>開始到<e>的單詞串。<s>和<e>是一個數字。 返回:返回字符串<text>中從<s>到<e>的單詞字串。若是<s>比<text>中的單詞數要大,那麼返回空字符串。若是<e>大於<text>的單詞數,那麼返回從<s>開始,到< text>結束的單詞串。 示例: $(wordlist 2, 3, foo bar baz)返回值是「bar baz」。
$(words <text>)
名稱:單詞個數統計函數——words。 功能:統計<text>中字符串中的單詞個數。 返回:返回<text>中的單詞數。 示例:$(words, foo bar baz)返回值是「3」。 備註:若是咱們要取<text>中最後的一個單詞,咱們能夠這樣:$(word $(words <text>),<text>)。
$(firstword <text>)
名稱:首單詞函數——firstword。 功能:取字符串<text>中的第一個單詞。 返回:返回字符串<text>的第一個單詞。 示例:$(firstword foo bar)返回值是「foo」。 備註:這個函數能夠用word函數來實現:$(word 1,<text>)。
以上,是全部的字符串操做函數,若是搭配混合使用,能夠完成比較複雜的功能。這裏,舉一個現實中應用的例子。咱們知道,make使用「VPATH」變量來指定「依賴文件」的搜索路徑。因而,咱們能夠利用這個搜索路徑來指定編譯器對頭文件的搜索路徑參數CFLAGS,如:
override CFLAGS += (patsubst(patsubst(subst :, ,(VPATH)))如果我們的「(VPATH)))若是咱們的「(VPATH)」值是「src:../headers」,那麼「(patsubst(patsubst(subst :, ,$(VPATH)))」將返回「-Isrc -I../headers」,這正是cc或gcc搜索頭文件路徑的參數。函數
下面咱們要介紹的函數主要是處理文件名的。每一個函數的參數字符串都會被當作一個或是一系列的文件名來對待。測試
$(dir <names...>)
名稱:取目錄函數——dir。 功能:從文件名序列<names>中取出目錄部分。目錄部分是指最後一個反斜槓(「/」)以前的部分。若是沒有反斜槓,那麼返回「./」。 返回:返回文件名序列<names>的目錄部分。 示例: $(dir src/foo.c hacks)返回值是「src/ ./」。
$(notdir <names...>)
名稱:取文件函數——notdir。 功能:從文件名序列<names>中取出非目錄部分。非目錄部分是指最後一個反斜槓(「/」)以後的部分。 返回:返回文件名序列<names>的非目錄部分。 示例: $(notdir src/foo.c hacks)返回值是「foo.c hacks」。
$(suffix <names...>)
名稱:取後綴函數——suffix。 功能:從文件名序列<names>中取出各個文件名的後綴。 返回:返回文件名序列<names>的後綴序列,若是文件沒有後綴,則返回空字串。 示例:$(suffix src/foo.c src-1.0/bar.c hacks)返回值是「.c .c」。
$(basename <names...>)
名稱:取前綴函數——basename。 功能:從文件名序列<names>中取出各個文件名的前綴部分。 返回:返回文件名序列<names>的前綴序列,若是文件沒有前綴,則返回空字串。 示例:$(basename src/foo.c src-1.0/bar.c hacks)返回值是「src/foo src-1.0/bar hacks」。
$(addsuffix <suffix>,<names...>)
名稱:加後綴函數——addsuffix。 功能:把後綴<suffix>加到<names>中的每一個單詞後面。 返回:返回加事後綴的文件名序列。 示例:$(addsuffix .c,foo bar)返回值是「foo.c bar.c」。
$(addprefix <prefix>,<names...>)
名稱:加前綴函數——addprefix。 功能:把前綴<prefix>加到<names>中的每一個單詞後面。 返回:返回加過前綴的文件名序列。 示例:$(addprefix src/,foo bar)返回值是「src/foo src/bar」。
$(join <list1>,<list2>)
名稱:鏈接函數——join。 功能:把<list2>中的單詞對應地加到<list1>的單詞後面。若是<list1>的單詞個數要比< list2>的多,那麼,<list1>中的多出來的單詞將保持原樣。若是<list2>的單詞個數要比< list1>多,那麼,<list2>多出來的單詞將被複制到<list2>中。 返回:返回鏈接事後的字符串。 示例:$(join aaa bbb , 111 222 333)返回值是「aaa111 bbb222 333」。
foreach函數和別的函數很是的不同。由於這個函數是用來作循環用的,Makefile中的foreach函數幾乎是仿照於Unix標準Shell(/bin/sh)中的for語句,或是C-Shell(/bin/csh)中的foreach語句而構建的。它的語法是:this
$(foreach ,,)
這個函數的意思是,把參數中的單詞逐一取出放到參數所指定的變量中,而後再執行所包含的表達式。每一次會返回一個字符串,循環過程當中,的所返回的每一個字符串會以空格分隔,最後當整個循環結束時,所返回的每一個字符串所組成的整個字符串(以空格分隔)將會是foreach函數的返回值。atom
因此,最好是一個變量名,能夠是一個表達式,而中通常會使用這個參數來依次枚舉中的單詞。舉個例子:
names := a b c d files := $(foreach n,$(names),$(n).o)
上面的例子中,(name)中的單詞會被挨個取出,並存到變量「n」中,「(name)中的單詞會被挨個取出,並存到變量「n」中,「(n).o」每次根據「(n)」計算出一個值,這些值以空格分隔,最後做爲foreach函數的返回,所以,(n)」計算出一個值,這些值以空格分隔,最後做爲foreach函數的返回,因此,(files)的值是「a.o b.o c.o d.o」。
注意,foreach中的參數是一個臨時的局部變量,foreach函數執行完後,參數的變量將不在做用,其做用域只在foreach函數當中。
if函數很像GNU的make所支持的條件語句——ifeq(參見前面所述的章節),if函數的語法是:
$(if ,)
或是
$(if ,,)
可見,if函數能夠包含「else」部分,或是不含。即if函數的參數能夠是兩個,也能夠是三個。參數是if的表達式,若是其返回的爲非空字符串,那麼這個表達式就至關於返回真,因而,會被計算,不然會被計算。
而if函數的返回值是,若是爲真(非空字符串),那個會是整個函數的返回值,若是爲假(空字符串),那麼會是整個函數的返回值,此時若是沒有被定義,那麼,整個函數返回空字串。
因此,和只會有一個被計算。
call函數是惟一一個能夠用來建立新的參數化的函數。你能夠寫一個很是複雜的表達式,這個表達式中,你能夠定義許多參數,而後你能夠用call函數來向這個表達式傳遞參數。其語法是:
$(call ,,,...)
當make執行這個函數時,參數中的變量,如(1),(1),(2),$(3)等,會被參數,,依次取代。而的返回值就是call函數的返回值。例如:
reverse = $(1) $(2) foo = $(call reverse,a,b)
那麼,foo的值就是「a b」。固然,參數的次序是能夠自定義的,不必定是順序的,如:
reverse = $(2) $(1) foo = $(call reverse,a,b)
此時的foo的值就是「b a」。
在Makefile規則中,通配符會被自動展開。但在變量的定義和函數引用時,通配符將失效。這種狀況下若是須要通配符有效,就須要使用函數「wildcard」,它的用法是:(wildcardPATTERN…)。在Makefile中,它被展開爲已經存在的、使用空格分開的、匹配此模式的所有文件列表。如果不存在任何符合此模式的文件,函數會忽略模式字符並返回空。需要注意的是: