目錄
前言
- 本筆記主要記錄Makefile一些概念要點。
概念
Chapter 5:變數的基礎
-
變數可以使用在 目標 、 依賴目標 、 命令 或是 Makefile的其它部分中。
-
變數的名字可以包含 字元、數字和下劃線(可以以數字開頭)。
- 但是不應該包含有 : # = 空格 回車 等特殊字元。
- 變數名具有大小寫敏感特性。(推薦大小寫搭配使用)
-
變數賦值時,會自動刪除等號 = 兩邊的空格,但是,變數值後面的空格會保留,直至遇到 結束符或註釋符 **
5.1 變數的基礎 *
- 使用變數時需要在變數前面新增 $ 符號,表示去該變數的值。
- 推薦在取值時給變數新增上 () 或 {}
- 如果需要使用真實的 $ ,就用 $$ 即可。
- 取變數值其實就是相當於 C/C++ 中的巨集展開一樣,其實還是字串替換。
- 注:推薦看例子。*
- 賦值時要注意後面的空格和註釋符 #
- 註釋符 # 可以表示終止一個變數的定義。
- 例子:
- /foo/bar 後面還跟了幾個 空格,如果使用到
$(dir)/file
,那 路徑就錯誤了。
- /foo/bar 後面還跟了幾個 空格,如果使用到
- 賦值時要注意後面的空格和註釋符 #
dir := /foo/bar # directory to put the frobs indir := /foo/bar # directory to put the frobs in
空格的定義 **
- 先定義一個空變數
empty
- 然後用 $ 符號取出 + 空格 + 註釋符 #
- 因為 註釋符 # 可以結束一個變數的賦值。
- 不用註釋符 # 也可以,只是怕空格的數量不對才用 註釋符 # 表示一下而已。
empty:=
a = $(empty) #
一些賦值
變數定義語法:
形式 | 說明 |
---|---|
A = xxx | 延時變數 |
B ?= xxx | 延時變數,只有第一次定義時賦值才成功,若曾被定義過,則此賦值無效。 |
C := xxx | 立即變數 |
D += yyy | 如果D在前面是延時變數,那麼現在它還是延時變數 如果D在前面是立即變數,那麼它現在還是立即變數 |
一些特殊的符號
符號 | 說明 |
---|---|
$@ | 表示規則中的目標檔案集 |
$% | 當目標為函式庫的時候,則表示規則中的目標成員名。反之為空。如一個目標為"foo.a(bar.o)",那麼,"$%"就是"bar.o",以空格分隔開。 |
$< | 依賴檔案集合中的第一個檔案,如果依賴檔案以"%"形式出現,則表示符合模式的一系列檔案集合 |
$? | 所有比目標新的依賴集合,以空格分隔開。 |
$^ | 所有依賴檔案集合,以空格分隔開。如果依賴有相同,則取其一。 |
$+ | 和 "$^"類同,但是不會把相同的刪除掉。 |
$* | 這個變數表示目標模式中 "%"及其之前的部分,如果目標是 test/a.test.c,目標模式為 a.%.c, 那麼 "$* " 就是 test/a.test。 |
5.2 變數中的變數 *
- 在 = 號右側可以是值,也可以是變數*
- 如果 = 右側是 變數,那麼該 變數 可以定義在檔案的任何一處(就是 延時變數 =)。(但是不推薦使用該方法)
- 為了避免上面第二點的操作,一般使用 即時變數 := 來賦值,例子:
- y 的值是 foo bar
x := foo
y := $(x) bar
x := later
* y 的值是 **bar**
y := $(x) bar
x := food
5.3 變數高階用法
- 變數值替換
- 把變數的值再變成變數
變數值替換
- 替換變數中的共有的部分
- 格式
$(var:a=b)
${var:a=b}
- 意思是把變數 var 中的所有以 a 字串結尾的 a 替換成 b 字串。
- 這裡 結尾 的意思是 空格 或 結束符。
- 例子
- 格式
foo := a.o b.o c.o
bar := $(foo:.o=.c)
# 或
foo := a.o b.o c.o
bar := $(foo:%.o=%.c)
把變數的值再當成變數
- 直接上例子:
ifdef do_sort
func := sort
else
func := strip
endif
bar := a d b g q c
foo := $($(func) $(bar))
- 用在操作符左邊:
dir = foo
$(dir)_sources := $(wildcard $(dir)/*.c)
define $(dir)_print
lpr $($(dir)_sources)
endef
5.5 override 指示符
- 通常在執行 make 時,如果通過命令列定義了一個變數,那麼它將替代在 Makefile 中出現的同名變數的定義。
- 如果不希望命令列指定的變數值替代在 Makefile 中的變數定義,那麼我們需要在 Makefile 中使用指示符 override 來對這個變數進行宣告,如:
override <variable>; = <value>;
# 或
override <variable>; := <value>;
# 或
override <variable>; += <more text>;
# 或
override define foo
bar
endef
5.6 多行變數
- 相當於 C 中的函式
- 關鍵字 define。(使用該該關鍵字可以有 換行)
- 例子
define two-lines
echo foo
echo $(bar)
endef
5.7 環境變數
- make 執行時的系統環境變數可以在 make 開始執行時被載入到 Makefile 檔案中,但是如果 Makefile中已定義了這個變數,或是這個變數由 make 命令列帶入,那麼系統的環境變數的值將被覆蓋。(如果make 指定了“-e”引數,那麼,系統環境變數將覆蓋 Makefi le 中定義的變數)
5.8 目標變數
- 為某個目標設定區域性變數,這種變數被稱為Target-specifi c Variable。
- 範圍只在這條規則以及連帶規則中。
- 語法
; 可以是前面講過的各種賦值表示式,如 = := += 或是 ?=
<target ...> : <variable-assignment>;
<target ...> : overide <variable-assignment>
- 例子
- 在這個示例中,不管全域性的 $(CFLAGS) 的值是什麼,在 prog 目標,以及其所引發的所有規則中(prog.o foo.o bar.o 的規則),$(CFLAGS) 的值都是 -g。
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
5.9 模式變數
- 就是把上面 目標變數 中的具體目標改為一種模式(一條語句(表達一種模式))。
- 語法
<pattern ...>; : <variable-assignment>;
<pattern ...>; : override <variable-assignment>;
- 例子:就是把 prog 改為 %.o,%.o 就是一種模式,所有 .o 結尾的都符合該模式。
%.o : CFLAGS = -O
參考
- 《GUN Makefile》
- 《跟我一起寫Makefile》