參考原文http://blog.csdn.net/liang13664759/article/details/1771246/shell
Makefile中變量如C\C++中宏同樣執行時候自動原模原樣展開在使用的地方,與C/C++不一樣得失,Makefile中能夠改變其值。Makefile中變量可使用在「目標」,「依賴目標」,「命令」或其餘部分。ide
變量名能夠包含字符數字下劃線(能夠數字開頭),可是不該該含有「:」、「#」、「=」或是空字符,區分大小寫。函數
聲明時須要給予初始值,使用時加上「$」符號,最好用「()」或者「{}」把變量包括起來。而使用真是的「$」須要「$$」表示。spa
變量能夠用在許多地方,如規則中的目標、依賴、命令以及新的變量。.net
①使用「=」,左側是變量,右側是變量的值,右側變量的值能夠定義在文件的任何一處,也就是說右側變量不必定是一已定義好的值,也可使用後面定義的值。命令行
例如:blog
foo = $(bar)遞歸
bar = $(ugh)ip
ugh = huh?ci
all:
echo $(foo)
執行make all會打印出變量$(foo)的值「Huh?」。因此,變量是能夠用後面的變量來定義的。
注:這樣可能會產生遞歸定義:
A= $(B)
B=$(A)
這會讓make陷入無限的變量展開過程當中去,固然,make有檢測這樣的能力,並會報錯。
若是變量中使用函數,這也會讓make運行時很是慢。他會使用make的「wildcard」和「shell」發生不可預知的錯誤。
②「:=」,前面的變量不能使用後面的變量,只能使用已定義好的變量。
x:=foo
y:=$(x) bar
x:=later
等價於
y := foo bar
x := later
而
y := $(x) bar
x := foo
那麼y的值是「bar」,而不是「foo, bar」
系統變量「MAKELEVEL」表示,若是make有一個嵌套執行的動做,則該變量會記錄當前的Makefile調用層數.
(如下的我也還沒懂,先標記)
nullstring :=
space := $(nullstring) # end of the line
nullstring是一個Empty變量,其中什麼也沒有,而咱們的space的值是一個空格。由於在操做符的右邊是很難描述一個空格的,這裏採用的技術很管用,先用一個Empty變量來標明變量的值開始了,然後面採用「#」註釋符來表示變量定義的終止,這樣,咱們能夠定義出其值是一個空格的變量。請注意這裏關於「#」的使用,註釋符「#」的這種特性值得咱們注意,若是咱們這樣定義一個變量:
dir := /foo/bar # directory to put the frobs in
dir這個變量的值是「/foo/bar」,後面還跟了4個空格,若是咱們這樣使用這樣變量來指定別的目錄——「$(dir)/file」那麼就完蛋了。
③、另外的賦值法,「?=」表示若是沒有被定義過,則賦值。若是定義過,則什麼也不作。
FOO ?= bar
等價於:
ifeq ($(origin FOO), undefined)
FOO = bar
endif
①變量值的替換
替換變量中的共有部分,格式「$(var:a=b)」或是「${var:a=b}」,表示吧變量var中的全部以「a」結尾的「a」替換成「b」
例如:
foo := a.o b.o c.o
bar := $(foo:.o=.c)
把「$(foo)」中的全部「.o」結尾所有替換爲「.c」,因此「$(bar)」的值就是「a.c b.c c.c」。
另一種前面記錄過得靜態模式,
foo := a.o b.o c.o
bar := $(foo:%.o=%.c)
②、「把變量的值在當成變量」
x = y
y = z
a:=$($(x))
例子中,$(x)=y, 因此$($(x))就是$(y),因而$(a)的值就是z
「函數」於「條件語句」一同使用的例子:
ifdef do_set
func := sort
else
func := strip
endif
bar := a b d g q c
foo := $($(func) $(bar))
示例中若是定義了"do_sort",foo:=$(sort a d b g q c),因而$(foo)就是「a b c d g q」。若是沒有定義「do_sort」,則foo:=$(strip a d b g q c),調用strip函數。
「把變量的值當成變量」一樣能夠用在操做符的左邊:
dir = foo
$(dir)_sources := $(wildcard $(dir)/*.c)
define $(die)_print
lpr $($(dir)_sources)#該命令表示把文件發送給打印機
endef
使用「+=」給變量追加值,如:
objects = main.o foo.o bar.o utils.o
objects += another.o
因而,$(objects)值就變成:「main.o foo.o bar.o utils.o another.o"
等價於:
objects = main.p foo.o bar.o utils.o
objects := $(objects) another.o
但「+=」更爲簡潔,且若是前面沒有定義過該變量。「+=」自動變成「=」,若是 有定義過,「+=」聚集成前次操做的賦值符。若是前一次的是「:=」,那麼「+=」會以「:=」爲其賦值符,如:
variable := value
variable += more
等價於:
variable := value
variable := $(variable) more
可是「=」狀況卻不同,例如:
variable = value
variable += more
因爲前次的賦值符是「=」,因此「+=」也會以「=」做爲賦值,那麼豈不會發生變量的遞補歸定義,這是很很差的,因此make會自動爲咱們解決這個問題,咱們沒必要擔憂這個問題。(沒懂)
若是有變量是一般的make命令行參數設置,那麼Makefile中對這個變量的賦值會被忽略。若是想在Makefile中設置這類參數的值,可以使用「override」指示符。
override <variable>=<value>
override <variable>:=<value>
還能夠追加
override <variable>+=<more text>
對於多行的變量定義,可使用define指示符,而define指示符前,也一樣可使用override,如:
override define foo
bar
endef
定義變量foo bar
使用define關鍵字設置變量的值能夠有換行,有利於一系列的命令。(命令包就是利用該關鍵字)
define指示符後面跟變量的名字,重起一行定義變量的值,定義以關鍵字endef結束。工做方式和「=」操做符同樣。變量的值能夠包含函數、命令、文字或是其餘變量。define定義的命令變量中一樣要以【Tab】鍵開頭
define two-lines
echo foo
echo $(bar)
endef
make運行時的系統環境變量能夠在make開始運行時被載入到Makefile文件中,可是若是Makefile中定義了這個變量,或是這個變量由make命令行帶入,那麼系統的環境變量的值將被覆蓋(若是make指定了「-e」參數,那麼系統環境變量將覆蓋Makefile中定義的變量,-e, --environment-overrides環境變量覆蓋Makefile文件)
所以,若是咱們在環境變量中設置了「CFLAGS」環境變量,那麼咱們就能夠在全部的Makefile中使用這個變量。這對於使用統一的編譯參數很方便。若是Makefile中定義了CFLAGS,那麼會使用Makefile中的這個變量,若是沒有定義則使用系統的環境變量。
當make嵌套調用時,上層Makefile中定義的變量會以系統環境變量的方式傳遞到下層的Makefile中。默認狀況下,只有經過命令行設置的變量會被傳遞。定義在文件中的變量傳遞須要export。
不推薦許多的變量定義在系統環境中,這樣執行不用的Makefile擁有同一套系統變量,可能會有麻煩。
前面所述的Makefile中定義的變量都是「全局變量」,整個文件中均可以訪問這些變量。固然「自動化變量」除外("$<"、「$@」、「$^」)屬於「規則型變量」,這種變量的值依賴於規則的目標和依賴目標的定義。
固然,也能夠爲某個目標設置局部變量,成爲「Target-specific Variable」,它能夠和「全局變量」同名,由於他的做用範圍只在這條規則以及連帶規則中,其值也只在做用範圍內有效,不會影響規則鏈之外的全局變量的值。以下:
<target...>:<variable-assignment>
<target...>:overide<vatiable-assignment>
<vatiable-assignment>能夠是前面的各類賦值表達式。「=」、「:=」、「+=」、「?=」。第二條是make命令行帶入的變量或是系統環境變量。
示例:
prog:CFLAGS=-g
prog:prog.o foo.o bar.o
$(CC) $(CFLAGS) prog.o foo.o bar.o
prog.o:prog.c
$(CC) $(CFLAGS) prog.c
foo.o:foo.c
$(CC) $(CFLAGS) foo.c
bar.o:bar.c
$(CC) $(CFLAGS) bar.c
實例中,無論全局的$(CFLAGS)的值是什麼,在prog以及所引起的全部規則中(prog.o foo.o bar.o),$(CFLAGS)的值都是「-g」
9、模式變量
在GNU的make中,還支持模式變量(Pattern-speific Variable),經過前面,變量能夠定義在某個目標上,模式變量的好處就是能夠給定一種「模式」,能夠把變量定義在符合這種模式的全部目標上。
示例:%.o:CFLAGS=-o
<pattern...>:<variable-assignment>
<pattern...>:override<variable-assignment>
make命令行指定變量override針對系統環境傳入變量。