歡迎您光臨本站 註冊首頁

linux編程跟我學之Makefile之使用變數

←手機掃碼閱讀     火星人 @ 2014-03-23 , reply:0

變數的作用方式:
1.變數為一個文本字串;
2.Makefile執行時變數會自動原模原樣地展開在使用地方;
3.變數可以使用在:「目標」,「依賴目標」,「命令」或是 Makefile的其它部分中;

變數命名規則:
1.包含字元、數字,下劃線(可以是數字開頭),字元大小寫敏感;
2.不應該含有「:」、「#」、「=」或是空字元(空 格、回車等);
3.Makefile中存在自動化變數,例如:「$<」、「$@」等;

一、變數的基礎
1.聲明時給予初值;
2.使用時在變數名前加「$」;
注意:最好用小括弧「()」或是大括弧「{}」把變數給包括起來。
3.使用「$」字元時用「$$」來表示。

示例一:
foo = c
prog.o : prog.$(foo)
$(foo)$(foo) -$(foo) prog.$(foo)
展開后:
prog.o : prog.c
cc -c prog.c


二、變數中的變數

變數定義變數值的兩種方式:

1.變數1 = $(變數2);
注意:
1.變數2可以定義在文件的任何一處;
2.變數2不一定是已定義好的

示例一:
foo = $(bar)
bar = $(ugh)
ugh = Huh?
all:
echo $(foo)

結果:執行「make all」將會打出變數$(foo)的值是「Huh?」

說明:
1.優點: 變數的真實值推到後面來定義
例如 :
CFLAGS = $(include_dirs) -O
include_dirs = -Ifoo -Ibar
結果: 展開是CFLAGS = -Ifoo -Ibar -O。

2.缺點: 該種形式能引起遞歸定義
例如:
CFLAGS = $(CFLAGS) -O或:
A = $(B)
B = $(A)
結果:make陷入無限的變數展開過程中;不過make有能力檢測這樣的定義,並會報錯;

3.變數中使用函數時,make運行非常慢,make調用自身的函數「wildcard」和「shell」發生不可預知的錯誤。
這是可以使用第2種定義變數的方式。

2.變數1 := [$(變數2)] 變數值

示例一:
x := foo
y := $(x) bar
x := later

結果: 執行時其等價於:
y := foo bar
x := later

說明:
1.優點:前面的變數不能使用後面的變數,只能使用前面已定義好了的變數
例如:
y := $(x) bar
x := foo
結果: y = bar;

示例二:其中包括了make的函數、條件表達式和一個系統變數「MAKELEVEL」的使用
ifeq (0,${MAKELEVEL})
cur-dir := $(shell pwd)
whoami := $(shell whoami)
host-type := $(shell arch)
MAKE := ${MAKE} host-type=${host-type} whoami=${whoami}
endif

說明:
1.系統變數「MAKELEVEL」,這個變數會記錄了當前Makefile的調用層數。

示例三:定義一個其值是一個空格的變數
nullstring :=
space := $(nullstring) # end of the line

說明:
1.nullstring 是一個Empty變數,用一個 Empty變數來標明變數的值開始
2.採用「#」註釋符表示變數定義終止,這樣就定義出其值是一個空格的變數。

示例四:
dir := /foo/bar # directory to put the frobs in
說明:
1.dir的值是「/foo/bar」,後面跟了4個空格;
2.$(dir)/file= /foo/bar /file,這樣是錯誤的
3.特殊操作符是「?=」
示例一:
FOO ?= bar

說明:
1.如果FOO沒有被定義過,那麼變數FOO的值就是「bar」;
2.如果FOO先前被定義過,那麼這條語將什麼也不做;
3.等價於語句為:
ifeq ($(origin FOO), undefined)
FOO = bar
endif

三、變數高級用法

兩種變數的高級使用方法

1.變數值替換

概述:將變數中的共有部分替換成其他部分
語法:「$(var:a=b)」或「${var:a=b}」
解釋:將變數「var」中所有以「a」字串「結尾」的「a」替換成「b」字串。
說明:「結尾」意思是「空格」或是「結束符」。

示例一:
foo := a.o b.o c.o
bar := $(foo:.o=.c)

說明:
1.第一行定義一個「$(foo)」變數;
2.第二行把「$(foo)」中所有「.o」字串全部替換成「.c」;
3.最終的結果為:$(bar)=「a.c b.c c.c」;
4.另外一種變數替換的技術「靜態模式」:
foo := a.o b.o c.o
bar := $(foo:%.o=%.c)
說明:被替換字串有相同模式,上面foo中必須包含一個「%」(任意一個字元)字元,這個例子同樣讓$(bar)變數的值為「a.c b.c c.c」。

2.把變數的值再當成變數
示例一
x = y
y = z
a := $($(x))
說明:
1.$(x)的值是「y」;
2.$($(x))就是$(y);
3.$(a)的值就是「z」;

示例二:
x = $(y)
y = z
z = Hello
a :=
說明:
0.$(a) = $($(x))
1.$(x) = $(y)
2.$($(x)) = $($(y))
3.$($(y)) = $(z)
4.$(z) = hello
5.$(a) = hello

示例三:
x = variable1
variable2 := Hello
y = $(subst 1,2,$(x))
z = y
a := $($($(z)))
說明:
1.(subst str1,str2,varb)函數將varb中的str1替換成str2
2.y = variable2
3.a := $($($(z)))
4.$(z) = y
5.a := $($(y))
6.$(y) = variable2
7.a := $(variable2)
8.a := "Hello"

示例四:用多個變數來組成一個變數的名字,然後再取其值
first_second = Hello
a = first
b = second
all = $($a_$b)
說明:
1.「$a_$b」組成了「first_second」;
2.$(all)的值就是「Hello」。

示例五:
a_objects := a.o b.o c.o
1_objects := 1.o 2.o 3.o
sources := $($(a1)_objects:.o=.c)

說明:
1.如果$(a1)是「a」,那麼$(sources)為「a.c b.c c.c」;
2.如果$(a1)是「1」,那麼$(sources)為「1.c 2.c 3.c」

示例六:變數替換,函數和條件語句一同使用
ifdef do_sort
func := sort
else
func := strip
endif
bar := a d b g q c
foo := $($(func) $(bar))
說明:
1.如果定義了"do_sort",那麼foo := $(sort a d b g q c),於是$(foo)的值就是「a b c d g q」;
2.如果沒定義"do_sort",那麼foo := $(strip a d b g q c)
3.

示例六:把"變數的值再當成變數"技術應用在操作符的左邊
dir = foo
$(dir)_sources := $(wildcard $(dir)/*.c)
define $(dir)_print
lpr $($(dir)_sources)
endef
說明:
1.該例子定義了三個變數:「dir」,「foo_sources」和「foo_print」。

四、追加變數值
追加變數:使用「+=」操作符

示例一:
objects = main.o foo.o bar.o utils.o
objects += another.o
說明:
1.$(objects) =「main.o foo.o bar.o utils.o another.o」
2.還可以向下面一樣使用;
objects = main.o foo.o bar.o utils.o
objects := $(objects) another.o
3."+="相對 ":="更為簡潔;
4.如果變數之前沒有定義過,「+=」會自動變成「=」;
5.如果變數之前有變數定義,「+=」會繼承於前次操作的賦值符。
6.如果前一次的是「:=」, 「+=」會以「:=」作為其賦值符,如:
variable := value
variable += more
等價於:
variable := value
variable := $(variable) more
7.如果前一次的是「=」, 「+=」會以「=」作為其賦值符,如:
variable = value
variable += more
等價於:
variable = value
variable = $(variable) more (注意)
說明:make會自動解決上面的遞歸定義問題。

五、override 指示符
make可以通過命令行參數設置變數,Makefile中忽略對這個變數的賦值。
如果想在Makefile中設置這類參數值可以使用「override」指示符。

語法:
override =
override :=
override +=

定義多行變數,使用define指示符;
在define指示符前可以使用ovveride指示符

如:
override define foo
bar
endef

六、多行變數
利用define關鍵字設置變數值可以有換行,這有利於定義一系列的命令(前面講過「命令包」的技術就是利用這個關鍵字)。

說明:
1.define指示符後面是變數名字;
2.重起一行為變數值;
3.定義以endef關鍵字結束;
4.其工作方式和「=」操作符一樣;
5.變數的值可以包含函數、命令、文 字,或是其它變數;
6.define定義的命令變數必須以[Tab]鍵開頭,否則make不會認為其是命令。

示例一:
define two-lines
echo foo
echo $(bar)
endef

七、環境變數
說明:
1.同一變數在系統中定義的系統環境變數優先順序低於在Makefile中定義的。
2.make 使用"-e"參數使系統中的變數替換Makefile中相同的變數。
3.make嵌套調用時,上層Makefile中make定義的變數以系統變數方式傳輸到子Makefile中。
4.make嵌套調用時,上層Makefile中定義的變數以使用export將變數傳輸到子Makefile中。
5.注意變數定義在系統環境中,可能會帶來一些麻煩。

八、目標變數
目標變數定義:
作用範圍為某條規則以及連帶規則,其值只在規則以及連帶規則內有效,不會影響規則鏈以外的同名全局變數的變數稱為目標變數。

全局變數定義:
Makefile中定義的變數稱為「全局變數」,在作用於整個文件。

自動化變數定義:
變數的值依賴於規則的目標和依賴目標而定義的變數。如「$<」

說明:
1.目標局部變數稱為「Target-specific Variable」,它可以和「全局變數」同名;
2.改變數不會影響到同名的全局變數;

目標變數定義語法格式:
:
: overide

語法格式說明;
1.可以是前面講過的各種賦值表達式,如「=」、「:=」、「+=」或是「?=」;
2.第二個語法是針對於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

說明:
1.無論全局的$(CFLAGS)值是什麼,在prog目標,以及其所引發的所有規則中(prog.o foo.o bar.o的規則),$(CFLAGS)的值都是「-g」

九、模式變數

模式變數定義:把變數定義在符合這種模式的所有目標上的變數。
模式變數又稱Pattern-specific Variable

示例一:給所有以[.o]結尾的目標定義目標變數:
%.o : CFLAGS = -O

說明:
1.make的「模式」一般是至少含有一個「%」。
語法:
:
: override
說明:
override同樣是針對於系統環境傳入的變數,或是make命令行指定的變數。

[火星人 ] linux編程跟我學之Makefile之使用變數已經有3129次圍觀

http://coctec.com/docs/linux/show-post-108866.html