由于用的是Chrome,上一篇的末尾不知道為何突然退出隧饼,點(diǎn)進(jìn)去好多次,依然是一有動(dòng)作就自動(dòng)退出。之前用插件馬克飛象的時(shí)候就出現(xiàn)過(guò)這種情況较解。好像跟字?jǐn)?shù)有關(guān)系艺挪,字?jǐn)?shù)超過(guò)上限就會(huì)崩潰厢塘。
接上次的尉桩。這種方法,也就是make的隱式規(guī)則妻献。上面文件內(nèi)容中蛛株,.PHONY
表示,clean是個(gè)偽目標(biāo)文件育拨。
另類風(fēng)格的makefile
既然我們的 make 可以自動(dòng)推導(dǎo)命令谨履,那么我看到那堆.o
和.h
的依賴就有點(diǎn)不爽,那么多的重復(fù)的.h]
熬丧,能不能把其收攏起來(lái)笋粟,其實(shí)這個(gè)對(duì)于make來(lái)說(shuō)還挺容易的。更為簡(jiǎn)潔的Makefile可以這樣寫(xiě):
objects = main.o kbd.o command.o display.o \
insert.o search.o files.o utils.o
edit: $(objects)
cc -o edit $(objects)
$(objects): defs.h
kbd.o command.o files.o : command.h
display.o insert.o search.o files.o: buffer.h
.PHONY: clean
clean:
rm edit $(objects)
這種風(fēng)格析蝴,讓我們的 makefile 變得很簡(jiǎn)單害捕,但我們的文件依賴關(guān)系就顯得有點(diǎn)凌亂了。魚(yú)和熊掌不可兼得闷畸。還得看個(gè)人喜好了尝盼。有些人是不喜歡這種風(fēng)格的,一是文件的依賴關(guān)系看不清楚佑菩,二是如果文件一多盾沫,要加入幾個(gè)新的.o
文件,那就理不清楚了殿漠。
清空目標(biāo)文件的規(guī)則
每個(gè)Makefile中都應(yīng)該寫(xiě)一個(gè)清空目標(biāo)文件(.o
和執(zhí)行文件)的規(guī)則赴精,這不僅便于重編譯,也很利于保持文件的清潔绞幌。一般的風(fēng)格都是:
clean:
rm edit $(objects)
更為穩(wěn)健的做法是:
.PHONY : clean
clean :
-rm edit $(objects)
前面說(shuō)過(guò)蕾哟,.PHONY
意思表示 clean 是一個(gè)偽目標(biāo)。而在rm命令前面加了一個(gè)減號(hào)的意思就是莲蜘,也許某些文件出現(xiàn)問(wèn)題谭确,但不要管,繼續(xù)做后面的事菇夸。當(dāng)然琼富,clean 的規(guī)則不要放在文件的開(kāi)頭仪吧,不然庄新,這就會(huì)變成make的默認(rèn)目標(biāo),相信誰(shuí)也不愿意這樣。不成文的規(guī)矩是——“clean從來(lái)都是放在文件的最后”择诈。
Makefile文件名規(guī)則
默認(rèn)的情況下械蹋,make命令會(huì)在當(dāng)前目錄下按順序找尋文件名為GNUmakefile
、makefile
羞芍、Makefile
的文件哗戈,找到了解釋這個(gè)文件。在這三個(gè)文件名中荷科,最好使用Makefile
這個(gè)文件名唯咬,因?yàn)椋@個(gè)文件名第一個(gè)字符為大寫(xiě)畏浆,這樣有一種顯目的感覺(jué)胆胰。最好不要用 GNUmakefile
,這個(gè)文件是GNU的 make 識(shí)別的刻获。有另外一些 make 只對(duì)全小寫(xiě)的makefile
文件名敏感蜀涨,但是基本上來(lái)說(shuō),大多數(shù)的 make 都支持makefile
和Makefile
這兩種默認(rèn)文件名蝎毡。
當(dāng)然厚柳,你可以使用別的文件名來(lái)書(shū)寫(xiě) Makefile,比如:Make.Linux
沐兵,Make.Solaris
别垮,Make.AIX
等,如果要指定特定的 Makefile扎谎,你可以使用 make 的-f
和--file
參數(shù)宰闰,如:make -f Make.Linux
或make --file Make.AIX
。
引用其他的Makefile
在Makefile使用include關(guān)鍵字可以把別的Makefile包含進(jìn)來(lái)簿透,這很像C語(yǔ)言的#include移袍,被包含的文件會(huì)原模原樣的放在當(dāng)前文件的包含位置。include的語(yǔ)法是:
include <filename>;
filename可以是當(dāng)前操作系統(tǒng)Shell的文件模式(可以包含路徑和通配符)老充。在include前面可以有一些空字符葡盗,但是絕不能是Tab
鍵開(kāi)始。include
和<filename>;
可以用一個(gè)或多個(gè)空格隔開(kāi)啡浊。
make 命令開(kāi)始時(shí)觅够,會(huì)找尋include
所指出的其它 Makefile,并把其內(nèi)容安置在當(dāng)前的位置巷嚣。就好像C/C++的#include
指令一樣喘先。如果文件都沒(méi)有指定絕對(duì)路徑或是相對(duì)路徑的話,make 會(huì)在當(dāng)前目錄下首先尋找廷粒,如果當(dāng)前目錄下沒(méi)有找到窘拯,那么红且,make還會(huì)在下面的幾個(gè)目錄下找:
- 如果make執(zhí)行時(shí),有
-I
或--include-dir
參數(shù)涤姊,那么make就會(huì)在這個(gè)參數(shù)所指定的目錄下去尋找暇番。 - 如果目錄
<prefix>/include
(一般是:/usr/local/bin
或/usr/include
)存在的話,make 也會(huì)去找思喊。
如果有文件沒(méi)有找到的話壁酬,make會(huì)生成一條警告信息,但不會(huì)馬上出現(xiàn)致命錯(cuò)誤恨课。它會(huì)繼續(xù)載入其它的文件舆乔,一旦完成makefile 的讀取, make 會(huì)再重試這些沒(méi)有找到剂公,或是不能讀取的文件蜕煌,如果還是不行,make 才會(huì)出現(xiàn)一條致命信息诬留。如果你想讓 make 不理那些無(wú)法讀取的文件斜纪,而繼續(xù)執(zhí)行,你可以在include
前加一個(gè)減號(hào)-
文兑。如:-include <filename>;
總結(jié)
根據(jù)以上細(xì)節(jié)盒刚,關(guān)于Makefile的的基本組成和工作的流程就可總結(jié)如下。
Makefile里主要包含了五個(gè)東西:顯式規(guī)則绿贞、隱式規(guī)則因块、變量定義、文件指示和注釋籍铁。
- 顯式規(guī)則涡上。顯式規(guī)則說(shuō)明了,如何生成一個(gè)或多個(gè)目標(biāo)文件拒名。要生成的文件吩愧,文件的依賴文件,生成的命令增显。
- 隱式規(guī)則雁佳。由于 make 有自動(dòng)推導(dǎo)的功能,所以隱式規(guī)則可以讓我們比較簡(jiǎn)略地書(shū)寫(xiě)Makefile同云。
- 變量的定義糖权。在Makefile中我們要定義一系列的變量,變量一般都是指代文件名或路徑名的字符串炸站,這個(gè)有點(diǎn)像C語(yǔ)言中的宏星澳,當(dāng) Makefile 被執(zhí)行時(shí),其中的變量都會(huì)被擴(kuò)展到相應(yīng)的引用位置上旱易。
-
文件指示禁偎。其包括了三個(gè)部分腿堤,一個(gè)是在一個(gè) Makefile 中引用另一個(gè) Makefile,就像C語(yǔ)言中的
include
一樣届垫;另一個(gè)是指根據(jù)某些情況指定 Makefile 中的有效部分,就像C語(yǔ)言中的預(yù)編譯#if
一樣全释;還有就是定義一個(gè)多行的命令装处。 -
注釋。Makefile 中只有行注釋浸船,和Linux的Shell腳本一樣妄迁,其注釋是用
#
字符,這個(gè)就像C/C++中的//
一樣李命。如果你要在你的 Makefile 中使用#
字符登淘,可以用反斜線進(jìn)行轉(zhuǎn)義,如:#
封字。
GNU的make工作時(shí)的執(zhí)行步驟如下:
- 讀入所有的Makefile黔州。
- 讀入被include的其它Makefile。
- 初始化文件中的變量阔籽。
- 推導(dǎo)隱式規(guī)則流妻,并分析所有規(guī)則。
- 為所有的目標(biāo)文件創(chuàng)建依賴關(guān)系鏈笆制。
- 根據(jù)依賴關(guān)系绅这,決定哪些目標(biāo)要重新生成。
- 執(zhí)行生成命令在辆。