|
|||||||||||
| 技術(shù)交流 | 電路欣賞 | 工控天地 | 數(shù)字廣電 | 通信技術(shù) | 電源技術(shù) | 測控之家 | EMC技術(shù) | ARM技術(shù) | EDA技術(shù) | PCB技術(shù) | 嵌入式系統(tǒng) 驅(qū)動編程 | 集成電路 | 器件替換 | 模擬技術(shù) | 新手園地 | 單 片 機(jī) | DSP技術(shù) | MCU技術(shù) | IC 設(shè)計(jì) | IC 產(chǎn)業(yè) | CAN-bus/DeviceNe |
Makefile使用初步 |
| 作者:shenlan51 欄目:嵌入式系統(tǒng) |
原文見這里: http://www.mcublog.com/more.asp?NAME=shenlan&id=10854 一. 為什么使用變量 變量在makefile中用來代表一個(gè)字符串,用來表示 1. 一系列文件的名字 2. 傳遞給編譯器的參數(shù) 3. 需要運(yùn)行的程序 4. 需要查找源代碼的目錄 5. 你需要輸出信息的目錄 6. 你想做的其它事情。 說白了,這有些類似于編程語言中的宏。 二. 定義變量的方式和建議 變量的名字是大小新敏感的,從大的方面來說,makefile中的變量被分為兩種,一個(gè)是用=來定義的,老外叫right-hand sides of variable,另外一種是用define關(guān)鍵字定義的,叫做bodies of variable。先簡單說這些,后面詳述。 傳統(tǒng)上使用大寫字母為變量命名,但是GNU推薦使用小寫字母作為makefile內(nèi)部使用的變量的名字,并用大寫字母定義隱式規(guī)則中的參數(shù)或在命令行中允許用戶重新定義的參數(shù)。 三. 基本的變量引用 用$(NAME)或${NAME}來引用一個(gè)變量,所以當(dāng)你要表示一個(gè)$符號時(shí),你要使用$$。當(dāng)你只使用一個(gè)字母作為變量的名字時(shí),你可以用$NAME來引用這個(gè)變量,不過GNU 并不推薦這樣做,因?yàn)檫@種方式通常用來引用自動變量(Automatic Variables)。 四. 兩種風(fēng)格的變量定義 GNU有兩種定義變量的方式,它們的不同體現(xiàn)在定義它們的風(fēng)格和他們被展開的方式。 第一類叫做遞歸展開變量(Recursively Expanded Variable)。用=或define關(guān)鍵字都 可以定義這種變量,如果變量的定義引用了其它的變量,那么引用會一直展開下去, 直到找到被引用的變量的最新的定義,并以此作為改變量的值返回。例如: 代碼: foo = $(bar) bar = $(ugh) ugh = Huh? $(foo)的值究竟是什么呢? $(foo)被展開成$(bar),$(bar)被展開成$(ugh),最終$(ugh) 被展開成“Huh?”,那么$(foo)的值就是“Huh?”這種類型的變量是所有其他make工具支持 的變量類型。它有著自己的有點(diǎn)和缺點(diǎn): 優(yōu)點(diǎn): 它可以向后引用變量 缺點(diǎn): 1).你不能對該變量進(jìn)行任何擴(kuò)展,例如 CFLAGS=$(CFLAGS) -O 會造成無限循環(huán)展開,所有對于遞歸展開變量,這樣做是不允許的。 2).如果makefile中的某個(gè)變量調(diào)用了某些函數(shù),那么在變量被展開的每一次,函數(shù)都會被調(diào)用, 說的好些,無非是make慢點(diǎn),更壞的情況是一些 shell函數(shù)和通配符的重復(fù)調(diào)用的結(jié)果往往 是難以預(yù)知的。 最后,用一個(gè)例子說明上面的問題。用這個(gè)makefile試一下就明白了(分別開啟和注銷掉第三行, 你就能看到結(jié)果) 代碼: bar = TEST foo = $(bar) bar = $(ugh) ugh = Huh? all: ;echo foo 為了解決這些問題,GNU定義了另一中其它風(fēng)格的變量,叫做簡單擴(kuò)展變量(Simply Expanded Variables) 簡單擴(kuò)展變量用符號:=來定義,用這種方式定義的變量,會在變量的定義點(diǎn),按照被引用的變量的當(dāng)前值 進(jìn)行展開。同樣寫個(gè)例子,測試一下,這東西用文字表達(dá)太困難了 代碼: m := mm x := $(m) y := $(x) bar x := later all:;echo $(x) $(y) 這種定義變量的方式更適合在大的編程項(xiàng)目中使用,因?yàn)樗裎覀円话愕木幊陶Z言。 其實(shí),GNU還對makefile中定義變量的方式進(jìn)行了第三種擴(kuò)展,用?=定義變量,它的含義是如果變量還沒定義 就定義它,例如 FOO ?= Am I defined?,那么,它相當(dāng)于下面的代碼片斷 代碼: ifeq ($(origin FOO), undefined) FOO = Am I defined? endif 這種寫法可以用于為用戶提供默認(rèn)的選項(xiàng),即如果用戶不定義,就提供給他默認(rèn)的。另外,要說明的是把變量 定義成NULl,也是定義了變量,此時(shí)?=將不再起作用。 注意: 最后要說的是,無論我們使用那種風(fēng)格定義變量,都不要在定義變量的行后面加上隨機(jī)數(shù)目的空格,之后寫注釋, 這個(gè)我們想象的是不一樣的,例如 ml = MAGIC_linux 和 ml = MAGIC_linux # My favourite linux distribution 這是兩個(gè)完全不同的變量,其中第一個(gè)ml的值是MAGIC_linux,而后一個(gè)的值是‘MAGIC_linux ’,所以除非 你有意要定義末尾帶有空格的變量,否則不要在定義變量行末尾隨便添加空格和注釋。 五. 高級的變量引用方法 有兩種方法: 1. 替換變量引用 2. 計(jì)算變量的值(更確切的說是推導(dǎo)) 第一種 定義方法: $(var: a=b) ${var: a=b} 意義:把其變量a的值中,每一個(gè)詞的最后一個(gè)字幕換成b 例如: 代碼: foo := a.o b.o c.o bar := $(foo:.o=.c) all:;echo $(bar) 這時(shí),bar的值等于a.c b.c c.c 另外,我們還可以用bar := $(foo:%.o=%.c)的形式 第二種 這是一種高級的makefile編程技術(shù),一般我們很少使用它,但是它并不難,先看個(gè)例子 代碼: x = y y = z a := $($(x)) 此時(shí),a的值是什么呢?答案是z。因?yàn)閮?nèi)層的$(x)=y,而外層的$(y)=z,也就是說a的值是通過$(x)計(jì)算出來的,所以 叫做計(jì)算變量的值。當(dāng)然嵌套可是有很多層,自己試試吧,不多說了。在嵌套變量引用的時(shí)候,還可以包含函數(shù)調(diào)用, 例如: 代碼: x = variable1 variable2 := Hello y = $(subst 1,2,$(x)) z = y a := $($($(z))) 一番推導(dǎo),a的值等于Hello 整個(gè)變量的推導(dǎo)過程中可以涉及到多個(gè)變量,這樣,一個(gè)變量就可以有多個(gè)字面值,例如: 代碼: a_dirs := dira dirb 1_dirs := dir1 dir2 a_files := filea fileb 1_files := file1 file2 ifeq "$(use_a)" "yes" a1 := a else a1 := 1 endif ifeq "$(use_dirs)" "yes" df := dirs else df := files endif dirs := $($(a1)_$(df)) 根據(jù)usa_a和use_dirs這兩個(gè)兩個(gè)變量的值,dirs可以有不同的值 另外,推導(dǎo)變量值還可以用在替換變量引用中,例如: 代碼: a_objects := a.o b.o c.o 1_objects := 1.o 2.o 3.o sources := $($(a1)_objects:.o=.c) 根據(jù)上面a1值的不同,source可以等于a.c b.c c.c或1.c 2.c 3.c 這種內(nèi)嵌變量的限制是你不能把函數(shù)調(diào)用作為定義變量的一種方式,舉個(gè)例子 代碼: ifdef do_sort func := sort else func := strip endif bar := a d b g q c foo := $($(func) $(bar)) foo的是什么呢?它是sort a d b g q c或strip a d b g q c,而并不是我們想象的把a(bǔ) d b g q c作為參數(shù) 傳遞給sort或strip 你還可以把推導(dǎo)出來的變量名作為變量的左值 代碼: dir = foo $(dir)_sources := $(wildcard $(dir)/*.c) 最后要說明的是,要注意把遞歸擴(kuò)展變量和嵌套推廣變量區(qū)分開。 六. 變量得到值的辦法 1) 在你運(yùn)行make的時(shí)候覆蓋變量的值,例如make CFLAGS='-g -O' 2) 在makefile中用上面說的方式為變量賦值 3) 設(shè)定的環(huán)境變量可以在makefile中成為變量 4) GNU定義的一些自動變量,詳見http://www.gnu.org/software/make/manual/html_chapter/make_10.html#SEC111 5) 一些變量有固定的初始值,詳見http://www.gnu.org/software/make/manual/html_chapter/make_10.html#SEC106 七. 為變量添加值 你可以通過+=為已定義的變量添加新的值,例如 代碼: objects = main.o foo.o bar.o utils.o objects += another.o 看上去,+=有些和下面的代碼類似 代碼: objects = main.o foo.o bar.o utils.o objects := $(objects) another.o 但是,它們還是存在這一些不同 當(dāng)變量從前沒有被定義過, +=和=是一樣的,它定義一個(gè)遞歸展開的變量,但是,當(dāng)變量已經(jīng)有定義的時(shí)候,+=只是簡單 的進(jìn)行字符的添加工作。 如果起初你用:=定義變量,那么+=只是利用變量的當(dāng)前值進(jìn)行添加,這和我們的直覺是一樣的,例如: variable := MAGIC_ variable += linux 此時(shí)variable的值就是MAGIC_linux 如果起初用=定義變量,+=的行為就變得有些古怪,它并不會在使用+=的地方馬上進(jìn)行變量展開,而是會把展開工作推后, 直到它找到最后變量的定義,這和=定義變量的行為是類似的,但是總覺得不合直覺,例如: 代碼: var = I love variable = linux var += $(variable) variable = MAGIC all:;echo $(var) 當(dāng)你使用var := I love和上面的情 |
|
|
| 免費(fèi)注冊為維庫電子開發(fā)網(wǎng)會員,參與電子工程師社區(qū)討論,點(diǎn)此進(jìn)入 |
Copyright © 1998-2006 m.58mhw.cn 浙ICP證030469號 |