




版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡介
1、目錄1簡介31.1準(zhǔn)備工作31.2Makefile介紹31.3規(guī)則簡介41.4make工作原理41.5使用變量51.6簡化命令51.7另一種風(fēng)格61.8清理62MAKEFILE72.1makefile名字72.2包含72.3MAKEFILE變量72.4如何重新生成makefile72.5重載makefile83規(guī)則83.1例子83.2規(guī)則的語法93.3通配符93.3.1通配符的缺陷93.3.2wildcard函數(shù)103.4目錄搜索103.4.1VPATH103.4.2選擇性搜索113.4.3使用自動(dòng)變量113.4.4目錄搜索和隱含規(guī)則123.5PHONY目標(biāo)123.6FORCE目標(biāo)133.7空
2、目標(biāo)133.8內(nèi)建的特殊目標(biāo)133.9一個(gè)規(guī)則多個(gè)目標(biāo)143.10一個(gè)目標(biāo)多條規(guī)則143.11靜態(tài)模式規(guī)則143.11.1語法153.11.2靜態(tài)模式規(guī)則和隱式規(guī)則153.12雙冒號規(guī)則163.13自動(dòng)生成依賴關(guān)系164編寫命令174.1回顯174.2執(zhí)行174.3并行執(zhí)行174.4錯(cuò)誤184.5中斷make184.6遞歸使用184.6.1MAKE變量194.6.2傳遞變量到子make195命令行參數(shù)206參考236.1指令236.2函數(shù)246.3自動(dòng)變量266.4特殊變量27GNU Make使用Make 程序最初設(shè)計(jì)是為了維護(hù)C程序文件防止不必要的重新編譯。在使用命令行編譯器的時(shí)候,修改了一
3、個(gè)工程中的頭文件,如何確保包含這個(gè)頭文件的所有文件都得到編譯?現(xiàn)在的版本生成是使用批處理程序,編譯那些文件依賴于程序的維護(hù)者,在模塊之間相互引用頭文件的情況下,要將所有需要重新編譯的文件找出來是一件痛苦的事情;在找到這些文件之后,修改批處理進(jìn)行編譯。實(shí)際上這些工作可以讓make程序來自動(dòng)完成,make工具對于維護(hù)一些具有相互依賴關(guān)系的文件特別有用,它對文件和命令的聯(lián)系(在文件改變時(shí)調(diào)用來更新其它文件的程序)提供一套編碼方法。Make工具的基本概念類似于Proglog語言,你告訴make需要做什么,提供一些規(guī)則,make來完成剩下的工作。1 簡介make工作自動(dòng)確定工程的哪部分需要重新編譯,執(zhí)行
4、命令去編譯它們。雖然make多用于C程序,然而只要提供命令行的編譯器,你可以將其用于任何語言。實(shí)際上,make工具的應(yīng)用范圍不僅于編程,你可以描述任和一些文件改變需要自動(dòng)更新另一些文件的任務(wù)來使用它。1.1 準(zhǔn)備工作如果要使用make,你必須寫一個(gè)叫做“makefile”的文件,這個(gè)文件描述工程中文件之間的關(guān)系,提供更新每個(gè)文件的命令。典型的工程是這樣的:可執(zhí)行文件靠目標(biāo)文件來更新,目標(biāo)文件靠編譯源文件來更新。Makefile寫好之后,每次更改了源文件后,只要執(zhí)行make就足夠了,所有必要的重新編譯將執(zhí)行。Make程序利用makefile中的數(shù)據(jù)庫和文件的最后修改時(shí)間來確定那個(gè)文件需要更新;對
5、于需要更新的文件,make執(zhí)行數(shù)據(jù)庫中記錄的命令。可以提供命令行參數(shù)給make來控制那個(gè)文件需要重新編譯。1.2 Makefile介紹Makefile文件告訴make做什么,多數(shù)情況是怎樣編譯和鏈接一個(gè)程序。這里有一個(gè)簡單的makefile,描述如何編譯鏈接由8個(gè)C文件和3個(gè)頭文件組成的一個(gè)編輯器:edit : main.o kbd.o command.o display.o insert.o serach.o files.o utils.occ o edit main.o kbd.o command.o display.o insert.o search.o files.o utils.om
6、ain.o : main.c defs.hcc c main.ckdb.o : kbd.c defs.h command.hcc c kbd.ccommand.o : command.c defs.h command.hcc -c command.cdisplay.o : display.c defs.h buffer.hcc -c display.cinsert.o : insert.c defs.h buffer.hcc -c insert.csearch.o : search.c defs.h buffer.hcc -c search.cfiles.o : files.c defs.h
7、buffer.h command.hcc -c files.cutils.o : utils.c defs.hcc -c utils.cclean :rm edit main.o kbd.o command.o display.o insert.o search.o files.o utils.o將長行用分開便于閱讀,這和使用一個(gè)長行的作用是一樣的。使用這個(gè)makefile創(chuàng)建可執(zhí)行文件“edit”時(shí)運(yùn)行make就可以了;如果要將可執(zhí)行文件和目標(biāo)文件刪除,執(zhí)行make cleanmake重新編譯這個(gè)編輯器時(shí),每個(gè)更改的C文件必須重新編譯;如果頭文件更改了,每個(gè)包含頭文件的C文件必須重新編譯;每
8、次編譯產(chǎn)生一個(gè)對應(yīng)于原文件的目標(biāo)文件。最終,目標(biāo)文件鏈接在一起產(chǎn)生新的可執(zhí)行文件。1.3 規(guī)則簡介makefile中的規(guī)則是這樣的:TARGET : DEPENDENCIES COMMAND目標(biāo)(TARGET)程序產(chǎn)生的文件,如可執(zhí)行文件和目標(biāo)文件;目標(biāo)也可以是要執(zhí)行的動(dòng)作,如“clean”。依賴(DEPENDENCIES)是用來產(chǎn)生目標(biāo)的輸入文件,一個(gè)目標(biāo)通常依賴于多個(gè)文件。命令(COMMAND)是make執(zhí)行的動(dòng)作,一個(gè)可以有多個(gè)命令,每個(gè)占一行。注意:每個(gè)命令行的起始字符必須為TAB字符!有依賴關(guān)系規(guī)則中的命令通常在依賴文件變化時(shí)負(fù)責(zé)產(chǎn)生target文件,make執(zhí)行這些命令更新或產(chǎn)生t
9、arget。規(guī)則可以沒有依賴關(guān)系,如包含target “clean”的規(guī)則。規(guī)則解釋如何和何時(shí)重做該規(guī)則中的文件,make根據(jù)依賴關(guān)系執(zhí)行產(chǎn)生或更新目標(biāo);規(guī)則也說明如何和何時(shí)執(zhí)行動(dòng)作。有的規(guī)則看起來很復(fù)雜,但都符合上述模式。1.4 make工作原理缺省make從第一個(gè)target開始(第一個(gè)非 . 開始的target),這稱作缺省目標(biāo)。在上述的makefile中,缺省目標(biāo)是更新執(zhí)行程序edit,將這個(gè)目標(biāo)置于最前面。當(dāng)執(zhí)行make的時(shí)候,make程序從當(dāng)前目錄讀入makefile開始處理第一個(gè)規(guī)則;在例子中,這個(gè)規(guī)則是重新鏈接edit;在make處理這個(gè)規(guī)則之前,必須處理edit所依賴的那些文
10、件的規(guī)則,例子中是目標(biāo)文件。這些文件按照他們自己的規(guī)則處理:通過編譯源文件來更新每個(gè).o文件;當(dāng)依賴關(guān)系中的源文件或頭文件比目標(biāo)文件新,或目標(biāo)文件不存在時(shí),必須重新編譯。其它的規(guī)則被處理是因?yàn)樗麄兊膖arget是目標(biāo)的依賴,和目標(biāo)沒有依賴關(guān)系的規(guī)則不會(huì)被處理,除非指定make處理(如make clean)。在重新編譯目標(biāo)文件之前,make會(huì)試圖更新它的依賴:源文件和頭文件。例子中的makefile對源文件和頭文件未指定任何操作:.c和.h文件不是任何規(guī)則的目標(biāo)。確認(rèn)所有的目標(biāo)文件都是最新的之后,make決定是否重新鏈接edit:如果edit不存在,或者任何一個(gè)目標(biāo)文件都比它新,則鏈接工作將進(jìn)行
11、。這樣,如果我們改變insert.c運(yùn)行make,make會(huì)編譯這個(gè)文件來更新insert.o,然后鏈接edit;如果修改了command.h運(yùn)行make,kbd.o,command.o,files.o會(huì)重新生成,鏈接edit。1.5 使用變量在例子中,在規(guī)則edit中,目標(biāo)文件被列出來兩次:edit : main.o kbd.o command.o display.o insert.o search.o files.o utils.occ -o edit main.o kbd.o command.o display.o insert.o search.o files.o utils.o這樣的
12、重復(fù)容易出錯(cuò):假設(shè)工程中加入了一個(gè)新的目標(biāo)文件,可能只將其加入了一個(gè)列表中;通過使用變量可以消除這種風(fēng)險(xiǎn):變量允許一個(gè)預(yù)定義的字符串在多個(gè)地方被替換。在makefile中,可以寫這樣一行來定義object變量:objects = main.o kbd.o command.o display.o insert.o search.o files.o utils.o于是在需要目標(biāo)文件名列表的地方,使用$(object) 來代替變量的值。以下是使用了變量以后的makefile:objects = main.o kbd.o command.o display.o insert.o search.o fi
13、les.o utils.oedit : $(objects)cc -o edit $(objects)main.o : main.c defs.hcc -c main.ckbd.o : kbd.c defs.h command.hcc -c kbd.ccommand.o : command.c defs.h command.hcc -c command.cdisplay.o : display.c defs.h buffer.hcc -c display.cinsert.o : insert.c defs.h buffer.hcc -c insert.csearch.o : search.c
14、defs.h buffer.hcc -c search.cfiles.o : files.c defs.h buffer.h command.hcc -c files.cutils.o : utils.c defs.hcc -c utils.cclean :rm edit $(objects)1.6 簡化命令為每個(gè)文件寫出編譯命令不是必要的,因?yàn)閙ake可以自己來做;以.c文件更新.o文件有一個(gè)隱含的規(guī)則,使用cc -c命令。Make將利用cc c main.c o main.o來將main.c編譯為main.o,因此在生成目標(biāo)文件的規(guī)則中,可以省略命令。當(dāng).c文件以這樣的方式使用時(shí),將自動(dòng)加
15、入到依賴關(guān)系中;由是在省略命令的前提下,可以將.c文件從依賴關(guān)系中省略。以下是簡化過的makefile:objects = main.o kbd.o command.o display.o insert.o search.o files.o utils.oedit : $(objects) cc -o edit $(objects)main.o : defs.hkbd.o : defs.h command.hcommand.o : defs.h command.hdisplay.o : defs.h buffer.hinsert.o : defs.h buffer.hsearch.o : de
16、fs.h buffer.hfiles.o : defs.h buffer.h command.hutils.o : defs.h.PHONY : cleanclean : -rm edit $(objects)1.7 另一種風(fēng)格如果makefile中的目標(biāo)都是以隱含規(guī)則生成,可以將規(guī)則按照依賴關(guān)系分組:objects = main.o kbd.o command.o display.o insert.o search.o files.o utils.oedit : $(objects) cc -o edit $(objects)$(objects) : defs.hkbd.o command.
17、o files.o : command.hdisplay.o insert.o search.o files.o : buffer.h這里defs.h作為所有目標(biāo)文件的依賴。這種風(fēng)格是好是壞取決于個(gè)人喜好,它非常緊湊,但是將每個(gè)目標(biāo)的依賴信息放在一起看起來更清楚一些。1.8 清理編寫規(guī)則不至于編譯程序。Makefile通常描述如何做其它事情:比如刪除目錄中的目標(biāo)文件和可執(zhí)行文件來清理目錄。例子中是這樣寫的:clean: rm edit $(objects)實(shí)際情況是,我們需要處理一些意外事件:存在一個(gè)叫做clean的文件;如果rm出錯(cuò),并不希望make過程停止下來,修改過的版本如下:.PHON
18、Y : cleanclean : -rm edit $(objects)這樣的規(guī)則當(dāng)然不能放在makefile的開始,因?yàn)檫@并不是我們?nèi)笔∫龅墓ぷ?。由于clean并不是edit的依賴,在運(yùn)行make時(shí)沒有參數(shù)時(shí),這條規(guī)則不會(huì)執(zhí)行;要執(zhí)行這個(gè)規(guī)則,必須運(yùn)行make clean。2 MakefileMakefile中包含五種內(nèi)容:顯式規(guī)則,隱式規(guī)則,變量定義,指令(directive)和注釋。l 顯式規(guī)則描述如何生成規(guī)則的目標(biāo),它列出了目標(biāo)依賴的文件,指定了產(chǎn)生或更新目標(biāo)的命令l 隱式規(guī)則描述如何生成基于文件名的一類文件,說明目標(biāo)可能依賴于和其文件名類似的文件,指定了相應(yīng)的命令。l 指令類似與編
19、譯器的偽指令,包含:ü 指示make讀入另一個(gè)makefileü 決定是否忽略makefile中的一部分ü 定義一個(gè)變量l 一行中#開始是注釋,直到行末,除非遇到續(xù)行符號。在define和命令中不能有注釋,其它情況下注釋可出現(xiàn)在任何地方。2.1 makefile名字缺省情況下,make以下列名字查找makefile:GNUmakefile,makefile和Makefile(注意大小寫)。通常你的makefile應(yīng)叫做makefile或Makefile。GNUmakefile不推薦,除非你的makefile是為GNU的make定制的,其它的make不認(rèn)為該名字是一
20、個(gè)makefile的名字。如果你使用非標(biāo)準(zhǔn)命名的makefile,必須用命令開關(guān)-f 或 file。參數(shù) f NAME或file NAME告訴make讀入NAME作為makefile。如果使用多個(gè)該開關(guān),所有的文件將按順序連接起來。如果使用該選項(xiàng),標(biāo)準(zhǔn)的makefile名字不會(huì)自動(dòng)檢測。2.2 包含include指令告訴make暫停處理余下的內(nèi)容,讀入其它makefile。語法如下:include FILENAMES 這一行起始可以有空格,但TAB字符不允許。如果文件名包含變量或函數(shù),這些將被擴(kuò)展。2.3 MAKEFILE變量如果環(huán)境變量MAKEFILE已定義,make認(rèn)為它的值是一系列空格隔
21、開的文件名,這些文件在處理其它makefile前被make程序讀入。這類似于include指令;這些文件中的目標(biāo)不會(huì)影響缺省目標(biāo),而且如果文件未找到的話,make并不認(rèn)為是錯(cuò)誤。這個(gè)變量的主要用途是遞歸引用make程序時(shí)通訊2.4 如何重新生成makefile有時(shí)候makefile是從其它文件生成的,比如RCS或SCCS文件。如果makefile是由其它文件生成的,需要make讀入最新版本的makefile。在讀入所有makefile之后,make認(rèn)為每個(gè)makefile是一個(gè)目標(biāo),試圖去更新它;如果makefile中有一條如何更新它的規(guī)則,或者有適用的隱式規(guī)則,需要的更新會(huì)進(jìn)行。所有的mak
22、efile檢查完之后,如果有的改變了,make重新開始再讀入(make會(huì)試圖再做更新,但通常不會(huì)再改變了,因?yàn)橐呀?jīng)是最新的了)。如果一個(gè)文件使用雙冒號規(guī)則,提供了命令但沒有依賴關(guān)系,文件始終會(huì)被更新。在makefile的情況下,如果makefile雙冒號規(guī)則,提供了命令但沒有依賴關(guān)系,這樣makefile始終會(huì)重新生成,這會(huì)導(dǎo)致循環(huán):make只是在不斷更新makefile,卻不干活。為避免這種情況,make不會(huì)重新生成那些只有命令沒有依賴關(guān)系的雙冒號規(guī)則的makefile。如果沒有使用-f或-file選項(xiàng),make會(huì)嘗試缺省的makefile文件名。和指明-f或-file選項(xiàng)不同,make不能
23、確定這些文件是否應(yīng)當(dāng)存在。然而,如果缺省makefile不存在但可以通過運(yùn)行make規(guī)則生成,你可能希望這些規(guī)則被運(yùn)行使得makefile可以使用。因此,如果沒有缺省makefile,make試圖按照makefile名查找的順序生成它,直到成功或名字用完。注意如果make 不能找到或生成makefile,這并不是錯(cuò)誤;makefile不總是必需的。當(dāng)使用-t或-touch選項(xiàng)時(shí),不希望使用過時(shí)的makefile來決定那個(gè)目標(biāo)來touch。所以-t選項(xiàng)對makefile更新不起作用;類似-q(or question)和-n(or just-print)不阻止makefile的更新,因?yàn)檫^時(shí)的ma
24、kefile會(huì)產(chǎn)生錯(cuò)誤的輸出。這樣make f mfile n foo會(huì)更新mfile,讀入它,打印出更新foo需要執(zhí)行的命令但不運(yùn)行這些命令。與foo有關(guān)的命令是更新過的mfile中的內(nèi)容。但是有時(shí)不希望更新makefile,可以將makefile作為命令行的目標(biāo),當(dāng)makefile被顯式指定為目標(biāo)時(shí),-t選項(xiàng)也適用于它們。這樣make f mfile n mfile foo會(huì)讀入mfile,打印出更新執(zhí)行的命令,foo的命令是當(dāng)前的mfile中的內(nèi)容。2.5 重載makefile可以使用include指令來包含其它makefile,增加目標(biāo)的變量定義。然而,make不允許同一個(gè)目標(biāo)有不同的
25、命令,有其它的途徑可以達(dá)到目的。假設(shè)有makefile 和mfile,makfile要包含mfile,但都有對于目標(biāo)foo的規(guī)則。這是可以在makefile中寫一條匹配任意模式的規(guī)則,指明當(dāng)make在makefile中未找到目標(biāo)時(shí),搜索mfile:foo: frobnicate > foo%: force $(MAKE) -f mfile $ force: ;當(dāng)執(zhí)行make foo時(shí),make找到makefile,執(zhí)行命令 frobnicate > foo;執(zhí)行make bar時(shí),在makefile中未找到相應(yīng)的規(guī)則,這時(shí)模式規(guī)則適用,執(zhí)行命令make f mfile bar,ma
26、kefile中未提及的其它目標(biāo)也是類似的。這種方法之所有工作是因?yàn)槟J揭?guī)則的模式是%,可以匹配任何的目標(biāo);這條規(guī)則的依賴是force,保證即使目標(biāo)存在命令也會(huì)執(zhí)行;force規(guī)則的命令為空防止make為其搜索隱式規(guī)則這樣會(huì)導(dǎo)致依賴循環(huán)。3 規(guī)則makefile中的規(guī)則描述如何生成特定的文件,即規(guī)則的目標(biāo)。規(guī)則列出了目標(biāo)的依賴文件,指定生成或更新目標(biāo)的命令。規(guī)則的次序是不重要的,除非是確定缺省目標(biāo):缺省目標(biāo)是第一個(gè)makefile中的第一個(gè)規(guī)則;如果第一個(gè)規(guī)則有多個(gè)目標(biāo),第一個(gè)目標(biāo)是缺省的。有兩個(gè)例外:以.開頭的目標(biāo)不是缺省目標(biāo);模式規(guī)則對缺省目標(biāo)沒有影響。通常我們所寫的地一個(gè)規(guī)則是編譯整個(gè)或m
27、akefile中指定的所有程序。3.1 例子foo.o : foo.c defs.h # module for twiddling the frobscc -c -g foo.c它的目標(biāo)是foo.o,依賴于foo.c和defs.h,有一個(gè)命令cc c g foo.c。命令行以TAB字符開始標(biāo)識它是一個(gè)命令。這條規(guī)則說明兩件事:l 如何決定foo.o是舊的:如果它不存在,或者foo.c或者defs.h比它新。l 如何更新foo.o文件:通過運(yùn)行cc程序。命令未提及defs.h,擔(dān)可以猜想foo.c包含了它,這是defs.h被置于依賴關(guān)系中的理由。3.2 規(guī)則的語法語法如下:TARGETS : D
28、EPENDENCIESCOMMAND.或者TARGETS : DEPENDENCIES ; COMMANDCOMMAND.TARGETS是以空格隔開的文件名,統(tǒng)配符可以使用。通常一個(gè)規(guī)則只有一個(gè)目標(biāo),偶爾也有多個(gè)。命令行以TAB鍵開始。第一條命令可在依賴關(guān)系的下一行;或者在同一行,在分號后面;兩種方式效果相同。因?yàn)?符號被用做變量引用,如果要在規(guī)則中使用$符號,必須寫兩個(gè):$。可以用符號來分割一個(gè)長行,這不是必須的,因?yàn)閙ake對行的長度沒有限制。3.3 通配符規(guī)則中的文件名可以包含統(tǒng)配符,如*,?。文件名前的字符有特殊的含義。單獨(dú)使用,或跟隨一個(gè)/,代表用戶的home目錄,比如/bin擴(kuò)展為
29、/home/you/bin;如果跟隨一個(gè)單詞,表示單詞指示的那個(gè)用戶的home目錄,如john/bin擴(kuò)展為/home/john/bin。通配符在目標(biāo),依賴關(guān)系,命令中自動(dòng)擴(kuò)展,其它情況下,統(tǒng)配符的擴(kuò)展除非顯式使用wildcard函數(shù)。通配符的特殊意義可以使用符號關(guān)閉。例子:clean: rm -f *.o和print: *.c lpr -p $? touch print通配符在定義變量時(shí)并不擴(kuò)展,例如:objects = *.o則objects的值是字符串*.o;但是如果你將objects用于目標(biāo),依賴或命令中,擴(kuò)展會(huì)進(jìn)行。要將objects設(shè)置成擴(kuò)展過的內(nèi)容,使用:objects := $
30、(wildcard *.o)3.3.1 通配符的缺陷這是一個(gè)使用通配符的例子,但結(jié)果不是你所期望的。假設(shè)可執(zhí)行文件foo是從當(dāng)前目錄中的所有.o文件生成的:objects = *.ofoo : $(objects) cc -o foo $(CFLAGS) $(objects)objects變量的值是字符串*.o。通配符擴(kuò)展在規(guī)則foo中進(jìn)行,于是所有存在的.o文件成為foo的依賴而且在需要時(shí)重新編譯。但如果刪除了所有的.o文件呢?當(dāng)通配符不匹配任何文件時(shí),一切都保持原樣:則foo依賴于一個(gè)叫做*.o的文件;由于這個(gè)文件不大可能存在,make程序會(huì)報(bào)告一個(gè)無法生成*.o文件的錯(cuò)誤,這不是期待的結(jié)
31、果。實(shí)際上可以用通配符獲得期望結(jié)果,但是需要復(fù)雜的技術(shù),包括wildcard函數(shù)和字符串替換函數(shù)。3.3.2 wildcard函數(shù)通配符自動(dòng)在規(guī)則中進(jìn)行。但是在變量賦值的和函數(shù)的參數(shù)中通配符不會(huì)擴(kuò)展,如果在這些情況下需要通配符擴(kuò)展,必須使用wildcard函數(shù)。語法如下:$(wildcard PATTERN.)這個(gè)在makefile任何地方出現(xiàn)的字符串,會(huì)被匹配任何一個(gè)文件名格式的以空格隔開的現(xiàn)有文件列表替換。如果沒有任何文件匹配一個(gè)模式,這個(gè)模式從wildcard的輸出中忽略,注意,這和上述的通配符的處理是不一樣的。wildcard函數(shù)的一個(gè)功能是找出目錄中所有的.c文件:$(wildcar
32、d *.c)可以通過替換后綴.c為.o從C文件列表得到目標(biāo)文件的列表:$(patsubst %.c,%.o,$(wildcard *.c)這樣,上節(jié)中的makefile改寫為:objects := $(patsubst %.c,%.o,$(wildcard *.c)foo : $(objects) cc -o foo $(objects)這個(gè)makefile利用了編譯C程序的隱含規(guī)則,所以不需要對編譯寫出顯式的規(guī)則。(:=是=的一個(gè)變體)注意:PATTERN是大小寫敏感的。3.4 目錄搜索對于大的系統(tǒng),通常將源文件和目標(biāo)文件放在不同的目錄中。目錄搜索功能可以讓make自動(dòng)在多個(gè)目錄中搜尋依賴文
33、件,當(dāng)你將文件重新分布是,不需要改變規(guī)則,更改搜索路徑即可。3.4.1 VPATHmake變量VPATH列出make應(yīng)當(dāng)搜索的目錄列表。很多情況下,當(dāng)前目錄不包含依賴文件,VPATH描述一個(gè)對所有文件的搜索列表,包含那些是規(guī)則的目標(biāo)的文件。如果一個(gè)目標(biāo)或者依賴文件在當(dāng)前目錄沒找到的話,make在VPATH中列出的目錄中查找同名的文件。如果找到的話,那個(gè)文件成為依賴文件;規(guī)則可以象這些文件在當(dāng)前目錄中一樣來使用他們。在VPATH變量中,目錄名以冒號或空格隔開;目錄列出的順序決定make查找的順序。(注:在pSOSystem 2.5移植到Win32的GNU make目錄名必須使用分號隔開,以下均簡
34、稱Win32 GNU make)。舉例說明:VPATH = src:./headers 則規(guī)則foo.o : foo.c 被解釋為foo.o : src/foo.c假設(shè)foo.c在當(dāng)前目錄不存在,在src目錄中可以找到。3.4.2 選擇性搜索與VPATH變量相似但更具選擇性的是vpath指令(注意是小寫),可以指定對于符合特定模式文件的查找路徑。這樣可以為不同類型的文件指定不同的搜索路徑。vpath指令共有三中形式:l vpath PATTERN DIRECTORIES為匹配PATTERN的文件名指定搜索路徑DIRECTORIES,目錄的分隔和VPATH的相同l vpath PATTERN清除
35、為匹配PATTERN的文件名指定的搜索路徑l vpath清除所有以前用vpath指定的搜索路徑vpath的模式是包含%的字符串:這個(gè)字符串必須匹配需要搜索的依賴文件名,%字符匹配0個(gè)或多個(gè)任意字符。例如:%.h匹配任何以.h結(jié)尾的文件(如果沒有%,則PATTERN必須和依賴文件完全一致,這種用法不太多)。當(dāng)當(dāng)前目錄中不存在依賴文件時(shí),如果vpath中的PATTERN匹配依賴文件名,則指令中DIRECTORIES列出的目錄和VPATH中同樣處理。舉例:vpath %.h ./headers告訴make在當(dāng)前目錄中未找到的.h文件在./headers目錄中查找。如果多個(gè)vapth的模式匹配依賴文件
36、名,make將逐一處理,在所有指定的目錄中搜索。Make按照vapth在makefile中的次序;來處理它們,多個(gè)相同模式的vapth是相互獨(dú)立的。vpath %.c foovpath % blishvpath %.c bar將按照foo,blish,bar的次序查找.c文件。而vpath %.c foo:barvpath % blish按照foo,bar,blish的順序搜索。3.4.3 使用自動(dòng)變量目錄搜索的結(jié)果并不改變規(guī)則中的命令:命令按原樣被執(zhí)行。因此,必須寫出與目錄搜索功相適應(yīng)的命令。這可以通過使用$這樣的自動(dòng)變量來完成。$表示規(guī)則中的所有依賴文件,包含它們所在的目錄名(參見目錄搜索
37、);$表示目標(biāo)。例如:foo.o : foo.ccc -c $(CFLAGS) $ -o $通常情況下,依賴文件也包含頭文件,但命令中并不提及這些文件:變量$<表示第一個(gè)依賴文件:VPATH = src:./headersfoo.o : foo.c defs.h hack.hcc c $(CFLAGS) $< -o $3.4.4 目錄搜索和隱含規(guī)則使用VPATH和vpath指定目錄搜索也會(huì)影響隱含規(guī)則。例如:文件foo.o沒有顯式規(guī)則,make會(huì)考慮隱式規(guī)則:如果foo.c存在則編譯它;如果這個(gè)文件不存在,則在相應(yīng)的目錄中查找;如果foo.c在任一的目錄中存在,則C編譯的隱式規(guī)則被
38、應(yīng)用。隱式規(guī)則的命令使用自動(dòng)變量通常是必要的,這樣無需其它努力即可以使用目錄搜索得到的文件名。3.5 PHONY目標(biāo)Phony目標(biāo)并非實(shí)際的文件名:只是在顯式請求時(shí)執(zhí)行命令的名字。有兩種理由需要使用phony目標(biāo):避免和同名文件沖突,改善性能。如果編寫一個(gè)規(guī)則,并不產(chǎn)生目標(biāo)文件,則其命令在每次make該目標(biāo)時(shí)都執(zhí)行。例如:clean:rm *.o temp因?yàn)閞m命令并不產(chǎn)生clean文件,則每次執(zhí)行make clean的時(shí)候,該命令都會(huì)執(zhí)行。如果目錄中出現(xiàn)了clean文件,則規(guī)則失效了:沒有依賴文件,文件clean始終是最新的,命令永遠(yuǎn)不會(huì)執(zhí)行;為避免這個(gè)問題,可使用.PHONY指明該目標(biāo)。
39、如:.PHONY : clean這樣執(zhí)行make clean會(huì)無視clean文件存在與否。已知phony目標(biāo)并非是由其它文件生成的實(shí)際文件,make會(huì)跳過隱含規(guī)則搜索。這就是聲明phony目標(biāo)會(huì)改善性能的原因,即使你并不擔(dān)心實(shí)際文件存在與否。完整的例子如下:.PHONY : cleanclean :rm *.o tempphony目標(biāo)不應(yīng)是真正目標(biāo)文件的依賴。如果這樣,每次make在更新此文件時(shí),命令都會(huì)執(zhí)行。只要phony目標(biāo)不是真正目標(biāo)的依賴,規(guī)則的命令只有在指定此目標(biāo)時(shí)才執(zhí)行。Phony目標(biāo)可以有依賴關(guān)系。當(dāng)一個(gè)目錄中有多個(gè)程序是,將其放在一個(gè)makefile中會(huì)更方便。因?yàn)槿笔∧繕?biāo)是m
40、akefile中的第一個(gè)目標(biāo),通常將這個(gè)phony目標(biāo)叫做all,其依賴文件為各個(gè)程序:all : prog1 prog2 prog3.PHONY : allprog1 : prog1.o utils.o cc -o prog1 prog1.o utils.oprog2 : prog2.o cc -o prog2 prog2.oprog3 : prog3.o sort.o utils.o cc -o prog3 prog3.o sort.o utils.o這樣,使用make將可以將三個(gè)程序都生成了。當(dāng)一個(gè)phony目標(biāo)是另一個(gè)的依賴,其作用相當(dāng)于子程序,例如:.PHONY: cleanall
41、cleanobj cleandiffcleanall : cleanobj cleandiff rm programcleanobj : rm *.ocleandiff : rm *.diff3.6 FORCE目標(biāo)當(dāng)規(guī)則沒有依賴關(guān)系也沒有命令,而且其目標(biāo)不是存在的文件名,make認(rèn)為此規(guī)則運(yùn)行時(shí)這個(gè)目標(biāo)總是被更新。這意味著如果規(guī)則依賴于此目標(biāo),其命令總是被執(zhí)行。clean: FORCE rm $(objects)FORCE:例中目標(biāo)FORCE滿足這種特殊條件,這樣依賴于它的目標(biāo)clean被強(qiáng)制執(zhí)行其命令。名字FORCE沒有特殊含義,只不過通常這樣用而已。這種方式使用FORCE和.PHONY :
42、 clean效果相同。使用.PHONY更加明確高效,擔(dān)不是所有的make都支持;這樣許多makefile中使用了FORCE。3.7 空目標(biāo)空目標(biāo)(empty target)是phony目標(biāo)的變種:用來執(zhí)行顯式請求的一個(gè)動(dòng)作。和phony目標(biāo)不同的是:這個(gè)目標(biāo)文件可以真實(shí)存在,擔(dān)文件的內(nèi)容無關(guān)緊要,通常是空的。空目標(biāo)文件的目的是利用其最后修改時(shí)間來記錄命令最近一次執(zhí)行的時(shí)間,這是通過使用touch命令更新目標(biāo)文件來達(dá)到的。print: foo.c bar.c lpr -p $? touch print利用這條規(guī)則,執(zhí)行make print時(shí)如果自上次make print之后任一文件改變了,lpr
43、命令會(huì)執(zhí)行。自動(dòng)變量$?是為了只打印出那些變化了的文件。3.8 內(nèi)建的特殊目標(biāo)某些名字作為目標(biāo)存在時(shí)有特殊含義。 .PHONY該目標(biāo)的依賴被認(rèn)為是phony目標(biāo),處理這些目標(biāo)時(shí),命令無條件被執(zhí)行,不管文件名是否存在及其最后修改時(shí)間 .SUFFIXES該目標(biāo)的依賴被認(rèn)為是一個(gè)后綴列表,在檢查后綴規(guī)則時(shí)使用 .DEFAULT該目標(biāo)的規(guī)則被使用在沒有規(guī)則(顯式的或隱含的)的目標(biāo)上。如果DEFAULT命令定義了,則對所有不是規(guī)則目標(biāo)的依賴文件都會(huì)執(zhí)行該組命令 .PRECIOUS該目標(biāo)的依賴文件會(huì)受到特別對待:如果make被kill或命令的執(zhí)行被中止,這些目標(biāo)并不刪除;而且如果該目標(biāo)是中間文件,在不需要
44、時(shí)不會(huì)被刪除。可以將隱含規(guī)則的目標(biāo)模式(如%.o)做為.PRECIOUS的依賴文件,這樣可以保存這些規(guī)則產(chǎn)生的中間文件。 .INTERMEDIATE該目標(biāo)的依賴文件被當(dāng)作中間文件;如果該目標(biāo)沒有依賴文件,則makefile中所有的目標(biāo)文件均被認(rèn)為是中間文件。 .IGNORE在執(zhí)行該目標(biāo)的依賴規(guī)則的命令時(shí),make會(huì)忽略錯(cuò)誤,此規(guī)則本身的命令沒有意義。如果該規(guī)則沒有依賴關(guān)系,表示忽略所有命令執(zhí)行的錯(cuò)誤,這種用法只是為了向后兼容;由于會(huì)影響到所有的命令,所以不是特別有用,推薦使用其它更有選擇性忽略錯(cuò)誤的方法。 .SILENT在執(zhí)行該目標(biāo)的依賴規(guī)則的命令時(shí),make并不打印命令本身。該規(guī)則的命令沒有
45、意義。在.SILIENT沒有依賴關(guān)系時(shí),表示執(zhí)行makefile中的所有命令都不會(huì)打印,該規(guī)則只是為了向后兼容提供的。 .EXPORT_ALL_VARIABLES只是作為一個(gè)目標(biāo)存在,指示make將所有變量輸出到子進(jìn)程中。定義的隱含規(guī)則的后綴作為目標(biāo)時(shí),也認(rèn)為它是特殊目標(biāo);兩個(gè)后綴的連接也是一樣,比如.c.o。這些目標(biāo)是后綴規(guī)則,一中定義隱式規(guī)則的過時(shí)方法(但仍然廣泛使用)。后綴通常以.開始,所以特殊目標(biāo)也以.開始。3.9 一個(gè)規(guī)則多個(gè)目標(biāo)一條有多個(gè)目標(biāo)的規(guī)則和寫多條規(guī)則,每條一個(gè)目標(biāo)作用是等同的。同樣的命令應(yīng)用于所有目標(biāo),但其效用會(huì)因?qū)?shí)際目標(biāo)以$代替而不同。規(guī)則中所有目標(biāo)的依賴關(guān)系是一樣的
46、。這在兩種情況下有用:只有依賴關(guān)系,不需要命令。例如:kbd.o command.o files.o: command.h 所有的目標(biāo)同樣的命令。命令不需要完全相同,因?yàn)樵诿钪锌梢允褂?:bigoutput littleoutput : text.g generate text.g -$(subst output,$) > $和bigoutput : text.g generate text.g -big > bigoutputlittleoutput : text.g generate text.g -little > littleoutput等同。這里假設(shè)程序gener
47、ate產(chǎn)生兩種輸出:一種使用-big選項(xiàng),一種使用-little選項(xiàng)。如果想象使用$變化命令那樣來變化依賴關(guān)系,不能通過多目標(biāo)的普通規(guī)則實(shí)現(xiàn),但是可以通過模式規(guī)則來實(shí)現(xiàn)。3.10 一個(gè)目標(biāo)多條規(guī)則一個(gè)文件可以是多條規(guī)則的目標(biāo),所有規(guī)則的依賴關(guān)系被合并。如果目標(biāo)比任一個(gè)依賴文件舊,命令被執(zhí)行。一個(gè)文件只能有一組命令執(zhí)行。如果多個(gè)規(guī)則對于同一個(gè)文件都給出了命令,make使用最后一組并打印錯(cuò)誤信息(特殊情況:如果文件名以.開始,并不打印錯(cuò)誤信息,這一點(diǎn)是為了和其它make兼容)。沒有任何理由需要將makefile寫成這樣,這是make給出錯(cuò)誤信息的理由。一條只有依賴關(guān)系的附加規(guī)則可以一次給出許多文件
48、的附加依賴文件。例如objects變量表示系統(tǒng)中編譯器的所有輸出.,說明當(dāng)config.h更改時(shí)所有文件必須重做的簡單方法如下: objects = foo.o bar.o foo.o : defs.h bar.o : defs.h test.h $(objects) : config.h不用改變實(shí)際目標(biāo)文件生成的規(guī)則,這條規(guī)則可以在需要增刪附加的依賴關(guān)系時(shí)插入或提出。另一個(gè)訣竅是附加的依賴關(guān)系可以用變量表示,在make執(zhí)行時(shí),可以給變量賦值:extradeps=$(objects) : $(extradeps)當(dāng)命令make extradeps=foo.h'執(zhí)行時(shí)會(huì)認(rèn)為foo.h是每
49、個(gè)目標(biāo)文件的依賴文件,但簡單的make命令不是這樣。3.11 靜態(tài)模式規(guī)則靜態(tài)模式規(guī)則(static pattern rules)可以指定多個(gè)目標(biāo),并且使用目標(biāo)名字來建議依賴文件的名字;比普通多目標(biāo)規(guī)則更通用因?yàn)椴恍枰蕾囮P(guān)系是相同的:依賴關(guān)系必須類似但不需要相同。3.11.1 語法TARGETS .: TARGET-PATTERN: DEP-PATTERNS . COMMANDS .TARGETS列表指出規(guī)則應(yīng)用的目標(biāo),可以包含通配符,于普通規(guī)則的目標(biāo)相同。TARGET-PATTERN和DEP-PATTERNS來表明目標(biāo)的依賴關(guān)系如何計(jì)算:匹配TARGET-PATTERN的目標(biāo)從名字中抽出一
50、部分,叫做詞干(stem),詞干被替換到DEP-PATTERNS來形成依賴文件名。每個(gè)模式通常包含一個(gè)%字符。當(dāng)TARGET-PATTERN匹配一個(gè)目標(biāo)時(shí),%字符可以匹配目標(biāo)名中的任何部分;這部分即是詞干,模式的其余部分必須完全匹配。例如foo.o匹配%.o,foo是詞干;目標(biāo)foo.c和foo.out并不匹配這個(gè)模式。目標(biāo)的依賴文件名通過將DEP-PATTERNS中的%替換為詞干形成:如果依賴模式為%.c,在替換詞干foo可以得到foo.c。依賴模式中不包含%也是合法的,此依賴文件對所有的目標(biāo)均有效。如果需要在模式規(guī)則中使用%字符,必須在其前面加字符,如果%前的字符是有實(shí)際意義的,必須在其前
51、面加,其它的不必如此處理。如the%weird%pattern在有效的%前是the%weird,其后是pattern。最后的保持原樣是因?yàn)槠洳⒉挥绊?字符。以下例子從相應(yīng)的.c文件編譯foo.o和bar.o:objects = foo.o bar.o$(objects): %.o: %.c $(CC) -c $(CFLAGS) $< -o $每個(gè)目標(biāo)必須匹配目標(biāo)模式,對于不匹配的目標(biāo)會(huì)給出警告。如果列表中只有部分文件匹配模式,可以使用filter函數(shù)移去不匹配的文件名:files = foo.elc bar.o lose.o$(filter %.o,$(files): %.o: %.c
52、$(CC) -c $(CFLAGS) $< -o $(filter %.elc,$(files): %.elc: %.el emacs -f batch-byte-compile $<例子中$(filter %.o,$(files)' 結(jié)果是bar.o lose.o; $(filter %.elc,$(files)' 的結(jié)果是foo.elc'。以下例子說明$*的使用:bigoutput littleoutput : %output : text.g generate text.g -$* > $命令generate'執(zhí)行時(shí),$*擴(kuò)展為詞干big
53、或little。3.11.2 靜態(tài)模式規(guī)則和隱式規(guī)則靜態(tài)模式規(guī)則和隱式規(guī)則在作為模式規(guī)則是具有很多共同點(diǎn),都有目標(biāo)模式和構(gòu)造依賴文件名的模式,不同之處在于make決定何時(shí)應(yīng)用規(guī)則的方法。隱式規(guī)則可應(yīng)用于匹配其模式的任何目標(biāo),但只限于沒有指定命令的目標(biāo),如果有多條可應(yīng)用的隱式規(guī)則,只有一條被使用,取決于規(guī)則的順序。反之,靜態(tài)模式規(guī)則適用于規(guī)則中明確目標(biāo)列表,不適用于其它目標(biāo)且總是適用于指定的每個(gè)目標(biāo)。如果有兩條沖突的規(guī)則,且都有命令,這是一個(gè)錯(cuò)誤。靜態(tài)模式規(guī)則比隱式規(guī)則優(yōu)越之處如下: 可為一些不能按句法分類,但可以顯式列出的文件重載隱式規(guī)則 不能判定目錄中的精確內(nèi)容,一些無關(guān)的文件可能導(dǎo)致make適用錯(cuò)誤的隱式規(guī)則;最終結(jié)果可能依賴于隱式規(guī)則的次序。適用靜態(tài)模式規(guī)則時(shí),這種不確定性是不存在的:規(guī)則適用于明確指定的目標(biāo)。3.12 雙冒號規(guī)則雙冒號規(guī)則(Double-colon rules)的目標(biāo)后是:而不是:,當(dāng)一個(gè)目標(biāo)出現(xiàn)在多條規(guī)則中時(shí),其處理和普通規(guī)則的處理不同。當(dāng)一個(gè)目標(biāo)出現(xiàn)在多條規(guī)則中時(shí),所有規(guī)則必須是相同類型的:都是普通的或者都是雙冒號的。如果是雙冒號,規(guī)則之間相互獨(dú)立;如果目標(biāo)需要更新,則規(guī)則的命令被執(zhí)行;結(jié)果可能是沒有執(zhí)行,或者執(zhí)行了其中一些,
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲(chǔ)空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 鍛造生產(chǎn)工藝員考試試卷及答案
- 2025年南平事業(yè)單位真題
- 高原環(huán)境下低空空域的研究與挑戰(zhàn)
- 2024年麗水云和縣招聘事業(yè)編制教師真題
- 昌吉吉盛新型建材二期工業(yè)硅項(xiàng)目綜合循環(huán)水泵站水泵技術(shù)協(xié)議
- 教育變革背景下的在線教育平臺政策分析
- 教育行業(yè)的數(shù)據(jù)泄露預(yù)防與應(yīng)對措施
- 數(shù)字時(shí)代的教育變革傳統(tǒng)教學(xué)與數(shù)字教材的結(jié)合
- 企業(yè)園區(qū)安全防范的智能化升級方案
- 中職文案寫作課件
- 2025年初級消防設(shè)施操作員職業(yè)技能鑒定考試試卷真題(后附專業(yè)解析)
- 腎癌的護(hù)理課件教學(xué)
- (零診)成都市2023級(2026屆)高三高中畢業(yè)班摸底測試語文試卷(含答案)
- 國家職業(yè)技能標(biāo)準(zhǔn)-半導(dǎo)體分立器件和集成電路裝調(diào)工
- 2024新版(外研版三起孫有中)三年級英語上冊單詞帶音標(biāo)
- 保障性租賃住房申請表
- 2023年中智總部及直屬單位個(gè)高管職位公開招聘筆試參考題庫附帶答案詳解
- iqc培訓(xùn)教材基礎(chǔ)課件
- 中等職業(yè)學(xué)校藝術(shù)課程標(biāo)準(zhǔn)(2020年版)(word精排版)
- GB/T 15435-1995環(huán)境空氣二氧化氮的測定Saltzman法
- GB/T 1355-2021小麥粉
評論
0/150
提交評論