2020国产成人精品视频,性做久久久久久久久,亚洲国产成人久久综合一区,亚洲影院天堂中文av色

分享

GNU make中文手冊(cè)-第三章:Makefile 總述

 todaytomo 2006-12-30
GNU make中文手冊(cè)-第三章:Makefile 總述 作者: hew  發(fā)布日期: 2006-3-21    查看數(shù): 151   出自: http://www.
第三章:Makefile 總述

3.1 Makefile的內(nèi)容
在一個(gè)完整的Makefile中,包含了5個(gè)東西:顯式規(guī)則、隱含規(guī)則、變量的定義、指示符和注釋。關(guān)于“規(guī)則”、“變量”和“Makefile指示符”將在后續(xù)的章節(jié)進(jìn)行詳細(xì)的討論。本章討論的是一些基本概念。

² 顯式規(guī)則:它描述了在何種情況下如何更新一個(gè)或者多個(gè)被稱(chēng)為目標(biāo)的文件(Makefile的目標(biāo)文件)。在書(shū)寫(xiě)Makefile是需要明確地給出目標(biāo)文件、目標(biāo)的依賴(lài)文件列表以及更新目標(biāo)文件所需要的命令。

² 隱含規(guī)則:它是make根據(jù)此類(lèi)目標(biāo)文件的命名(典型的是文件名的后綴)而自動(dòng)推導(dǎo)出來(lái)的規(guī)則。make根據(jù)目標(biāo)文件的名字,自動(dòng)產(chǎn)生目標(biāo)的依賴(lài)文件并使用默認(rèn)的命令來(lái)對(duì)目標(biāo)進(jìn)行更新。

² 變量定義:就是使用一個(gè)字符串代表一段文本串,當(dāng)定義了變量以后,Makefile后續(xù)在需要使用此文本串的地方,通過(guò)引用這個(gè)變量來(lái)實(shí)現(xiàn)對(duì)文本串的使 用。第一章的的例子中,我們就定義了一個(gè)變量“objects”來(lái)表示一個(gè).o文件列表。關(guān)于變量的詳細(xì)討論可參考 第五章 Makefile中的變量

² Makefile指示符:指示符指明在make程序讀取makefile文件過(guò)程中所要執(zhí)行的一個(gè)動(dòng)作。其中包括:

² 讀取一個(gè)文件,讀取給定文件名的文件。參考 2.3 包含其它makefile文件一節(jié)

² 決定(通常是根據(jù)一個(gè)變量的得值)處理或者忽略Makefile中的某一特定部分。參考 第六章Makefile的條件執(zhí)行

² 定義一個(gè)多行變量。參考 5.8 多行定義 一節(jié)

² 注釋?zhuān)篗akefile中“#”字符后的內(nèi)容被作為是注釋內(nèi)容(和shell腳本一樣)處理。如果此行的第一個(gè)非空字符為“#”,那么此行為注釋行。注釋 行的結(jié)尾如果存在反斜線(\),那么下一行也被作為注釋行。一般在書(shū)寫(xiě)Makefile時(shí)推薦將注釋作為一個(gè)獨(dú)立的行,而不要和Makefile的有效行 放在一行中書(shū)寫(xiě)。當(dāng)在Makefile中需要使用字符“#”時(shí),可以使用反斜線加“#”(\#)來(lái)實(shí)現(xiàn),其表示將“#”作為一字符而不是注釋的開(kāi)始標(biāo)志。

需要注意的地方:

Makefile中第一個(gè)規(guī)則之后的所有以[Tab]字符開(kāi)始的的行,make程序都會(huì)將其給系統(tǒng)的shell程序去解釋執(zhí)行。因此以[Tab]字符開(kāi)始 的注釋行也會(huì)被交給shell來(lái)處理,此命令行是否需要被執(zhí)行(shell執(zhí)行或者忽略)是由系統(tǒng)shell程序來(lái)判決的。

另外,在使用指示符“define”定義一個(gè)多行的變量或者命令包時(shí),其定義體(“define”和“endef”之間的內(nèi)容)會(huì)被完整的展開(kāi)到 Makefile中引用此變量的地方(包含定義體中的注釋行);make在引用此變量的地方對(duì)所有的定義體進(jìn)行處理,決定是注釋還是有效內(nèi)容。 Makefile中的變量可以和C語(yǔ)言中的宏(實(shí)質(zhì)一樣)一樣來(lái)理解。對(duì)一個(gè)變量引用的地方make所做的就是將這個(gè)變量根據(jù)定義進(jìn)行基于文本的展開(kāi),展 開(kāi)變量的過(guò)程不涉及到任何變量的具體含義和功能分析。



3.2 makefile文件的命名
默認(rèn)的情況下,make會(huì)在工作目錄(執(zhí)行make的目錄)下按照文件名順序?qū)ふ襪akefile文件讀取并執(zhí)行,查找的文件名順序?yàn)椋?#8220;GNUmakefile”、“makefile”、“Makefile”。

通常應(yīng)該使用“makefile”或者“Makefile”作為一個(gè)makefile的文件名(我們推薦使用“Makefile”,首字母大寫(xiě)而比較顯 著,一般在一個(gè)目錄中和當(dāng)前目錄的一些重要文件(README,Chagelist等)靠近,在尋找時(shí)會(huì)比較容易的發(fā)現(xiàn)它)。而 “GNUmakefile”是我們不推薦使用的文件名,因?yàn)橐源嗣奈募挥?#8220;GNU make”才可以識(shí)別,而其他版本的make程序只會(huì)在工作目錄下“makefile”和“Makefile”這兩個(gè)文件。

如果make程序在工作目錄下無(wú)法找到以上三個(gè)文件中的任何一個(gè),它將不讀取任何其他文件作為解析對(duì)象。但是根據(jù)make隱含規(guī)則的特性,我們可以通過(guò)命 令行指定一個(gè)目標(biāo),如果當(dāng)前目錄下存在符合此目標(biāo)的依賴(lài)文件,那么這個(gè)命令行所指定的目標(biāo)將會(huì)被創(chuàng)建或者更新,參見(jiàn)注釋。

當(dāng)makefile文件的命名不是這三個(gè)任何一個(gè)時(shí),需要通過(guò)make的“-f”或者“--file”選項(xiàng)來(lái)指定make讀取的makefile文件。給 make指定makefile文件的格式為:“-f NAME”或者“—file=NAME”,它指定文件“NAME”作為執(zhí)行make時(shí)讀取的makefile文件。也可以通過(guò)多個(gè)“-f”或者“-- file”選項(xiàng)來(lái)指定多個(gè)需要讀取的makefile文件,多個(gè)makefile文件將會(huì)被按照指定的順序進(jìn)行連接并被make解析執(zhí)行。當(dāng)通過(guò)“-f” 或者“--file”指定make讀取makefile的文件時(shí),make就不再自動(dòng)查找這三個(gè)標(biāo)準(zhǔn)命名的makefile文件。



注釋?zhuān)和ㄟ^(guò)命令指定目標(biāo)使用make的隱含規(guī)則:

當(dāng)前目錄下不存在以“GNUmakefile”、“makefile”、“Makefile”命名的任何文件,

1. 當(dāng)前目錄下存在一個(gè)源文件foo.c的,我們可以使用“make foo.o”來(lái)使用make的隱含規(guī)則自動(dòng)生成foo.o。當(dāng)執(zhí)行“make foo.o”時(shí)。我們可以看到其執(zhí)行的命令為:

cc –c –o foo.o foo.c

之后,foo.o將會(huì)被創(chuàng)建或者更新。

2. 如果當(dāng)前目錄下沒(méi)有foo.c文件時(shí),就是make對(duì).o文件目標(biāo)的隱含規(guī)則中依賴(lài)文件不存在。如果使用命令“make foo.o”時(shí),將回到到如下提示:

make: *** No rule to make target ‘foo.o’. Stop.

3. 如果直接使用命令“make”時(shí),得到的提示信息如下:

make: *** No targets specified and no makefile found. Stop.



3.3 包含其它makefile文件
本節(jié)我們討論如何在一個(gè)Makefile中包含其它的makefile文件。Makefile中包含其它文件的關(guān)鍵字是“include”,和C語(yǔ)言對(duì)頭文件的包含方式一致。

“include”指示符告訴make暫停讀取當(dāng)前的Makefile,而轉(zhuǎn)去讀取“include”指定的一個(gè)或者多個(gè)文件,完成以后再繼續(xù)當(dāng)前Makefile的讀取。Makefile中指示符“include”書(shū)寫(xiě)在獨(dú)立的一行,其形式如下:



include FILENAMES...



FILENAMES是shell所支持的文件名(可以使用通配符)。

指示符“include”所在的行可以一個(gè)或者多個(gè)空格(make程序在處理時(shí)將忽略這些空格)開(kāi)始,切忌不能以[Tab]字符開(kāi)始(如果一行以 [Tab]字符開(kāi)始make程序?qū)⒋诵凶鳛橐粋€(gè)命令行來(lái)處理)。指示符“include”和文件名之間、多個(gè)文件之間使用空格或者[Tab]鍵隔開(kāi)。行尾 的空白字符在處理時(shí)被忽略。使用指示符包含進(jìn)來(lái)的Makefile中,如果存在變量或者函數(shù)的引用。它們將會(huì)在包含它們的Makefile中被展開(kāi)。

來(lái)看一個(gè)例子,存在三個(gè).mk文件,“$(bar)”被擴(kuò)展為“bish bash”。則

include foo *.mk $(bar)



等價(jià)于

include foo a.mk b.mk c.mk bish bash



make程序在處理指示符include時(shí),將暫停對(duì)當(dāng)前使用指示符“include”的makefile文件的讀取,而轉(zhuǎn)去依此讀取由 “include”指示符指定的文件列表。直到完成所有這些文件以后再回過(guò)頭繼續(xù)讀取指示符“include”所在的makefile文件。

通常指示符“include”用在以下場(chǎng)合:

1. 有多個(gè)不同的程序,由不同目錄下的幾個(gè)獨(dú)立的Makefile來(lái)描述其創(chuàng)建或者更新規(guī)則。它們需要使用一組通用的變量定義或者模式規(guī)則。通用的做法是將這 些共同使用的變量或者模式規(guī)則定義在一個(gè)文件中(沒(méi)有具體的文件命名限制),在需要使用的Makefile中使用指示符“include”來(lái)包含此文件。

2. 當(dāng)根據(jù)源文件自動(dòng)產(chǎn)生依賴(lài)文件時(shí);我們可以將自動(dòng)產(chǎn)生的依賴(lài)關(guān)系保存在另外一個(gè)文件中,主Makefile使用指示符“include”包含這些文件。這 樣的做法比直接在主Makefile中追加依賴(lài)文件的方法要明智的多。其它版本的make已經(jīng)使用這種方式來(lái)處理。

如果指示符“include”指定的文件不是以斜線開(kāi)始(絕對(duì)路徑,如/usr/src/Makefile...),而且當(dāng)前目錄下也不存在此文件; make將根據(jù)文件名試圖在以下幾個(gè)目錄下查找:首先,查找使用命令行選項(xiàng)“-I”或者“--include-dir”指定的目錄,如果找到指定的文件, 則使用這個(gè)文件;否則依此搜索以下幾個(gè)目錄(如果其存在):“/usr/gnu/include”、“/usr/local/include”和 “/usr/include”。

當(dāng)在這些目錄下都沒(méi)有找到“include”指定的文件時(shí),make將會(huì)提示一個(gè)包含文件未找到的告警提示,但是不會(huì)立刻退出。而是繼續(xù)處理 Makefile的內(nèi)容。當(dāng)完成讀取所有的makefile文件后,make將試圖使用規(guī)則來(lái)創(chuàng)建通過(guò)指示符“include”指定的但未找到的文件,當(dāng) 不能創(chuàng)建它時(shí)(沒(méi)有創(chuàng)建這個(gè)文件的規(guī)則),make將提示致命錯(cuò)誤并退出。會(huì)輸出類(lèi)似如下錯(cuò)誤提示:



Makefile:錯(cuò)誤的行數(shù):未找到文件名:提示信息(No such file or directory)

Make: *** No rule to make target ‘’. Stop



我們可使用“-include”來(lái)代替“include”,忽略由于包含文件不存在或者無(wú)法創(chuàng)建時(shí)的錯(cuò)誤提示(“-”的意思是告訴make,忽略此操作的錯(cuò)誤。make繼續(xù)執(zhí)行)。像下邊那樣:



-include FILENAMES...



使用這種方式時(shí),當(dāng)所要包含的文件不存在時(shí)不會(huì)有錯(cuò)誤提示、make也不會(huì)退出;除此之外,和第一種方式效果相同。以下是這兩種方式的比較:

使用“include FILENAMES...”,make程序處理時(shí),如果“FILENAMES”列表中的任何一個(gè)文件不能正常讀取而且不存在一個(gè)創(chuàng)建此文件的規(guī)則時(shí)make程序?qū)?huì)提示錯(cuò)誤并退出。

使用“-include FILENAMES...”的情況是,當(dāng)所包含的文件不存在或者不存在一個(gè)規(guī)則去創(chuàng)建它,make程序會(huì)繼續(xù)執(zhí)行,只有在因?yàn)閙akefile的目標(biāo)的規(guī)則不存在時(shí),才會(huì)提示致命錯(cuò)誤并退出。

為了和其它的make程序進(jìn)行兼容。也可以使用“sinclude”來(lái)代替“-include”(GNU所支持的方式)。



1.4 變量 MAKEFILES
如果當(dāng)前環(huán)境定義了一個(gè)“MAKEFILES”的環(huán)境變量,make執(zhí)行時(shí)首先將此變量的值作為需要讀入的Makefile文件,多個(gè)文件之間使用空格分 開(kāi)。類(lèi)似使用指示符“include”包含其它Makefile文件一樣,如果文件名非絕對(duì)路徑而且當(dāng)前目錄也不存在此文件,make會(huì)在一些默認(rèn)的目錄 去尋找。此情況和使用“include”的區(qū)別:

1. 環(huán)境變量指定的makefile文件中的“目標(biāo)”不會(huì)被作為make執(zhí)行的“終極目標(biāo)”。就是說(shuō),這些文件中所定義規(guī)則的目標(biāo),make不會(huì)將其作為“終 極目標(biāo)”來(lái)看待。如果在make的工作目錄下沒(méi)有一個(gè)名為“Makefile”、“makefile”或者“GNUmakefile”的文件,make同 樣會(huì)提示“make: *** No targets specified and no makefile found. Stop.”;而在make的工作目錄下存在這樣一個(gè)文件(“Makefile”、“makefile”或者“GNUmakefile”),那么make 執(zhí)行時(shí)的“終極目標(biāo)”就是當(dāng)前目錄下這個(gè)文件中所定義的“終極目標(biāo)”。

2. 環(huán)境變量所定義的文件列表,在執(zhí)行make時(shí),如果不能找到其中某一個(gè)文件(不存在或者無(wú)法創(chuàng)建)。make不會(huì)提示錯(cuò)誤,也不退出。就是說(shuō)環(huán)境變量“MAKEFILES”定義的包含文件是否存在不會(huì)導(dǎo)致make錯(cuò)誤(這是比較隱蔽的地方)。

3. make在執(zhí)行時(shí),首先讀取的是環(huán)境變量“MAKEFILES”所指定的文件列表,之后才是工作目錄下的makefile文件,“include”所指定 的文件是在make發(fā)現(xiàn)此關(guān)鍵字的時(shí)、暫停正在讀取的文件而轉(zhuǎn)去讀取“include”所指定的文件。

變量“MAKEFILES”主要用在“make”的遞歸調(diào)用過(guò)程中的的通信。實(shí)際應(yīng)用中很少設(shè)置此變量。一旦設(shè)置了此變量,在多層make調(diào)用時(shí);由于每 一級(jí)make都會(huì)讀取“MAKEFILES”變量所指定的文件,這樣可能導(dǎo)致執(zhí)行的混亂(可能不是你想看到的執(zhí)行結(jié)果)。不過(guò),我們可以使用此環(huán)境變量來(lái) 指定一個(gè)定義通用的“隱含規(guī)則”和用的變量的文件,比如設(shè)置默認(rèn)搜索路徑;通過(guò)這種方式設(shè)置的“隱含規(guī)則”和定義的變量可以被任何make進(jìn)程使用(有點(diǎn) 象C語(yǔ)言中的全局變量)。

也有人想讓login程序自動(dòng)的在自己的工作環(huán)境中設(shè)置此環(huán)境變量,編寫(xiě)的Makefile建立在此環(huán)境變量的基礎(chǔ)上。此想法可以肯定地說(shuō)不是一個(gè)好主 意。規(guī)勸大家千萬(wàn)不要這么干,否則你所編寫(xiě)的Makefile在其人的工作環(huán)境中肯定不能正常工作。因?yàn)閯e人的工作環(huán)境中可能沒(méi)有設(shè)置相同的環(huán)境變量 “MAKEFILES”。

推薦的做法實(shí):在需要包含其它makefile文件時(shí)使用指示符“include”來(lái)實(shí)現(xiàn)。



3.5 變量 MAKEFILE_LIST
make程序在讀取多個(gè)makefile文件時(shí),包括由環(huán)境變量“MAKEFILES”指定、命令行指、當(dāng)前工作下的默認(rèn)的以及使用指示符 “include”指定包含的,在對(duì)這些文件進(jìn)行解析執(zhí)行之前make讀取的文件名將會(huì)被自動(dòng)的追加到變量“MAKEFILE_LIST”的定義域中。

這樣我們就可以通過(guò)測(cè)試此變量的最后一個(gè)字來(lái)得知當(dāng)前make程序正在處理的是具體的那個(gè)makefile文件。具體地說(shuō)就是一個(gè)makefile文件中 當(dāng)使用指示符“include”包含另外一個(gè)文件之后,變量“MAKEFILE_LIST”的最后一個(gè)只可能是指示符“include”指定所要包含的那 個(gè)文件的名字。如果一個(gè)makefile的內(nèi)容如下:

name1 := $(word $(words $(MAKEFILE_LIST)),$(MAKEFILE_LIST))



include inc.mk



name2 := $(word $(words $(MAKEFILE_LIST)),$(MAKEFILE_LIST))



all:

@echo name1 = $(name1)

@echo name2 = $(name2)

執(zhí)行make,則看到的將是如下的結(jié)果:

name1 = Makefile

name2 = inc.mk

此例子中涉及到了make的函數(shù)的和變量定義的方式,這些將在后續(xù)的章節(jié)中有詳細(xì)的講述。



3.6 其他特殊變量
GNU make支持一個(gè)特殊的變量,此變量不能通過(guò)任何途經(jīng)給它賦值。此變量展開(kāi)以后是一個(gè)特定的值。第一個(gè)重要的特殊的變量是“.VARIABLES”。它被 展開(kāi)以后是此引用點(diǎn)之前、makefile文件中所定義的所有全局變量列表。包括:空變量(未賦值的變量)和make的內(nèi)嵌變量,但不包含目標(biāo)指定的變 量,目標(biāo)指定變量值在特定目標(biāo)的上下文有效。

3.7 makefile文件的重建
有時(shí),Makefile可由其它文件生成,比如RCS或SCCS文件。如果Makefile由其它文件重建,那么在make開(kāi)始解析Makefile時(shí)需要讀取的是更新后的Makefile、而不是那個(gè)沒(méi)有更新的Makefile。make的處理過(guò)程是這樣的:

make在讀入所有makefile文件之后,首先將所讀取的每個(gè)makefile作為一個(gè)目標(biāo),試著去更新它。如果存在一個(gè)更新特定makefile文 件明確規(guī)則或者隱含規(guī)則,則去更新這個(gè)makefile文件。在完成對(duì)所有的makefile文件的更新檢查動(dòng)作之后,如果之前所讀取的makefile 文件已經(jīng)被更新,那么make就清除本次執(zhí)行的狀態(tài)重新讀取一遍所有的makefile文件(此過(guò)程中,同樣在讀取完成以后也會(huì)去試圖更新所有的已經(jīng)讀取 的makefile文件,但是一般這些文件不會(huì)再次被重建,因?yàn)樗鼈冊(cè)跁r(shí)間戳上已經(jīng)是最新的)。

實(shí)際應(yīng)用中,我們會(huì)很明確的了解我們的那些makefile文件不需要重建。出于make效率的考慮,我們可以采用一些辦法來(lái)避免make在執(zhí)行過(guò)程時(shí)查找重建makefile的隱含規(guī)則。例如我們可以書(shū)寫(xiě)一個(gè)明確的規(guī)則,將makefile文件作為目標(biāo),命令為空。

Makefile規(guī)則中,如果使用一個(gè)沒(méi)有依賴(lài)只有命令行的雙冒號(hào)規(guī)則去更新一個(gè)文件,那么每次執(zhí)行make時(shí),此規(guī)則的目標(biāo)文件將會(huì)被無(wú)條件的更新。而 假如此規(guī)則的目標(biāo)文件是一個(gè)makefile文件,那么在執(zhí)行make時(shí),將會(huì)導(dǎo)致這個(gè)makefile文件被無(wú)條件更新,時(shí)make的執(zhí)行陷入到一個(gè)死 循環(huán)中(此makefile文件被不斷的更新、重新讀取、更新再重新讀取的過(guò)程)。為了防止進(jìn)入此循環(huán),make在遇到一個(gè)目標(biāo)是makefile文件的 雙冒號(hào)規(guī)則時(shí),將忽略對(duì)這個(gè)規(guī)則的執(zhí)行(其中包括了使用“MAKEFILES”指定、命令行選項(xiàng)指定、指示符“include”指定的需要make讀取的 所有makefile文件中定義的這一類(lèi)雙冒號(hào)規(guī)則)。

執(zhí)行make時(shí),如果沒(méi)有使用“-f(--file)”選項(xiàng)指定一個(gè)文件,make程序?qū)⒆x取缺省的文件。和使用“-f(--file)”選項(xiàng)不同, make無(wú)法確定工作目錄下是否存在缺省名稱(chēng)的makefile文件。如果缺省makefile文件不存在,但可以通過(guò)一個(gè)規(guī)則來(lái)創(chuàng)建它(此規(guī)則是隱含規(guī) 則),則會(huì)自動(dòng)創(chuàng)建缺省makefile文件,之后重新讀取它并開(kāi)始執(zhí)行。

因此,如果不存在缺省makefile文件,make將按照搜索makefile文件的名稱(chēng)順序去創(chuàng)建它,直到創(chuàng)建成功或者超越其缺省的命名順序。需要明 確的一點(diǎn)是:執(zhí)行make時(shí),如果不能成功地創(chuàng)建其缺省的makefile文件,并不一定會(huì)導(dǎo)致錯(cuò)誤。運(yùn)行make時(shí)一個(gè)makefile文件并不是必需 的。(關(guān)于這一點(diǎn)大家會(huì)在后續(xù)的閱讀過(guò)程中體會(huì)到)

當(dāng)使用“-t(--touch)”選項(xiàng)來(lái)對(duì)Makefile目標(biāo)文件進(jìn)行時(shí)間戳更新時(shí),對(duì)于哪些makefile文件的目標(biāo)是無(wú)效的。就是說(shuō)即使執(zhí)行 make時(shí)使用了選項(xiàng)“-t”,那些目標(biāo)是makefile文件的規(guī)則同樣也會(huì)被make執(zhí)行(而其它的規(guī)則不會(huì)被執(zhí)行,make只是簡(jiǎn)單的更新規(guī)則目標(biāo) 文件的時(shí)間戳);類(lèi)似還有選項(xiàng)“-q(—question)”和“-n(—just-print) ”,這主要是因?yàn)橐粋€(gè)過(guò)時(shí)的makefile文件對(duì)其它目標(biāo)的重建規(guī)則在當(dāng)前看來(lái)可能是錯(cuò)誤的。正因?yàn)槿绱耍瑘?zhí)行命令“make –f mfile –n foo”首先會(huì)試圖重建“mfile文件”、并重新讀取它,之后會(huì)打印出更新目標(biāo)“foo”規(guī)則中所定義的命令但不執(zhí)行此命令。

在這種情況下,如果我們不希望重建makefile文件。那么我們就需要在執(zhí)行make時(shí),在命令行中將這個(gè)makefile文件中為一個(gè)最終目的,這樣 “–t”和其它的選項(xiàng)就對(duì)這個(gè)makefile文件的目標(biāo)有效,防止執(zhí)行這個(gè)makefile作為目標(biāo)的規(guī)則。同樣,命令“make –f mfile –n mfile foo”會(huì)讀取文件“mfile”,打印出重建文件“mfile”的命令、重建“foo”的命令而實(shí)際不去執(zhí)行此命令。并且所打印的用于更新“foo”目 標(biāo)的命令是選項(xiàng)“-f”指定的、沒(méi)有被重建的“mfile”文件中所定義的命令。

3.8 重載另外一個(gè)makefile
有些情況下存在兩個(gè)比較類(lèi)似的makefile文件。其中一個(gè)(makefile-A)需要使用另外一個(gè)文件(makefile-B)中所定義的變量和規(guī) 則。我們可以在“makefile-A”中使用指示符“include”來(lái)包含“mkaefile-B”來(lái)達(dá)到目的,這種情況下,如果兩個(gè) makefile文件中存在相同目標(biāo),而其描述規(guī)則中使用不同的命令。相同目標(biāo)有兩個(gè)不同的規(guī)則命令,這是makefile所不允許的。遇到這種情況,使 用指示符“include”顯然是行不通的。GNU make提供另外一種途徑來(lái)達(dá)到此目的。具體的做法如下:

在需要包含的makefile文件(makefile-A)中,我們可以使用一個(gè)稱(chēng)之為“所有匹配模式”的規(guī)則來(lái)描述在“makefile-A”中沒(méi)有明確定義的目標(biāo),make將會(huì)在給定的makefile文件中尋找沒(méi)有在當(dāng)前Makefile中給出的目標(biāo)更新規(guī)則。

看一個(gè)例子,如果存在一個(gè)命名為“Makefile”的makefile文件,其中描述目標(biāo)“foo”的規(guī)則和其他的一些規(guī),我們也可以書(shū)寫(xiě)一個(gè)內(nèi)容如下命名為“GNUmakefile”的文件。



#sample GNUmakefile

foo:

frobnicate > foo



%: force

@$(MAKE) -f Makefile $@

force: ;



執(zhí)行命令“make foo”,make將使用工作目錄下命名為“GNUmakefile”的文件并執(zhí)行目標(biāo)“foo”所在的規(guī)則,創(chuàng)建它的命令是:“frobnicate > foo”。如果我們執(zhí)行另外一個(gè)命令“make bar”, “GUNmakefile”中沒(méi)有此目標(biāo)的更新規(guī)則。那么,make將會(huì)使用“所有匹配模式”規(guī)則,執(zhí)行命令“$(MAKE) -f Makefile bar”。如果文件“Makefile”中存在此目標(biāo)更新規(guī)則的定義,那么這個(gè)規(guī)則會(huì)被執(zhí)行。此過(guò)程同樣適用于其它 “GNUmakefile”中沒(méi)有給出的目標(biāo)更新規(guī)則。此方式的靈活之處在于:如果在“Makefile”文件中存在同樣一一個(gè)目標(biāo)“foo”的重建規(guī) 則,由于make執(zhí)行時(shí)首先讀取文件“GUNmakefile”并在其中能夠找到目標(biāo)“foo”的重建規(guī)則,所以make就不會(huì)去執(zhí)行這個(gè)“所有模式匹配 規(guī)則”(上例中的目標(biāo)是“%”的規(guī)則)。這樣就避免了使用指示符“include”包含一個(gè)makefile文件時(shí)所帶來(lái)的目標(biāo)規(guī)則的重復(fù)定義問(wèn)題。

此種方式,模式規(guī)則的模式只使用了單獨(dú)的“%”(我們才稱(chēng)他為“所有模式匹配規(guī)則”),它可以匹配任何一個(gè)目標(biāo);它的依賴(lài)是“force”,保證了即使目 標(biāo)文件已經(jīng)存在也會(huì)執(zhí)行這個(gè)規(guī)則(文件已存在時(shí),需要根據(jù)它的依賴(lài)文件的修改情況決定是否需要重建這個(gè)目標(biāo)文件);“force”規(guī)則中使用空命令是為了 防止make程序試圖尋找一個(gè)規(guī)則去創(chuàng)建目標(biāo)“force”時(shí),又使用了模式規(guī)則“%: force”而陷入無(wú)限循環(huán)。

3.9 make如何解析makefile文件
GUN make的執(zhí)行過(guò)程分為兩個(gè)階段。

第一階段:讀取所有的makefile文件(包括“MAKIFILES”變量指定的、指示符“include”指定的、以及命令行選項(xiàng)“-f(-- file)”指定的makefile文件),內(nèi)建所有的變量、明確規(guī)則和隱含規(guī)則,并建立所有目標(biāo)和依賴(lài)之間的依賴(lài)關(guān)系結(jié)構(gòu)鏈表。

在第二階段:根據(jù)第一階段已經(jīng)建立的依賴(lài)關(guān)系結(jié)構(gòu)鏈表決定哪些目標(biāo)需要更新,并使用對(duì)應(yīng)的規(guī)則來(lái)重建這些目標(biāo)。

理解make執(zhí)行過(guò)程的兩個(gè)階段是很重要的。它能幫助我們更深入的了解執(zhí)行過(guò)程中變量以及函數(shù)是如何被展開(kāi)的。變量和函數(shù)的展開(kāi)問(wèn)題是書(shū)寫(xiě) Makefile時(shí)容易犯錯(cuò)和引起大家迷惑的地方之一。本節(jié)將對(duì)這些不同的結(jié)構(gòu)的展開(kāi)階段進(jìn)行簡(jiǎn)單的總結(jié)(明確變量和函數(shù)的展開(kāi)階段,對(duì)正確的使用變量非 常有幫助)。首先,明確以下基本的概念;在make執(zhí)行的第一階段中如果變量和函數(shù)被展開(kāi),那么稱(chēng)此展開(kāi)是“立即”的,此時(shí)所有的變量和函數(shù)被展開(kāi)在需要 構(gòu)建的結(jié)構(gòu)鏈表的對(duì)應(yīng)規(guī)則中(此規(guī)則在建立鏈表是需要使用)。其他的展開(kāi)稱(chēng)之為“延后”的。這些變量和函數(shù)不會(huì)被“立即”展開(kāi),而是直到后續(xù)某些規(guī)則須要 使用時(shí)或者在make處理的第二階段它們才會(huì)被展開(kāi)。

可能現(xiàn)在講述的這些還不能完全理解。不過(guò)沒(méi)有關(guān)系,通過(guò)后續(xù)章節(jié)內(nèi)容的學(xué)習(xí),我們會(huì)一步一步的熟悉make的執(zhí)行過(guò)程。學(xué)習(xí)過(guò)程中可以回過(guò)頭來(lái)參考本節(jié)的內(nèi)容。相信在看完本書(shū)之后,會(huì)對(duì)make的整個(gè)過(guò)程有全面深入的理解。

3.9.1 變量取值
變量定義解析的規(guī)則如下:



IMMEDIATE = DEFERRED

IMMEDIATE ?= DEFERRED

IMMEDIATE := IMMEDIATE

IMMEDIATE += DEFERRED or IMMEDIATE

define IMMEDIATE

DEFERRED

Endef



當(dāng)變量使用追加符(+=)時(shí),如果此前這個(gè)變量是一個(gè)簡(jiǎn)單變量(使用 :=定義的)則認(rèn)為它是立即展開(kāi)的,其它情況時(shí)都被認(rèn)為是“延后”展開(kāi)的變量。

3.9.2 條件語(yǔ)句
所有使用到條件語(yǔ)句在產(chǎn)生分支的地方,make程序會(huì)根據(jù)預(yù)設(shè)條件將正確地分支展開(kāi)。就是說(shuō)條件分支的展開(kāi)是“立即”的。其中包括:“ifdef”、“ifeq”、“ifndef”和“ifneq”所確定的所有分支命令。

3.9.3 規(guī)則的定義
所有的規(guī)則在make執(zhí)行時(shí),都按照如下的模式展開(kāi):



IMMEDIATE : IMMEDIATE ; DEFERRED

DEFERRED



其中,規(guī)則中目標(biāo)和依賴(lài)如果引用其他的變量,則被立即展開(kāi)。而規(guī)則的命令行中的變量引用會(huì)被延后展開(kāi)。此模板適合所有的規(guī)則,包括明確規(guī)則、模式規(guī)則、后綴規(guī)則、靜態(tài)模式規(guī)則。

3.10 總結(jié)
make的執(zhí)行過(guò)程如下:

1. 依次讀取變量“MAKEFILES”定義的makefile文件列表

2. 讀取工作目錄下的makefile文件(根據(jù)命名的查找順序“GNUmakefile”,“makefile”,“Makefile”,首先找到那個(gè)就讀取那個(gè))

3. 依次讀取工作目錄makefile文件中使用指示符“include”包含的文件

4. 查找重建所有已讀取的makefile文件的規(guī)則(如果存在一個(gè)目標(biāo)是當(dāng)前讀取的某一個(gè)makefile文件,則執(zhí)行此規(guī)則重建此makefile文件,完成以后從第一步開(kāi)始重新執(zhí)行)

5. 初始化變量值并展開(kāi)那些需要立即展開(kāi)的變量和函數(shù)并根據(jù)預(yù)設(shè)條件確定執(zhí)行分支

6. 根據(jù)“終極目標(biāo)”以及其他目標(biāo)的依賴(lài)關(guān)系建立依賴(lài)關(guān)系鏈表

7. 執(zhí)行除“終極目標(biāo)”以外的所有的目標(biāo)的規(guī)則(規(guī)則中如果依賴(lài)文件中任一個(gè)文件的時(shí)間戳比目標(biāo)文件新,則使用規(guī)則所定義的命令重建目標(biāo)文件)

8. 執(zhí)行“終極目標(biāo)”所在的規(guī)則



執(zhí)行一個(gè)規(guī)則的過(guò)程:

對(duì)于一個(gè)存在的規(guī)則(明確規(guī)則和隱含規(guī)則)首先,make比較目標(biāo)文件和所有的依賴(lài)文件的時(shí)間戳。如果目標(biāo)的時(shí)間戳比所有依賴(lài)文件的時(shí)間戳更新(依賴(lài)文件 在上一次執(zhí)行make之后沒(méi)有被修改),那么什么也不做。否則(依賴(lài)文件中的某一個(gè)或者全部在上一次執(zhí)行make后已經(jīng)被修改過(guò)),規(guī)則所定義的重建目標(biāo) 的命令將會(huì)被執(zhí)行。這就是make工作的基礎(chǔ),也是其執(zhí)行規(guī)制所定義命令的依據(jù)。(后續(xù)討論規(guī)則時(shí)將會(huì)對(duì)此詳細(xì)地說(shuō)明)

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購(gòu)買(mǎi)等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶 評(píng)論公約

    類(lèi)似文章 更多