??? 經(jīng)常使用Windows平臺(tái)IDE做開(kāi)發(fā)的人員,可能對(duì)于makefile多少有些陌生桶至。因?yàn)閃indows下的IDE通常都將這一步封裝了昼伴,只提供編譯按鈕,不需要開(kāi)發(fā)人員人為地參與這個(gè)過(guò)程镣屹。Unix/Linux下軟件開(kāi)發(fā)工程項(xiàng)目需要開(kāi)發(fā)者自己編寫(xiě)makefile文件亩码。從某種程度上來(lái)講,熟練編寫(xiě)makefile文件也說(shuō)明了開(kāi)發(fā)者具備完成大型工程的一個(gè)方面地能力野瘦。
??? makefile關(guān)系到整個(gè)工程的編譯規(guī)則。通常一個(gè)大型的軟件工程項(xiàng)目擁有的源文件往往不計(jì)其數(shù)飒泻。按照工程化的思想鞭光,這些不計(jì)其數(shù)的源文件按照功能、模塊分別需要放在規(guī)劃好的不同的目錄中泞遗。而makefile則定義了一系列的規(guī)則來(lái)指定源文件的編譯順序惰许,以及哪些文件需要重新編譯更新,甚至一些比較復(fù)雜的編譯操作史辙。通常編寫(xiě)好makefile文件后汹买,就可以執(zhí)行make命令進(jìn)行自動(dòng)化編譯,從而提高開(kāi)發(fā)效率聊倔。迄今為止晦毙,make工具是應(yīng)用最為廣泛,也是使用最多的工具耙蔑。下面主要介紹makefile編寫(xiě)的基本規(guī)則和命令使用见妒。更多的makefile的使用會(huì)在后續(xù)加以講述。
1.makefile基本規(guī)范
??? 一個(gè)典型的makefile文件包含目標(biāo)文件甸陌、編譯連接過(guò)程以及刪除編譯產(chǎn)生的目標(biāo)文件和依賴文件须揣。其基本的構(gòu)成形式如下所示盐股。
[目標(biāo)文件…]:先決條件…
command
…
…
clean:
rm …
??? 其中,目標(biāo)文件可以為生成的最終可執(zhí)行程序耻卡、中間工程文件以及具體執(zhí)行動(dòng)作等疯汁。先決條件就是生成目標(biāo)文件所需要依賴的文件。這些文件生成的規(guī)則在下面的command中實(shí)現(xiàn)卵酪。通常幌蚊,只要先決條件中有一個(gè)文件比目標(biāo)文件新的話,command命令就會(huì)被執(zhí)行凛澎。這就是makefile的基本規(guī)則霹肝。為了能讓初學(xué)者有一個(gè)清晰的認(rèn)識(shí),這里一個(gè)完整的實(shí)際例子如下所示塑煎。
testMain : a.o b.o testMain.o??????????????????????? //目標(biāo)文件為程序名testMain沫换,它依賴a.o b.o testMain.o三個(gè)中間文件
g++ a.o b.o testMain.o -o testMain??? //具體執(zhí)行程序編譯的命令
testMain.o :????????????????????????????????????????????????????? //目標(biāo)文件為testMain.o中間文件命令執(zhí)行
g++ -c testMain.cpp????????????????????????????? //具體程序編譯成中間文件testMain.o的命令執(zhí)行
a.o : a.h a.cpp???????????????????????????????????????????????? //目標(biāo)文件為a.o中間文件命令執(zhí)行,依賴于a.h a.cpp文件
g++ -c a.cpp?????????????????????????????????????????? //具體程序編譯成中間文件a.o的命令執(zhí)行
b.o : b.h b.cpp???????????????????????????????????????????????? //目標(biāo)文件為b.o中間文件命令執(zhí)行最铁,依賴于b.h b.cpp文件
g++ -c b.cpp?????????????????????????????????????????? //具體程序編譯成中間文件b.o的命令執(zhí)行
clean :?????????????????????????????????????????????????????????????? //清理程序目錄動(dòng)作
rm -f testMain core *.o???????????????????????? //具體程序中清除文件的操作命令
??? 如上例子中讯赏,整個(gè)程序文件包含2個(gè)頭文件,3個(gè)C++源文件冷尉。上述例子可以保存為makefile漱挎、Makefile或者任意可以命名的文件。用戶可以通過(guò)make命令加-f選項(xiàng)來(lái)指定執(zhí)行哪個(gè)makefile文件雀哨。
??? 根據(jù)上述實(shí)例配置的makefile在當(dāng)前目錄執(zhí)行后的過(guò)程如下所示磕谅。
[developer @localhost ~]$ make
g++ -c a.cpp
g++ -c b.cpp
g++ -c testMain.cpp
g++ a.o b.o testMain.o -o testMain
[developer @localhost ~]$ make clean
rm -f testMain core *.o
[developer @localhost ~]$ make -f makefile
g++ -c a.cpp
g++ -c b.cpp
g++ -c testMain.cpp
g++ a.o b.o testMain.o -o testMain
??? 上述演示通過(guò)make命令執(zhí)行實(shí)例make文件,默認(rèn)情況下執(zhí)行的文件名稱為makefile雾棺,編譯代碼中間工程文件膊夹,最終完成可執(zhí)行程序編譯。也可以執(zhí)行make的clean命令清除生成的工程文件和可執(zhí)行程序文件捌浩,通過(guò)make的-f選項(xiàng)執(zhí)行指定的名為“makefile”編譯依賴關(guān)系定義文件放刨,最終生成可執(zhí)行程序。
??? 上述實(shí)例最終產(chǎn)生的一個(gè)目標(biāo)文件為可執(zhí)行程序testMain尸饺。它的生成依賴于a.o进统、b.o、testMain.o三個(gè)中間工程文件浪听。隨后下一行為其生成可執(zhí)行程序的具體命令螟碎。
??? 這里需要注意執(zhí)行具體命令的行,其開(kāi)頭一定要以Tab鍵開(kāi)作為空格馋辈,這是makefile的規(guī)定抚芦。下面依次是目標(biāo)文件、依賴文件和具體的執(zhí)行命令。最后有一個(gè)clean叉抡,這里的clean并不是像前面的作為目標(biāo)文件出現(xiàn)的尔崔,它是一個(gè)動(dòng)作。當(dāng)前shell下執(zhí)行make
??? clean命令時(shí)褥民,執(zhí)行其下面的具體清除目標(biāo)文件的命令季春。
2.makefile中使用變量
??? 通常工程實(shí)踐中,makefile文件會(huì)大量的使用變量定義消返。這也可能造成初學(xué)者學(xué)習(xí)makefile文件困難之處载弄。大型的工程項(xiàng)目中,源文件撵颊、目標(biāo)中間文件宇攻、庫(kù)等應(yīng)用非常的多。為了便于維護(hù)makefile文件倡勇,會(huì)使用變量來(lái)替換makefile中可能會(huì)發(fā)生變化的地方逞刷。例如,生成目標(biāo)文件所依賴的中間工程文件就可以采用變量來(lái)靈活替換妻熊。下面通過(guò)一個(gè)具體的實(shí)例給初學(xué)者對(duì)makefile應(yīng)用有一個(gè)初步的認(rèn)識(shí)夸浅。該makefile編輯如下所示。
OBJECTS=a.o b.o testMain.o????????????????????? //定義變量為OBJECTS扔役,表示a.o b.o testMain.o三個(gè)中間工程文件
CC=g++?????????????????????????????????????????????????????????? //定義變量為CC帆喇,表示使用g++編譯器
testMain: $(OBJECTS)????????????????????????????????? //目標(biāo)文件為可執(zhí)行程序testMain,依賴于變量OBJECTS的生成
$(CC) $(OBJECTS) -o testMain???????? //生成可執(zhí)行程序的命令亿胸,可以使用具體變量替換查看
testMain.o:?????????????????????????????????????????????????????? //目標(biāo)文件為中間文件testMain.o
$(CC) -c testMain.cpp????????????????????????? //生成中間文件testMain.o的具體命令
a.o:a.h a.cpp?????????????????????????????????????????????????? //目標(biāo)文件為中間文件a.o
$(CC) -c a.cpp?????????????????????????????????????? //生成中間文件a.o的具體命令
b.o:b.h b.cpp????????????????????????????????????????? ???????? //目標(biāo)文件為中間文件b.o
$(CC) -c b.cpp?????????????????????????????????????? //生成中間文件b.o的具體命令
clean:??????????????????????????????????????????????????????????????? //清理程序目錄動(dòng)作
rm -f testMain core $(OBJECTS)?????? //具體程序中清除文件的操作命令
??? 從之前的例子中可以看出坯钦,中間生成的工程文件在makefile中被使用了兩次。也就是說(shuō)侈玄,一旦有新的object文件加入時(shí)葫笼,就只需要修改兩處的先決條件。當(dāng)前的makefile文件比較簡(jiǎn)單拗馒,所以這里添加顯得不是很復(fù)雜。但是溯街,一旦makefile文件比較復(fù)雜后诱桂,就容易造成修改地方的遺漏。那么呈昔,這種變量定義使用的方式使得刪減或增加object文件只需要一處修改即可挥等,這樣makefile文件維護(hù)更加方便了。變量定義類似于C語(yǔ)言中宏的定義使用堤尾,變量基本定義形式很簡(jiǎn)單肝劲,取一個(gè)變量名之后,makefile文件中這樣定義。
OBJECTS=example1.o example2.o …
??? 變量?jī)?nèi)容可以換行辞槐,其后加“\”符號(hào)即可掷漱。另外,編譯器g++也可以采用變量來(lái)定義榄檬。在單個(gè)平臺(tái)下開(kāi)發(fā)通常只使用單一的C++編譯器卜范,但是Unix/Linux系統(tǒng)下C++編譯器有多種。不同平臺(tái)之間的程序移植帶來(lái)的C++編譯器置換鹿榜,為makefile維護(hù)帶來(lái)麻煩海雪。大型的軟件項(xiàng)目中可以將編譯器的變量放在單一的文件中,根據(jù)檢測(cè)系統(tǒng)的不同平臺(tái)替換不同的C++編譯器舱殿,為軟件在不同平臺(tái)的移植帶來(lái)極大的方便奥裸。
3.一種更為簡(jiǎn)便的方式
??? makefile文件還有一種更為簡(jiǎn)便的定義方式,那就是讓make程序自動(dòng)推導(dǎo)目標(biāo)文件及依賴文件之后的命令沪袭。上例修改之后如下所示湾宙。
OBJECTS=a.o b.o testMain.o????????????????????? //定義變量為OBJECTS,表示a.o b.o testMain.o三個(gè)中間工程文件
CC=g++???????????? ?????????????????????????????????????????????? //定義變量為CC枝恋,表示使用g++編譯器
testMain: $(OBJECTS)????????????????????????????????? //目標(biāo)文件為可執(zhí)行程序testMain创倔,依賴于變量OBJECTS的生成
$(CC) $(OBJECTS) -o testMain???????? //生成可執(zhí)行程序的命令,可以使用具體變量替換查看
a.o:a.h ??????????????????????????????????????????????????????????? //目標(biāo)文件為中間工程文件a.o焚碌,其生成依賴于頭文件a.h
b.o:b.h ??????????????????????????????????????????????????????????? //目標(biāo)文件為中間工程文件b.o畦攘,其生成依賴于頭文件b.h
clean:??????????????????????????????????????????????????????????????? //清理程序目錄動(dòng)作
rm -f testMain core $(OBJECTS)???????????????????? //具體程序中清除文件的操作命令
??? 如上所示,目標(biāo)文件為中間工程文件下具體執(zhí)行命令就不需要了十电。只要列出中間工程文件文件以及其依賴的頭文件知押,make可以自動(dòng)的推導(dǎo)出需要執(zhí)行的編譯的命令【槁睿可見(jiàn)make工具的功能是相當(dāng)?shù)膹?qiáng)大台盯。
??? make工具基本使用情況大致如上所述。這里只簡(jiǎn)單介紹基本makefile文件的組成及其使用情況畏线,更多的實(shí)際項(xiàng)目使用會(huì)在后面的項(xiàng)目實(shí)踐中詳細(xì)講述静盅。