Makefile中的變數
Makefile中變數有以下幾個特徵:
1. Makefile中變數和函式的展開(除規則命令列中的變數和函式以外),是在make讀取makefile檔案時進行的,這裡的變數包括了使用“=”定義和使用指示符“define”定義的。
2. 變數可以用來代表一個檔名列表、編譯選項列表、程式執行的選項引數列表、搜尋原始檔的目錄列表、編譯輸出的目錄列表和所有我們能夠想到的事物。
3. 變數名是不包括“:”、“#”、“=”、前置空白和尾空白的任何字串。
4. 變數名是大小寫敏感的。推薦的做法是在對於內部定義定義的一般變數(例如:目標檔案列表objects)使用小寫方式,而對於一些引數列表(例如:編譯選項CFLAGS)採用大寫方式。
5. 另外有一些變數名只包含了一個或者很少的幾個特殊的字元(符號)。稱它們為自動化變數。像“$<”、“[email protected]”、“$?”、“$*”等。
(1) 變數的引用
Makefile中在對一些簡單變數的引用,我們也可以不使用“()”和“{}”來標記變數名,而直接使用“$x”的格式來實現,此種用法僅限於變數名為單字元的情況。另外自動化變數也使用這種格式。對於一般多字元變數的引用必須使用括號了標記,否則make將把變數名的首字母作為作為變數而不是整個字串(“$PATH”在Makefile中實際上是“$(P)ATH”)。這一點和shell中變數的引用方式不同。shell中變數的引用可以是“${xx}”或者“$xx”格式。但在Makefile中多字元變數名的引用只能是“$(xx)”或者“${xx}”格式。
(2) 變數的定義
兩種風格:遞迴展開式變數和直接展開式變數。前者前者在引用的地方是嚴格的文字替換,後者用:=定義,變數值中對其他量或者函式的引用在定義變數時被展開(對變數進行替換),此風格變數在定義時就完成了對所引用變數和函式的展開,因此不能實現對其後定義變數的引用(前者是嫩購實現這個功能的)。如:
CFLAGS := $(include_dirs) -O
include_dirs := -Ifoo -Ibar
由於變數“include_dirs”的定義出現在“CFLAGS”定義之後。因此在“CFLAGS”的定義中,“include_dirs”的值為空。“CFLAGS”的值為“-O”而不是“-Ifoo -Ibar -O”。這一點也是直接展開式和遞迴展開式變數的不同點。
在複雜的Makefile中,推薦使用直接展開式變數。因為這種風格變數的使用方式和大多數程式語言中的變數使用方式基本上相同。它可以使一個比較複雜的Makefile在一定程度上具有可預測性。而且這種變數允許我們利用之前所定義的值來重新定義它(比如使用某一個函式來對它以前的值進行處理並重新賦值),此方式在Makefile中經常用到。儘量避免和減少遞迴式變數的使用。
當定義不包含尾空格的變數時,就不能使用這種方式,將變數定義和註釋書寫在同一行並使用若干空格分開。否則,註釋之前的空格會被作為變數值的一部分。例如下邊的做法就是不正確的:
dir := /foo/bar # directory to put the frobs in
變數“dir”的值是“/foo/bar ”(後面有4個空格),這可能並不是想要實現的。如果一個檔案以它作為路徑來表示“$(dir)/file”,那麼大錯特錯了。
“?=”操作符
GNU make中,還有一個被稱為條件賦值的賦值操作符“?=”。被稱為條件賦值是因為:只有此變數在之前沒有賦值的情況下才會對這個變數進行賦值。例如:
FOO ?= bar
其等價於:
ifeq ($(origin FOO), undefined)
FOO = bar
endif
含義是:如果變數“FOO”在之前沒有定義,就給它賦值“bar”。否則不改變它的值。
“+=”操作符
使用“+=”操作符,相當於:
objects = main.o foo.o bar.o utils.o
objects := $(objects) another.o
如果被追加值的變數之前沒有定義,那麼,“+=”會自動變成“=”,此變數就被定義為一個遞迴展開式的變數。如果之前存在這個變數定義,那麼“+=”就繼承之前定義時的變數風格。
variable := value
variable += more
就是
variable := value
variable := $(variable) more
variable = value
variable += more
相當於:
temp = value
variable = $(temp) more
(3) 變數的高階用法
1. 變數的替換引用
對於一個已經定義的變數,可以使用“替換引用”將其值中的字尾字元(串)使用指定的字元(字串)替換。
例如:
foo := a.o b.o c.o
bar := $(foo:.o=.c)
在這個定義中,變數“bar”的值就為“a.c b.c c.c”。使用變數的替換引用將變數“foo”以空格分開的值中的所有的字的尾字元“o”替換為“c”,其他部分不變。
又如:
foo := a.o b.o c.o
bar := $(foo:%.o=%.c)
這個例子同樣使變數“bar”的值為“a.c b.c c.c”。這種格式的替換引用方式比第一種方式更通用。
使用環境變數需要注意以下幾點:
1. 在Makefile中對一個變數的定義或者以make命令列形式對一個變數的定義,都將覆蓋同名的環境變數(注意:它並不改變系統環境變數定義,被修改的環境變數只在make執行過程有效)。而make使用“-e”引數時,Makefile和命令列定義的變數不會覆蓋同名的環境變數,make將使用系統環境變數中這些變數的定義值。
2. make的遞迴呼叫中,所有的系統環境變數會被傳遞給下一級make。預設情況下,只有環境變數和通過命令列方式定義的變數才會被傳遞給子make程序。在Makefile中定義的普通變數需要傳遞給子make時需要使用“export”指示符來對它宣告。
3. 一個比較特殊的是環將變數“SHELL”。在系統中這個環境變數的用途是用來指定使用者和系統的互動介面,顯然對於make是不合適的。因此make的執行環境變數“SHELL”沒有使用同名的環境變數定義,而是“/bin/sh”。make預設“/bin/sh”作為它的命令列解釋程式(make在執行之前將變數“SHELL”設定為“/bin/sh”)。
gcc -O2 -o [email protected] $< 意思
-O2表示優化選項,2表示最優優化,即編譯器會優化你的程式;-o表示後邊接的是檔名稱;[email protected]是Makefile的萬用字元,代指你前面指定的檔名,例如有規則%.o:%.c,那麼[email protected]表示xxx.o檔案(xxx是你的原始碼檔案的名稱字首);$<表示搜尋到的第一個匹配的檔案,對於規則%.o:%.c,$<表示第一個找到的.c檔案。簡而言之,假設在一個資料夾下有若干.c檔案,那麼下面的規則:
%.o:%.c
<TAB>gcc -O2 -o [email protected] $< #<TAB>表示Tab鍵
表示把所有的.c檔案編譯成中間.o檔案。
http://zhidao.baidu.com/question/246239567.html
四、巢狀執行make
在一些大的工程中,我們會把我們不同模組或是不同功能的原始檔放在不同的目錄中,我們可以在每個目錄中都書寫一個該目錄的Makefile,這有利於讓我們的Makefile變得更加地簡潔,而不至於把所有的東西全部寫在一個Makefile中,這樣會很難維護我們的Makefile,這個技術對於我們模組編譯和分段編譯有著非常大的好處。
例如,我們有一個子目錄叫subdir,這個目錄下有個Makefile檔案,來指明瞭這個目錄下檔案的編譯規則。那麼我們總控的Makefile可以這樣書寫:
subsystem:
cd subdir && $(MAKE)
其等價於:
subsystem:
$(MAKE) -C subdir
定義$(MAKE)巨集變數的意思是,也許我們的make需要一些引數,所以定義成一個變數比較利於維護。這兩個例子的意思都是先進入“subdir”目錄,然後執行make命令。
我們把這個Makefile叫做“總控Makefile”,總控Makefile的變數可以傳遞到下級的Makefile中(如果你顯示的宣告),但是不會覆蓋下層的Makefile中所定義的變數,除非指定了“-e”引數。
如果你要傳遞變數到下級Makefile中,那麼你可以使用這樣的宣告:
export <variable ...>
GNU組織建議把編譯器為每一個原始檔的自動生成的依賴關係放到一個檔案中,為每一個“name.c”的檔案都生成一個“name.d”的Makefile檔案,[.d]檔案中就存放對應[.c]檔案的依賴關係。
於是,我們可以寫出[.c]檔案和[.d]檔案的依賴關係,並讓make自動更新或自成[.d]檔案,並把其包含在我們的主Makefile中,這樣,我們就可以自動化地生成每個檔案的依賴關係了。 這裡,我們給出了一個模式規則來產生[.d]檔案: %.d: %.c @set -e; rm -f [email protected]; \ $(CC) -M $(CPPFLAGS) $< > [email protected] ; \ sed 's,$∗\.o[ :]*,\1.o [email protected] : ,g' < [email protected] > [email protected]; \ rm -f [email protected] 總而言之,這個模式要做的事就是在編譯器生成的依賴關係中加入[.d]檔案的依賴,即把依賴關係: main.o : main.c defs.h 轉成: main.o main.d : main.c defs.h 於是,我們的[.d]檔案也會自動更新了,並會自動生成了,當然,你還可以在這個[.d]檔案中加入的不只是依賴關係,包括生成的命令也可一併加入,讓每個[.d]檔案都包含一個完賴的規則。一旦我們完成這個工作,接下來,我們就要把這些自動生成的規則放進我們的主Makefile中。我們可以使用Makefile的“include”命令,來引入別的Makefile檔案(前面講過),例如: sources = foo.c bar.c include $(sources:.c=.d) 上述語句中的“$(sources:.c=.d)”中的“.c=.d”的意思是做一個替換,把變數$(sources)所有[.c]的字串都替換成[.d],關於這個“替換”的內容,在後面我會有更為詳細的講述。當然,你得注意次序,因為include是按次來載入檔案,最先載入的[.d]檔案中的目標會成為預設目標。 書寫命令 需注意下Makefile中:= 和 =區別
從上面的結果中我們可以清楚的看到他們的區別了
= 是最基本的賦值
:= 是覆蓋之前的值
?= 是如果沒有被賦值過就賦予等號後面的值
+= 是新增等號後面的值
1、“=”
make會將整個makefile展開後,再決定變數的值。也就是說,變數的值將會是整個makefile中最後被指定的值。看例子:
x = foo
y = $(x) bar
x = xyz
在上例中,y的值將會是 xyz bar ,而不是 foo bar 。
2、“:=”
“:=”表示變數的值決定於它在makefile中的位置,而不是整個makefile展開後的最終值。
x := foo
y := $(x) bar
x := xyz
在上例中,y的值將會是 foo bar ,而不是 xyz bar 了。
相關推薦
uboot的主Makefile中變數MKCONFIG中建立符號連結相關問題
在uboot的主Makefile中,定義了一個變數:MKCONFIG := $(SRCTREE)/mkconfig。 該MKCONFIG 變數即為源程式目錄下的mkconfig指令碼檔案,該檔案在uboot的前期配置操作時會用到。 x210_sd_conf
uboot的主Makefile中變數MKCONFIG功能介紹
在uboot的主Makefile中,定義了一個變數:MKCONFIG := $(SRCTREE)/mkconfig。 該MKCONFIG 變數即為源程式目錄下的mkconfig指令碼檔案,該檔案在uboot的前期配置操作時會用到。 x210_sd_config :
makefile中變數定義的空格
comma:= , empty:= # space變數用兩個空變數作為識別符號,當中是一個空格 space:= $(empty) $(empty) foo:= a b c bar:= $(subst $(space),$(comma),$(foo)) haha :@echo
Makefile中變數讀取與生效時間
現在我在A Makefile中include B Makefile,在B Makefile中有變數OBJS和VPATH的賦值 來看看B Makefile (libmad/Makefile) VPATH += $(ROOT_DIR)/libmad OBJS +
Makefile中變數$var與$$var的區別詳談
很多人對$var與$$var東西不理解,總是區分不開Makefile中的變數與shell中的變數,我來解釋一下吧。希望對你有用。 首先make精神就是實現自動化編譯,是按照Makefile的規則來進行的,啥子規則呢,目標與依賴檔案的規則。 凡是目標後面有依賴,並根據依賴產生
【三】makefile中的變數
一、變數賦值 直接展開式 := 特點:在定義時立即展開應用的變數 示例: value1 := 5 value2 := $(value1) #value2會立即被賦值成5 value1 :=6 var-test: @echo "value2", $(value2)
Makefile中的偽目標和變數定義格式
本節我們討論一個Makefile中的一個重要的特殊目標:偽目標。 偽目標是這樣一個目標:它不代表一個真正的檔名,在執行make時可以指定這個目標來執行其所在規則定義的命令,有時我們也可以將一個偽目標稱為標籤。使用偽目標有兩點原因:1. 避免在我們的Makefile中定義的
makefile 中 特殊變數的使用
1.源程式的編譯 在Linux下面,如果要編譯一個C語言源程式,我們要使用GNU的gcc編譯器。 下面我們以一個例項來說明如何使用gcc編譯器。 假設我們有下面一個非常簡單的源程式(hello.c): int main(int argc,char **argv) { pri
Makefile中的變數
Makefile中變數有以下幾個特徵: 1. Makefile中變數和函式的展開(除規則命令列中的變數和函式以外),是在make讀取makefile檔案時進行的,這裡的變數包括了使用“=”定義和使用指示符“define”定義的。 2. 變數可以用來代表一個檔名列表、編譯選項列表、程式執行的選項引數列表、搜尋
shell指令碼及makefile中的特殊變數
shell指令碼中的特殊變數 1. $# 傳遞到指令碼的引數個數 2. $* 以一個單字串顯示所有向指令碼傳遞的引數。與位置變數不同,此選項引數可超過9個3. $$ 指令碼執行的當前程序ID號4. $! 後臺執行的最後一個程序的程序ID號5. [email p
Makefile中常用自動變數
自動變數含義 $*不包含副檔名的目標檔名稱 $+所有的依賴檔案,以空格分開,並以出現的先後為序,可能包含重複的依賴檔案 $<第一個依賴檔案的名稱 $?所有時間戳比目標檔案晚的依賴檔案,並以空格分開 [email protected]目標檔案的完整名稱 $^所
makefile中使用環境變數的例子
上例子 首先,在linux 環境中,如此設定: #test=1234567 #export test #echo $test 1234567 # 然後編輯 Makefile all: @echo $(test) 執行結果: #make
Makefile中引用變數時大括號和小括號有啥區別?
如題。 Makefile中可以通過$(Var)或者${Var}的方式引用變數"Var", 我想問一下大括號應用跟小括號引用有啥區別?我有碰到過一個問題,通過小括號在某些情況下引用環境變數一直失敗,但大括號就可以,望各位達人給個正解,謝謝!------解決方案--------
MakeFile中的變數定義
一般在我們書寫Makefile時,各部分變數引用的格式我們建議如下:1. make變數(Makefile中定義的或者是make的環境變數)的引用使用“$(VAR)”格式。 2. 出現在規則命令列中shell變數(一般為執行命令過程中的臨時變數,它不屬於Makefile變
make的引數以及Makefile中的自動變數
最近把Makefile相關的內容稍微梳理了一遍,記錄下一些常用的內容,這篇寫下引數和自動變數吧,首先make的引數: make的引數 常用: “-q” “--question” 這個引數的行為是找目標的意思,也就是說,如果目標存在,那麼其什麼也不會輸出, 當然也不會執行編
Makefile中的變數和shell變數
我們在寫makefile時 多多少少會用到shell指令碼, 對於變數的在shell中的使用有一些要注意的細節。讓我們從一個簡單的makefile來看看。 注意makefile中一定要有一個目標,且一
makefile中的一點知識
color 一點 pan col get ack 是什麽 makefile track makefile文件裏以下這一部分展開是什麽樣的呢?。。。mytarget=foo $(mytarget): $(mytarget).c gcc -o $(mytarge
Makefile中怎樣調用python和perl文件為自己提供須要的數據
print erl col shel ria 實例代碼 space shell eight Makefile中怎樣調用python和perl文件為自己提供須要的數據,利用print函數對外輸出數據 實例代碼例如以下 perl.pl #!/usr/bin/per
Makefile中export分析
platform 打出 ont style focus false pla ext make 在分析內核啟動過程的./arch/arm/Makefile文件裏碰到了這樣字段 162 export TEXT_OFFSET GZFLAGS MMUEXT 然後在子目錄a
通用 Makefile(及makefile中的notdir,wildcard和patsubst)
and har alt table free modify sources follow rul notdir,wildcard和patsubst是makefile中幾個有用的函數,以前沒留意過makefile中函數的用法,今天稍微看看~ 1、makefile裏的函數