【正文】
GNU Make version April 2000Richard M. Stallman and Roland McGrath1 Make概述Make 可自動(dòng)決定一個(gè)大程序中哪些文件需要重新編譯,并發(fā)布重新編譯它們的命令。本版本GNU Make使用手冊(cè)由Richard M. Stallman and Roland McGrath編著,是從Paul D. 。GNU Make符合IEEE Standard () 。因?yàn)镃語言程序更具有代表性,所以我們的例子基于C語言程序,但Make并不是僅僅能夠處理C語言程序,它可以處理那些編譯器能夠在Shell命令下運(yùn)行的的各種語言的程序。事實(shí)上,GNU Make不僅僅限于程序,它可以適用于任何如果一些文件變化導(dǎo)致另外一些文件必須更新的任務(wù)。如果要使用Make,必須先寫一個(gè)稱為Makefile的文件,該文件描述程序中各個(gè)文件之間的相互關(guān)系,并且提供每一個(gè)文件的更新命令。在一個(gè)程序中,可執(zhí)行程序文件的更新依靠OBJ文件,而OBJ文件是由源文件編譯得來的。一旦合適的Makefile文件存在,每次更改一些源文件,在shell命令下簡(jiǎn)單的鍵入:make就能執(zhí)行所有的必要的重新編譯任務(wù)。Make程序根據(jù)Makefile文件中的數(shù)據(jù)和每個(gè)文件更改的時(shí)間戳決定哪些文件需要更新。對(duì)于這些需要更新的文件,Make基于Makefile文件發(fā)布命令進(jìn)行更新,進(jìn)行更新的方式由提供的命令行參數(shù)控制。具體操作請(qǐng)看運(yùn)行Make章節(jié)。 怎樣閱讀本手冊(cè)如果你現(xiàn)在對(duì)Make一無所知或者你僅需要了解對(duì)make 的普通性介紹,請(qǐng)查閱前幾章內(nèi)容,略過后面的章節(jié)。前幾章節(jié)是普通介紹性內(nèi)容,后面的章節(jié)是具體的專業(yè)、技術(shù)內(nèi)容。如果你對(duì)其它Make程序十分熟悉,請(qǐng)參閱GNU Make的特點(diǎn)和不兼容性和失去的特點(diǎn)部分,GNU Make的特點(diǎn)這一章列出了GNU Make對(duì)make程序的擴(kuò)展,不兼容和失去的特點(diǎn)一章解釋了其它Make程序有的特征而GNU Make缺乏的原因。對(duì)于快速瀏覽者,請(qǐng)參閱選項(xiàng)概要、快速參考和內(nèi)建的特殊目標(biāo)名部分。 問題和BUG如果你有關(guān)于GNU Make的問題或者你認(rèn)為你發(fā)現(xiàn)了一個(gè)BUG,請(qǐng)向開發(fā)者報(bào)告;我們不能許諾我們能干什么,但我們會(huì)盡力修正它。在報(bào)告BUG之前,請(qǐng)確定你是否真正發(fā)現(xiàn)了BUG,仔細(xì)研究文檔后確認(rèn)它是否真的按你的指令運(yùn)行。如果文檔不能清楚的告訴你怎么做,也要報(bào)告它,這是文檔的一個(gè)BUG。在你報(bào)告或者自己親自修正BUG之前,請(qǐng)把它分離出來,即在使問題暴露的前提下盡可能的縮小Makefile文件。然后把這個(gè)Makefile文件和Make給出的精確結(jié)果發(fā)給我們。同時(shí)請(qǐng)說明你希望得到什么,這可以幫助我們確定問題是否出在文檔上。一旦你找到一個(gè)精確的問題,請(qǐng)給我們發(fā)Email,我們的Email地址是:bugmake@在郵件中請(qǐng)包含你使用的GNU Make的版本號(hào)。你可以利用命令‘makeversion’得到版本號(hào)。同時(shí)希望你提供你的機(jī)器型號(hào)和操作系統(tǒng)類型,如有可能的話,(該文件有配置過程產(chǎn)生)。2 Makefile文件介紹Make程序需要一個(gè)所謂的Makefile文件來告訴它干什么。在大多數(shù)情況下,Makefile文件告訴Make怎樣編譯和連接成一個(gè)程序。本章我們將討論一個(gè)簡(jiǎn)單的Makefile文件,該文件描述怎樣將8個(gè)C源程序文件和3個(gè)頭文件編譯和連接成為一個(gè)文本編輯器。Makefile文件可以同時(shí)告訴Make怎樣運(yùn)行所需要的雜亂無章的命令(例如,清除操作時(shí)刪除特定的文件)。如果要看更詳細(xì)、復(fù)雜的Makefile文件例子,請(qǐng)參閱復(fù)雜的Makefile文件例子一章。當(dāng)Make重新編譯這個(gè)編輯器時(shí),所有改動(dòng)的C語言源文件必須重新編譯。如果一個(gè)頭文件改變,每一個(gè)包含該頭文件的C語言源文件必須重新編譯,這樣才能保證生成的編輯器是所有源文件更新后的編輯器。每一個(gè)C語言源文件編譯后產(chǎn)生一個(gè)對(duì)應(yīng)的OBJ文件,如果一個(gè)源文件重新編譯,所有的OBJ文件無論是剛剛編譯得到的或原來編譯得到的必須從新連接,形成一個(gè)新的可執(zhí)行文件。 規(guī)則的格式一個(gè)簡(jiǎn)單的Makefile文件包含一系列的“規(guī)則”,其樣式如下:目標(biāo)(target)…: 依賴(prerequiries)…tab命令(mand) … …目標(biāo)(target)通常是要產(chǎn)生的文件的名稱,目標(biāo)的例子是可執(zhí)行文件或OBJ文件。目標(biāo)也可是一個(gè)執(zhí)行的動(dòng)作名稱,諸如‘clean’(詳細(xì)內(nèi)容請(qǐng)參閱假想目標(biāo)一節(jié))。依賴是用來輸入從而產(chǎn)生目標(biāo)的文件,一個(gè)目標(biāo)經(jīng)常有幾個(gè)依賴。命令是Make執(zhí)行的動(dòng)作,一個(gè)規(guī)則可以含有幾個(gè)命令,每個(gè)命令占一行。注意:每個(gè)命令行前面必須是一個(gè)Tab字符,即命令行第一個(gè)字符是Tab。這是不小心容易出錯(cuò)的地方。通常,如果一個(gè)依賴發(fā)生變化,則需要規(guī)則調(diào)用命令對(duì)相應(yīng)依賴和服務(wù)進(jìn)行處理從而更新或創(chuàng)建目標(biāo)。但是,指定命令更新目標(biāo)的規(guī)則并不都需要依賴,例如,包含和目標(biāo)‘clean’相聯(lián)系的刪除命令的規(guī)則就沒有依賴。規(guī)則一般是用于解釋怎樣和何時(shí)重建特定的文件,這些特定文件是這個(gè)詳盡規(guī)則的目標(biāo)。Make需首先調(diào)用命令對(duì)依賴進(jìn)行處理,進(jìn)而才能創(chuàng)建或更新目標(biāo)。當(dāng)然,一個(gè)規(guī)則也可以是用于解釋怎樣和何時(shí)執(zhí)行一個(gè)動(dòng)作,詳見編寫規(guī)則一章。一個(gè)Makefile文件可以包含規(guī)則以外的其它文本,但一個(gè)簡(jiǎn)單的Makefile文件僅僅需要包含規(guī)則。雖然真正的規(guī)則比這里展示的例子復(fù)雜,但格式卻是完全一樣。 一個(gè)簡(jiǎn)單的Makefile文件一個(gè)簡(jiǎn)單的Makefile文件,該文件描述了一個(gè)稱為文本編輯器(edit)的可執(zhí)行文件生成方法,該文件依靠8個(gè)OBJ文件(.o文件),它們又依靠8個(gè)C源程序文件和3個(gè)頭文件。在這個(gè)例子中,所有的C語言源文件都包含‘’頭文件,但僅僅定義編輯命令的源文件包含‘’頭文件,僅僅改變編輯器緩沖區(qū)的低層文件包含‘’頭文件。edit : \ cc o edit \ : cc c : cc c : cc c : cc c : cc c : cc c : cc c : cc c clean : rm edit \ 我們把每一個(gè)長(zhǎng)行使用反斜杠新行法分裂為兩行或多行,實(shí)際上它們相當(dāng)于一行,這樣做的意圖僅僅是為了閱讀方便。使用Makefile文件創(chuàng)建可執(zhí)行的稱為‘edit’的文件,鍵入:make使用Makefile文件從目錄中刪除可執(zhí)行文件和目標(biāo),鍵入:make clean在這個(gè)Makefile文件例子中,目標(biāo)包括可執(zhí)行文件‘edit’和OBJ文件‘’及‘’。依賴是C語言源文件和C語言頭文件如‘’和‘’等。事實(shí)上,每一個(gè)OBJ文件即是目標(biāo)也是依賴。所以命令行包括‘cc c ’和‘cc c ’。當(dāng)目標(biāo)是一個(gè)文件時(shí),如果它的任意一個(gè)依賴發(fā)生變化,目標(biāo)必須重新編譯和連接。任何命令行的第一個(gè)字符必須是‘Tab’字符,這樣可以把Makefile文件中的命令行與其它行分別開來。(一定要牢記:Make并不知道命令是如何工作的,它僅僅能向你提供保證目標(biāo)的合適更新的命令。Make的全部工作是當(dāng)目標(biāo)需要更新時(shí),按照你制定的具體規(guī)則執(zhí)行命令。)目標(biāo)‘clean’不是一個(gè)文件,僅僅是一個(gè)動(dòng)作的名稱。正常情況下,在規(guī)則中‘clean’這個(gè)動(dòng)作并不執(zhí)行,目標(biāo)‘clean’也不需要任何依賴。一般情況下,除非特意告訴make執(zhí)行‘clean’命令,否則‘clean’命令永遠(yuǎn)不會(huì)執(zhí)行。注意這樣的規(guī)則不需要任何依賴,它們存在的目的僅僅是執(zhí)行一些特殊的命令。像這些不需要依賴僅僅表達(dá)動(dòng)作的目標(biāo)稱為假想目標(biāo)。詳細(xì)內(nèi)容參見假想目標(biāo);參閱命令錯(cuò)誤可以了解rm或其它命令是怎樣導(dǎo)致make忽略錯(cuò)誤的。 make處理makefile文件的過程缺省情況下,make開始于第一個(gè)目標(biāo)(假想目標(biāo)的名稱前帶‘.’)。這個(gè)目標(biāo)稱為缺省最終目標(biāo)(即make最終更新的目標(biāo),具體內(nèi)容請(qǐng)看指定最終目標(biāo)的參數(shù)一節(jié))。 在上節(jié)的簡(jiǎn)單例子中,缺省最終目標(biāo)是更新可執(zhí)行文件‘edit’,所以我們將該規(guī)則設(shè)為第一規(guī)則。這樣,一旦你給出命令:makemake就會(huì)讀當(dāng)前目錄下的makefile文件,并開始處理第一條規(guī)則。在本例中,第一條規(guī)則是連接生成‘edit’,但在make全部完成本規(guī)則工作之前,必須先處理‘edit’所依靠的OBJ文件。這些OBJ文件按照各自的規(guī)則被處理更新,每個(gè)OBJ文件的更新規(guī)則是編譯其源文件。重新編譯根據(jù)其依靠的源文件或頭文件是否比現(xiàn)存的OBJ文件更‘新’,或者OBJ文件是否存在來判斷。 其它規(guī)則的處理根據(jù)它們的目標(biāo)是否和缺省最終目標(biāo)的依賴相關(guān)聯(lián)來判斷。如果一些規(guī)則和缺省最終目標(biāo)無任何關(guān)聯(lián)則這些規(guī)則不會(huì)被執(zhí)行,除非告訴Make強(qiáng)制執(zhí)行(如輸入執(zhí)行make clean命令)。 在OBJ文件重新編譯之前,Make首先檢查它的依賴C語言源文件和C語言頭文件是否需要更新。如果這些C語言源文件和C語言頭文件不是任何規(guī)則的目標(biāo),make將不會(huì)對(duì)它們做任何事情。Make也可以自動(dòng)產(chǎn)生C語言源程序,這需要特定的規(guī)則,如可以根據(jù)Bison或Yacc產(chǎn)生C語言源程序。 在OBJ文件重新編譯(如果需要的話)之后,make決定是否重新連接生成edit可執(zhí)行文件。如果edit可執(zhí)行文件不存在或任何一個(gè)OBJ文件比存在的edit可執(zhí)行文件‘新’,則make重新連接生成edit可執(zhí)行文件。 這樣,如果我們修改了‘’文件,然后運(yùn)行make,make將會(huì)編譯‘’文件更新‘’文件,然后重新連接生成edit可執(zhí)行文件。如果我們修改了‘’文件,然后運(yùn)行make,make將會(huì)重新編譯‘’和‘’文件,然后重新連接生成edit可執(zhí)行文件。 使用變量簡(jiǎn)化makefile文件在我們的例子中,我們?cè)凇甧dit’的生成規(guī)則中把所有的OBJ文件列舉了兩次,這里再重復(fù)一遍:edit : \ cc o edit \ 這樣的兩次列舉有出錯(cuò)的可能,例如在系統(tǒng)中加入一個(gè)新的OBJ文件,我們很有可能在一個(gè)需要列舉的地方加入了,而在另外一個(gè)地方卻忘記了。我們使用變量可以簡(jiǎn)化makefile文件并且排除這種出錯(cuò)的可能。變量是定義一個(gè)字符串一次,而能在多處替代該字符串使用(具體內(nèi)容請(qǐng)閱讀使用變量一節(jié))。在makefile文件中使用名為objects, OBJECTS, objs, OBJS, obj, 或 OBJ的變量代表所有OBJ文件已是約定成俗。在這個(gè)makefile文件我們定義了名為objects的變量,其定義格式如下:objects = \ 然后,在每一個(gè)需要列舉OBJ文件的地方,我們使用寫為’$(objects)39。形式的變量代替(具體內(nèi)容請(qǐng)閱讀使用變量一節(jié))。下面是使用變量后的完整的makefile文件:objects = \ edit : $(objects) cc o edit $(objects) : cc c : cc c : cc c : cc c : cc c : cc c : cc c : cc c clean : rm edit $(objects) 讓make推斷命令編譯單獨(dú)的C語言源程序并不需要寫出命令,因?yàn)閙ake可以把它推斷出來:make有一個(gè)使用‘CC –c’命令的把C語言源程序編譯更新為相同文件名的OBJ文件的隱含規(guī)則。例如make可以自動(dòng)使用‘cc c o ’命令把‘’編譯 ‘’。因此,我們可以省略O(shè)BJ文件的更新規(guī)則。詳細(xì)內(nèi)容請(qǐng)看使用隱含規(guī)則一節(jié)。如果C語言源程序能夠這樣自動(dòng)編譯,則它同樣能夠自動(dòng)加入到依賴中。所以我們可在依賴中省略C語言源程序,進(jìn)而可以省略命令。下面是使用隱含規(guī)則和變量objects的完整makefile文件的例子:objects = \ edit : $(objects) cc o edit $(objects) : : : : : : : : .PHONY : cleanclean : rm edit $(objects)這是我們實(shí)際編寫makefile文件的例子。(和目標(biāo)‘clean’聯(lián)系的復(fù)雜情況在別處闡述。具體參見假想目標(biāo)及命令錯(cuò)誤兩節(jié)內(nèi)容。)因?yàn)殡[含規(guī)則十分方便,所以它們非常重要,在makefile文件中經(jīng)常使用它們。 另一種風(fēng)格的makefile文件當(dāng)時(shí)在makefile文件中使用隱含規(guī)則創(chuàng)建OBJ文件時(shí),采用另一種風(fēng)格的makefile文件也是可行的。在這種風(fēng)格的makefile文件中,可以依據(jù)依賴分組代替依據(jù)目標(biāo)分組。下面是采用這種風(fēng)格的makefile文件:objects = \ edit : $(objects) cc o edit $(objects)$(objects) : : : ;。雖然采用這種風(fēng)格編寫makefile文件更具風(fēng)味:makefile文件更加短小,但一部