makefile學習之實驗樓

2021-09-27 04:16:05 字數 2920 閱讀 6918

2.4.3 變數的分類與賦值

根據變數定義時所使用的賦值操作符的不同,可以將變數分成兩種型別(或者說是兩種風格):

遞迴展開式變數和直接展開式變數;

使用賦值操作符= 、 += 和 ?=定義的變數都是遞迴展開式變數,使用賦值操作符 :=定義的變數為直接展開式變數 。

兩種變數型別的的最根本區別在於:變數值的求值時機,遞迴式變數的求值時機在於變數被引用時,直接展開式的求值時機在於變數被定義時。

我們來編寫makefile 檔案 /home/shiyanlou/code/makefile_sample/variabletype.mk:

foo1 = $(bar) #遞迴展開式變數

foo2 := $(bar) #直接展開式變數

bar = $(ugh)

ugh = huh?

all:

echo 「foo1 is $(foo1), foo2 is $(foo2)」

然後,使用 $ make -f variabletype.mk 執行variabletype.mk,演示及結果如下:

1-2.4.3-1

由於變數foo1的變數值是在執行echo命令時才求的值,所以foo1的值被遞迴的展開為huh?; 而變數foo2的變數值在定義時就被求值了,此時由於變數bar的值為空,因此foo2的值也為空。

注意:使用遞迴展開式的變數定義,可能會由於出現變數的遞迴定義而導致make陷入到無限的變數展開過程中,最終使make執行失敗
+= 和 ?=是基於=擴充套件而來的兩種變數賦值操作符;

+= 稱為追加賦值操作符,它實現對於乙個已經存在定義的變數進行追加賦值,如下例子:

bar = foo1   

bar += foo2 #追加賦值,bar的值將為 foo1 foo2

all:

echo $(bar)

?=稱為條件賦值的賦值操作符,被稱為條件賦值為:只有此變數在之前沒有賦值的情況下才會對這個變數進行賦值。看一下例子:

bar1 = foo1

bar1 ?= foo2 # bar1 的值還是foo1

bar2 ?= foo2 # bar2 的值為foo2

all:

echo "bar1 is $(bar1), bar2 is $(bar2)"

2.4.4 特殊的變數

在makefile 中使用者除了可以自定義變數外,還可以使用make工具為我們提供的一些特殊的變數及用法。

自動化變數
所謂自動化變數,就是在每條規則中,make自動為我們提供的用於指定規則各個組成部分的變數,一般情況下常用的有以下幾個自動化變數:

$@ -- 代表規則中的目標檔名

$< -- 代表規則的第乙個依賴的檔名

$^ -- 代表規則中所有依賴檔案的列表,檔名用空格分割

看例子,編寫makefile 檔案 /home/shiyanlou/code/makefile_sample/auto_var.mk:

all: first second third

echo 「$$@ = @"e

cho"

@" echo "

@"echo

"$< = <"e

cho"

<" echo "

<"e

cho"

$^ = $^」

first second third:

這裡有幾點需要說明一下:

$字元在makefile中有特殊用途,因此如果要取消其特殊用途當成乙個普通字元傳遞給echo命令執行,需要使用$$

$@在bash shell中也有特殊用途,因此如果希望echo命令在bash中正常輸出$@, 需要加上\字元

該makefile的最後一行first second third: 看起來有點奇怪,這是一條沒有依賴和命令的多目標規則,讀者可自行將它刪除看有什麼效果,並思考原因。

演示及結果如下:

1-2.4.4-1

2.4.5 變數的替換引用

變數的分類與賦值
對於乙個已經定義的變數,可以使用「替換引用」將其值使用指定的字元(字串)進行替換。格式為(va

r:a=

b)或者

(var:a=b)或者

(var:a

=b)或

者,意思是,將變數「var」所表示的值中所有字串「a」結尾的字元替換為「b」的字。「結尾」的含義是空格之前(變數值的多個字以空格分開)。而對於變數其它部分的「a」字元不進行替換。例如:

sources := a.c b.c c.c d.d

objects := $(sources:.c=.o)

all:

echo "objects = $(objects)"

在這個定義中,變數「objects」的值就為「a.c b.c c.c d.d」。使用變數的替換引用將變數「sources」以空格分開的值中的所有的字的尾字元「o」替換為「c」,其他部分不變,注意這裡的d.d並不會被替換。

使用變數改進我們complicated專案的makefile(v1.2):

executbale := complicated

sources := main.c complicated.c

objects := $(sources:.c=.o)

cc := gcc

$(executbale): $(objects)

$(cc) -o $@ $^
main.o: main.c

$(cc) -o $@ -c $<

complicated.o: complicated.c

$(cc) -o $@ -c $<

實驗樓學習小記

linux基本操作總結圖 python基礎型別和基本語法 python的流程控制 python類基礎 class student object init 是乙個特殊方法用於在建立物件時進行初始化操作 通過這個方法我們可以為學生物件繫結name 和 age兩個屬性 def init self,name...

C語言系列之實驗樓筆記(一)

建立c程式的幾個過程 2 編譯 編譯器可以將源 轉成機器語言。linux 這些副檔名.o 4 執行 執行程式 開啟xfce終端 cd desktop cd命令是切換。cd desktop 切換至目錄桌面 touch 1 1.c 建立乙個1 1.c檔案 gedit 1 1.c 使用gedit編輯器將1...

實驗樓 Linux 學習筆記

1.1 linux 歷史的歷史 早期作業系統能夠處理批處理程式,它從檔案或者穿孔卡片讀取資料,然後輸出到另乙個檔案或者印表機,稱為批處理作業系統。後來,出現了能夠支援多個使用者從不同終端同時操作主機的系統,稱為分時作業系統。然後許多人紛紛嘗試開發分時作業系統,unix 就如此誕生,實現了 tcp i...