目錄
- 前言
- 概念
- Chapter 5:變量的基礎
- 5.1 變量的基礎 *
- 空格的定義 **
- 一些指派
- 一些特殊的符号
- 5.2 變量中的變量 *
- 5.3 變量進階用法
- 變量值替換
- 把變量的值再當成變量
- 5.5 override 訓示符
- 5.6 多行變量
- 5.7 環境變量
- 5.8 目标變量
- 5.9 模式變量
- 參考
- 5.1 變量的基礎 *
- 本筆記主要記錄Makefile一些概念要點。
- 變量可以使用在 目标 、 依賴目标 、 指令 或是 Makefile的其它部分中。
- 變量的名字可以包含 字元、數字和下劃線(可以以數字開頭)。
- 但是不應該包含有 : # = 空格 回車 等特殊字元。
- 變量名具有大小寫敏感特性。(推薦大小寫搭配使用)
- 變量指派時,會自動删除等号 = 兩邊的空格,但是,變量值後面的空格會保留,直至遇到 結束符或注釋符 **
- 使用變量時需要在變量前面添加 $ 符号,表示去該變量的值。
- 推薦在取值時給變量添加上 () 或 {}
- 如果需要使用真實的 $ ,就用 $$ 即可。
- 取變量值其實就是相當于 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。 |
- 在 = 号右側可以是值,也可以是變量*
- 如果 = 右側是 變量,那麼該 變量 可以定義在檔案的任何一處(就是 延時變量 =)。(但是不推薦使用該方法)
- 為了避免上面第二點的操作,一般使用 即時變量 := 來指派,例子:
- y 的值是 foo bar
x := foo
y := $(x) bar
x := later
* y 的值是 **bar**
y := $(x) bar
x := food
- 把變量的值再變成變量
- 替換變量中的共有的部分
- 格式
-
$(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
- 通常在執行 make 時,如果通過指令行定義了一個變量,那麼它将替代在 Makefile 中出現的同名變量的定義。
- 如果不希望指令行指定的變量值替代在 Makefile 中的變量定義,那麼我們需要在 Makefile 中使用訓示符 override 來對這個變量進行聲明,如:
override <variable>; = <value>;
# 或
override <variable>; := <value>;
# 或
override <variable>; += <more text>;
# 或
override define foo
bar
endef
- 相當于 C 中的函數
- 關鍵字 define。(使用該該關鍵字可以有 換行)
define two-lines
echo foo
echo $(bar)
endef
- make 運作時的系統環境變量可以在 make 開始運作時被載入到 Makefile 檔案中,但是如果 Makefile中已定義了這個變量,或是這個變量由 make 指令行帶入,那麼系統的環境變量的值将被覆寫。(如果make 指定了“-e”參數,那麼,系統環境變量将覆寫 Makefi le 中定義的變量)
- 為某個目标設定局部變量,這種變量被稱為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
- 就是把上面 目标變量 中的具體目标改為一種模式(一條語句(表達一種模式))。
<pattern ...>; : <variable-assignment>;
<pattern ...>; : override <variable-assignment>;
- 例子:就是把 prog 改為 %.o,%.o 就是一種模式,所有 .o 結尾的都符合該模式。
%.o : CFLAGS = -O
- 《GUN Makefile》
- 《跟我一起寫Makefile》