




版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領
文檔簡介
1、目錄1簡介31.1準備工作31.2Makefile介紹31.3規(guī)則簡介41.4make工作原理41.5使用變量51.6簡化命令51.7另一種風格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函數103.4目錄搜索103.4.1VPATH103.4.2選擇性搜索113.4.3使用自動變量113.4.4目錄搜索和隱含規(guī)則123.5PHONY目標123.6FORCE目標133.7空
2、目標133.8內建的特殊目標133.9一個規(guī)則多個目標143.10一個目標多條規(guī)則143.11靜態(tài)模式規(guī)則143.11.1語法153.11.2靜態(tài)模式規(guī)則和隱式規(guī)則153.12雙冒號規(guī)則163.13自動生成依賴關系164編寫命令174.1回顯174.2執(zhí)行174.3并行執(zhí)行174.4錯誤184.5中斷make184.6遞歸使用184.6.1MAKE變量194.6.2傳遞變量到子make195命令行參數206參考236.1指令236.2函數246.3自動變量266.4特殊變量27GNU Make使用Make 程序最初設計是為了維護C程序文件防止不必要的重新編譯。在使用命令行編譯器的時候,修改了一
3、個工程中的頭文件,如何確保包含這個頭文件的所有文件都得到編譯?現在的版本生成是使用批處理程序,編譯那些文件依賴于程序的維護者,在模塊之間相互引用頭文件的情況下,要將所有需要重新編譯的文件找出來是一件痛苦的事情;在找到這些文件之后,修改批處理進行編譯。實際上這些工作可以讓make程序來自動完成,make工具對于維護一些具有相互依賴關系的文件特別有用,它對文件和命令的聯系(在文件改變時調用來更新其它文件的程序)提供一套編碼方法。Make工具的基本概念類似于Proglog語言,你告訴make需要做什么,提供一些規(guī)則,make來完成剩下的工作。1 簡介make工作自動確定工程的哪部分需要重新編譯,執(zhí)行
4、命令去編譯它們。雖然make多用于C程序,然而只要提供命令行的編譯器,你可以將其用于任何語言。實際上,make工具的應用范圍不僅于編程,你可以描述任和一些文件改變需要自動更新另一些文件的任務來使用它。1.1 準備工作如果要使用make,你必須寫一個叫做“makefile”的文件,這個文件描述工程中文件之間的關系,提供更新每個文件的命令。典型的工程是這樣的:可執(zhí)行文件靠目標文件來更新,目標文件靠編譯源文件來更新。Makefile寫好之后,每次更改了源文件后,只要執(zhí)行make就足夠了,所有必要的重新編譯將執(zhí)行。Make程序利用makefile中的數據庫和文件的最后修改時間來確定那個文件需要更新;對
5、于需要更新的文件,make執(zhí)行數據庫中記錄的命令。可以提供命令行參數給make來控制那個文件需要重新編譯。1.2 Makefile介紹Makefile文件告訴make做什么,多數情況是怎樣編譯和鏈接一個程序。這里有一個簡單的makefile,描述如何編譯鏈接由8個C文件和3個頭文件組成的一個編輯器: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將長行用分開便于閱讀,這和使用一個長行的作用是一樣的。使用這個makefile創(chuàng)建可執(zhí)行文件“edit”時運行make就可以了;如果要將可執(zhí)行文件和目標文件刪除,執(zhí)行make cleanmake重新編譯這個編輯器時,每個更改的C文件必須重新編譯;如果頭文件更改了,每個包含頭文件的C文件必須重新編譯;每
8、次編譯產生一個對應于原文件的目標文件。最終,目標文件鏈接在一起產生新的可執(zhí)行文件。1.3 規(guī)則簡介makefile中的規(guī)則是這樣的:TARGET : DEPENDENCIES COMMAND目標(TARGET)程序產生的文件,如可執(zhí)行文件和目標文件;目標也可以是要執(zhí)行的動作,如“clean”。依賴(DEPENDENCIES)是用來產生目標的輸入文件,一個目標通常依賴于多個文件。命令(COMMAND)是make執(zhí)行的動作,一個可以有多個命令,每個占一行。注意:每個命令行的起始字符必須為TAB字符!有依賴關系規(guī)則中的命令通常在依賴文件變化時負責產生target文件,make執(zhí)行這些命令更新或產生t
9、arget。規(guī)則可以沒有依賴關系,如包含target “clean”的規(guī)則。規(guī)則解釋如何和何時重做該規(guī)則中的文件,make根據依賴關系執(zhí)行產生或更新目標;規(guī)則也說明如何和何時執(zhí)行動作。有的規(guī)則看起來很復雜,但都符合上述模式。1.4 make工作原理缺省make從第一個target開始(第一個非 . 開始的target),這稱作缺省目標。在上述的makefile中,缺省目標是更新執(zhí)行程序edit,將這個目標置于最前面。當執(zhí)行make的時候,make程序從當前目錄讀入makefile開始處理第一個規(guī)則;在例子中,這個規(guī)則是重新鏈接edit;在make處理這個規(guī)則之前,必須處理edit所依賴的那些文
10、件的規(guī)則,例子中是目標文件。這些文件按照他們自己的規(guī)則處理:通過編譯源文件來更新每個.o文件;當依賴關系中的源文件或頭文件比目標文件新,或目標文件不存在時,必須重新編譯。其它的規(guī)則被處理是因為他們的target是目標的依賴,和目標沒有依賴關系的規(guī)則不會被處理,除非指定make處理(如make clean)。在重新編譯目標文件之前,make會試圖更新它的依賴:源文件和頭文件。例子中的makefile對源文件和頭文件未指定任何操作:.c和.h文件不是任何規(guī)則的目標。確認所有的目標文件都是最新的之后,make決定是否重新鏈接edit:如果edit不存在,或者任何一個目標文件都比它新,則鏈接工作將進行
11、。這樣,如果我們改變insert.c運行make,make會編譯這個文件來更新insert.o,然后鏈接edit;如果修改了command.h運行make,kbd.o,command.o,files.o會重新生成,鏈接edit。1.5 使用變量在例子中,在規(guī)則edit中,目標文件被列出來兩次: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、重復容易出錯:假設工程中加入了一個新的目標文件,可能只將其加入了一個列表中;通過使用變量可以消除這種風險:變量允許一個預定義的字符串在多個地方被替換。在makefile中,可以寫這樣一行來定義object變量:objects = main.o kbd.o command.o display.o insert.o search.o files.o utils.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 簡化命令為每個文件寫出編譯命令不是必要的,因為make可以自己來做;以.c文件更新.o文件有一個隱含的規(guī)則,使用cc -c命令。Make將利用cc c main.c o main.o來將main.c編譯為main.o,因此在生成目標文件的規(guī)則中,可以省略命令。當.c文件以這樣的方式使用時,將自動加
15、入到依賴關系中;由是在省略命令的前提下,可以將.c文件從依賴關系中省略。以下是簡化過的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 另一種風格如果makefile中的目標都是以隱含規(guī)則生成,可以將規(guī)則按照依賴關系分組: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作為所有目標文件的依賴。這種風格是好是壞取決于個人喜好,它非常緊湊,但是將每個目標的依賴信息放在一起看起來更清楚一些。1.8 清理編寫規(guī)則不至于編譯程序。Makefile通常描述如何做其它事情:比如刪除目錄中的目標文件和可執(zhí)行文件來清理目錄。例子中是這樣寫的:clean: rm edit $(objects)實際情況是,我們需要處理一些意外事件:存在一個叫做clean的文件;如果rm出錯,并不希望make過程停止下來,修改過的版本如下:.PHON
18、Y : cleanclean : -rm edit $(objects)這樣的規(guī)則當然不能放在makefile的開始,因為這并不是我們缺省要做的工作。由于clean并不是edit的依賴,在運行make時沒有參數時,這條規(guī)則不會執(zhí)行;要執(zhí)行這個規(guī)則,必須運行make clean。2 MakefileMakefile中包含五種內容:顯式規(guī)則,隱式規(guī)則,變量定義,指令(directive)和注釋。l 顯式規(guī)則描述如何生成規(guī)則的目標,它列出了目標依賴的文件,指定了產生或更新目標的命令l 隱式規(guī)則描述如何生成基于文件名的一類文件,說明目標可能依賴于和其文件名類似的文件,指定了相應的命令。l 指令類似與編
19、譯器的偽指令,包含:ü 指示make讀入另一個makefileü 決定是否忽略makefile中的一部分ü 定義一個變量l 一行中#開始是注釋,直到行末,除非遇到續(xù)行符號。在define和命令中不能有注釋,其它情況下注釋可出現在任何地方。2.1 makefile名字缺省情況下,make以下列名字查找makefile:GNUmakefile,makefile和Makefile(注意大小寫)。通常你的makefile應叫做makefile或Makefile。GNUmakefile不推薦,除非你的makefile是為GNU的make定制的,其它的make不認為該名字是一
20、個makefile的名字。如果你使用非標準命名的makefile,必須用命令開關-f 或 file。參數 f NAME或file NAME告訴make讀入NAME作為makefile。如果使用多個該開關,所有的文件將按順序連接起來。如果使用該選項,標準的makefile名字不會自動檢測。2.2 包含include指令告訴make暫停處理余下的內容,讀入其它makefile。語法如下:include FILENAMES 這一行起始可以有空格,但TAB字符不允許。如果文件名包含變量或函數,這些將被擴展。2.3 MAKEFILE變量如果環(huán)境變量MAKEFILE已定義,make認為它的值是一系列空格隔
21、開的文件名,這些文件在處理其它makefile前被make程序讀入。這類似于include指令;這些文件中的目標不會影響缺省目標,而且如果文件未找到的話,make并不認為是錯誤。這個變量的主要用途是遞歸引用make程序時通訊2.4 如何重新生成makefile有時候makefile是從其它文件生成的,比如RCS或SCCS文件。如果makefile是由其它文件生成的,需要make讀入最新版本的makefile。在讀入所有makefile之后,make認為每個makefile是一個目標,試圖去更新它;如果makefile中有一條如何更新它的規(guī)則,或者有適用的隱式規(guī)則,需要的更新會進行。所有的mak
22、efile檢查完之后,如果有的改變了,make重新開始再讀入(make會試圖再做更新,但通常不會再改變了,因為已經是最新的了)。如果一個文件使用雙冒號規(guī)則,提供了命令但沒有依賴關系,文件始終會被更新。在makefile的情況下,如果makefile雙冒號規(guī)則,提供了命令但沒有依賴關系,這樣makefile始終會重新生成,這會導致循環(huán):make只是在不斷更新makefile,卻不干活。為避免這種情況,make不會重新生成那些只有命令沒有依賴關系的雙冒號規(guī)則的makefile。如果沒有使用-f或-file選項,make會嘗試缺省的makefile文件名。和指明-f或-file選項不同,make不能
23、確定這些文件是否應當存在。然而,如果缺省makefile不存在但可以通過運行make規(guī)則生成,你可能希望這些規(guī)則被運行使得makefile可以使用。因此,如果沒有缺省makefile,make試圖按照makefile名查找的順序生成它,直到成功或名字用完。注意如果make 不能找到或生成makefile,這并不是錯誤;makefile不總是必需的。當使用-t或-touch選項時,不希望使用過時的makefile來決定那個目標來touch。所以-t選項對makefile更新不起作用;類似-q(or question)和-n(or just-print)不阻止makefile的更新,因為過時的ma
24、kefile會產生錯誤的輸出。這樣make f mfile n foo會更新mfile,讀入它,打印出更新foo需要執(zhí)行的命令但不運行這些命令。與foo有關的命令是更新過的mfile中的內容。但是有時不希望更新makefile,可以將makefile作為命令行的目標,當makefile被顯式指定為目標時,-t選項也適用于它們。這樣make f mfile n mfile foo會讀入mfile,打印出更新執(zhí)行的命令,foo的命令是當前的mfile中的內容。2.5 重載makefile可以使用include指令來包含其它makefile,增加目標的變量定義。然而,make不允許同一個目標有不同的
25、命令,有其它的途徑可以達到目的。假設有makefile 和mfile,makfile要包含mfile,但都有對于目標foo的規(guī)則。這是可以在makefile中寫一條匹配任意模式的規(guī)則,指明當make在makefile中未找到目標時,搜索mfile:foo: frobnicate > foo%: force $(MAKE) -f mfile $ force: ;當執(zhí)行make foo時,make找到makefile,執(zhí)行命令 frobnicate > foo;執(zhí)行make bar時,在makefile中未找到相應的規(guī)則,這時模式規(guī)則適用,執(zhí)行命令make f mfile bar,ma
26、kefile中未提及的其它目標也是類似的。這種方法之所有工作是因為模式規(guī)則的模式是%,可以匹配任何的目標;這條規(guī)則的依賴是force,保證即使目標存在命令也會執(zhí)行;force規(guī)則的命令為空防止make為其搜索隱式規(guī)則這樣會導致依賴循環(huán)。3 規(guī)則makefile中的規(guī)則描述如何生成特定的文件,即規(guī)則的目標。規(guī)則列出了目標的依賴文件,指定生成或更新目標的命令。規(guī)則的次序是不重要的,除非是確定缺省目標:缺省目標是第一個makefile中的第一個規(guī)則;如果第一個規(guī)則有多個目標,第一個目標是缺省的。有兩個例外:以.開頭的目標不是缺省目標;模式規(guī)則對缺省目標沒有影響。通常我們所寫的地一個規(guī)則是編譯整個或m
27、akefile中指定的所有程序。3.1 例子foo.o : foo.c defs.h # module for twiddling the frobscc -c -g foo.c它的目標是foo.o,依賴于foo.c和defs.h,有一個命令cc c g foo.c。命令行以TAB字符開始標識它是一個命令。這條規(guī)則說明兩件事:l 如何決定foo.o是舊的:如果它不存在,或者foo.c或者defs.h比它新。l 如何更新foo.o文件:通過運行cc程序。命令未提及defs.h,擔可以猜想foo.c包含了它,這是defs.h被置于依賴關系中的理由。3.2 規(guī)則的語法語法如下:TARGETS : D
28、EPENDENCIESCOMMAND.或者TARGETS : DEPENDENCIES ; COMMANDCOMMAND.TARGETS是以空格隔開的文件名,統(tǒng)配符可以使用。通常一個規(guī)則只有一個目標,偶爾也有多個。命令行以TAB鍵開始。第一條命令可在依賴關系的下一行;或者在同一行,在分號后面;兩種方式效果相同。因為$符號被用做變量引用,如果要在規(guī)則中使用$符號,必須寫兩個:$??梢杂梅杹矸指钜粋€長行,這不是必須的,因為make對行的長度沒有限制。3.3 通配符規(guī)則中的文件名可以包含統(tǒng)配符,如*,?。文件名前的字符有特殊的含義。單獨使用,或跟隨一個/,代表用戶的home目錄,比如/bin擴展為
29、/home/you/bin;如果跟隨一個單詞,表示單詞指示的那個用戶的home目錄,如john/bin擴展為/home/john/bin。通配符在目標,依賴關系,命令中自動擴展,其它情況下,統(tǒng)配符的擴展除非顯式使用wildcard函數。通配符的特殊意義可以使用符號關閉。例子:clean: rm -f *.o和print: *.c lpr -p $? touch print通配符在定義變量時并不擴展,例如:objects = *.o則objects的值是字符串*.o;但是如果你將objects用于目標,依賴或命令中,擴展會進行。要將objects設置成擴展過的內容,使用:objects := $
30、(wildcard *.o)3.3.1 通配符的缺陷這是一個使用通配符的例子,但結果不是你所期望的。假設可執(zhí)行文件foo是從當前目錄中的所有.o文件生成的:objects = *.ofoo : $(objects) cc -o foo $(CFLAGS) $(objects)objects變量的值是字符串*.o。通配符擴展在規(guī)則foo中進行,于是所有存在的.o文件成為foo的依賴而且在需要時重新編譯。但如果刪除了所有的.o文件呢?當通配符不匹配任何文件時,一切都保持原樣:則foo依賴于一個叫做*.o的文件;由于這個文件不大可能存在,make程序會報告一個無法生成*.o文件的錯誤,這不是期待的結
31、果。實際上可以用通配符獲得期望結果,但是需要復雜的技術,包括wildcard函數和字符串替換函數。3.3.2 wildcard函數通配符自動在規(guī)則中進行。但是在變量賦值的和函數的參數中通配符不會擴展,如果在這些情況下需要通配符擴展,必須使用wildcard函數。語法如下:$(wildcard PATTERN.)這個在makefile任何地方出現的字符串,會被匹配任何一個文件名格式的以空格隔開的現有文件列表替換。如果沒有任何文件匹配一個模式,這個模式從wildcard的輸出中忽略,注意,這和上述的通配符的處理是不一樣的。wildcard函數的一個功能是找出目錄中所有的.c文件:$(wildcar
32、d *.c)可以通過替換后綴.c為.o從C文件列表得到目標文件的列表:$(patsubst %.c,%.o,$(wildcard *.c)這樣,上節(jié)中的makefile改寫為:objects := $(patsubst %.c,%.o,$(wildcard *.c)foo : $(objects) cc -o foo $(objects)這個makefile利用了編譯C程序的隱含規(guī)則,所以不需要對編譯寫出顯式的規(guī)則。(:=是=的一個變體)注意:PATTERN是大小寫敏感的。3.4 目錄搜索對于大的系統(tǒng),通常將源文件和目標文件放在不同的目錄中。目錄搜索功能可以讓make自動在多個目錄中搜尋依賴文
33、件,當你將文件重新分布是,不需要改變規(guī)則,更改搜索路徑即可。3.4.1 VPATHmake變量VPATH列出make應當搜索的目錄列表。很多情況下,當前目錄不包含依賴文件,VPATH描述一個對所有文件的搜索列表,包含那些是規(guī)則的目標的文件。如果一個目標或者依賴文件在當前目錄沒找到的話,make在VPATH中列出的目錄中查找同名的文件。如果找到的話,那個文件成為依賴文件;規(guī)則可以象這些文件在當前目錄中一樣來使用他們。在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假設foo.c在當前目錄不存在,在src目錄中可以找到。3.4.2 選擇性搜索與VPATH變量相似但更具選擇性的是vpath指令(注意是小寫),可以指定對于符合特定模式文件的查找路徑。這樣可以為不同類型的文件指定不同的搜索路徑。vpath指令共有三中形式:l vpath PATTERN DIRECTORIES為匹配PATTERN的文件名指定搜索路徑DIRECTORIES,目錄的分隔和VPATH的相同l vpath PATTERN清除
35、為匹配PATTERN的文件名指定的搜索路徑l vpath清除所有以前用vpath指定的搜索路徑vpath的模式是包含%的字符串:這個字符串必須匹配需要搜索的依賴文件名,%字符匹配0個或多個任意字符。例如:%.h匹配任何以.h結尾的文件(如果沒有%,則PATTERN必須和依賴文件完全一致,這種用法不太多)。當當前目錄中不存在依賴文件時,如果vpath中的PATTERN匹配依賴文件名,則指令中DIRECTORIES列出的目錄和VPATH中同樣處理。舉例:vpath %.h ./headers告訴make在當前目錄中未找到的.h文件在./headers目錄中查找。如果多個vapth的模式匹配依賴文件
36、名,make將逐一處理,在所有指定的目錄中搜索。Make按照vapth在makefile中的次序;來處理它們,多個相同模式的vapth是相互獨立的。vpath %.c foovpath % blishvpath %.c bar將按照foo,blish,bar的次序查找.c文件。而vpath %.c foo:barvpath % blish按照foo,bar,blish的順序搜索。3.4.3 使用自動變量目錄搜索的結果并不改變規(guī)則中的命令:命令按原樣被執(zhí)行。因此,必須寫出與目錄搜索功相適應的命令。這可以通過使用$這樣的自動變量來完成。$表示規(guī)則中的所有依賴文件,包含它們所在的目錄名(參見目錄搜索
37、);$表示目標。例如:foo.o : foo.ccc -c $(CFLAGS) $ -o $通常情況下,依賴文件也包含頭文件,但命令中并不提及這些文件:變量$<表示第一個依賴文件:VPATH = src:./headersfoo.o : foo.c defs.h hack.hcc c $(CFLAGS) $< -o $3.4.4 目錄搜索和隱含規(guī)則使用VPATH和vpath指定目錄搜索也會影響隱含規(guī)則。例如:文件foo.o沒有顯式規(guī)則,make會考慮隱式規(guī)則:如果foo.c存在則編譯它;如果這個文件不存在,則在相應的目錄中查找;如果foo.c在任一的目錄中存在,則C編譯的隱式規(guī)則被
38、應用。隱式規(guī)則的命令使用自動變量通常是必要的,這樣無需其它努力即可以使用目錄搜索得到的文件名。3.5 PHONY目標Phony目標并非實際的文件名:只是在顯式請求時執(zhí)行命令的名字。有兩種理由需要使用phony目標:避免和同名文件沖突,改善性能。如果編寫一個規(guī)則,并不產生目標文件,則其命令在每次make該目標時都執(zhí)行。例如:clean:rm *.o temp因為rm命令并不產生clean文件,則每次執(zhí)行make clean的時候,該命令都會執(zhí)行。如果目錄中出現了clean文件,則規(guī)則失效了:沒有依賴文件,文件clean始終是最新的,命令永遠不會執(zhí)行;為避免這個問題,可使用.PHONY指明該目標。
39、如:.PHONY : clean這樣執(zhí)行make clean會無視clean文件存在與否。已知phony目標并非是由其它文件生成的實際文件,make會跳過隱含規(guī)則搜索。這就是聲明phony目標會改善性能的原因,即使你并不擔心實際文件存在與否。完整的例子如下:.PHONY : cleanclean :rm *.o tempphony目標不應是真正目標文件的依賴。如果這樣,每次make在更新此文件時,命令都會執(zhí)行。只要phony目標不是真正目標的依賴,規(guī)則的命令只有在指定此目標時才執(zhí)行。Phony目標可以有依賴關系。當一個目錄中有多個程序是,將其放在一個makefile中會更方便。因為缺省目標是m
40、akefile中的第一個目標,通常將這個phony目標叫做all,其依賴文件為各個程序: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將可以將三個程序都生成了。當一個phony目標是另一個的依賴,其作用相當于子程序,例如:.PHONY: cleanall
41、cleanobj cleandiffcleanall : cleanobj cleandiff rm programcleanobj : rm *.ocleandiff : rm *.diff3.6 FORCE目標當規(guī)則沒有依賴關系也沒有命令,而且其目標不是存在的文件名,make認為此規(guī)則運行時這個目標總是被更新。這意味著如果規(guī)則依賴于此目標,其命令總是被執(zhí)行。clean: FORCE rm $(objects)FORCE:例中目標FORCE滿足這種特殊條件,這樣依賴于它的目標clean被強制執(zhí)行其命令。名字FORCE沒有特殊含義,只不過通常這樣用而已。這種方式使用FORCE和.PHONY :
42、 clean效果相同。使用.PHONY更加明確高效,擔不是所有的make都支持;這樣許多makefile中使用了FORCE。3.7 空目標空目標(empty target)是phony目標的變種:用來執(zhí)行顯式請求的一個動作。和phony目標不同的是:這個目標文件可以真實存在,擔文件的內容無關緊要,通常是空的??漳繕宋募哪康氖抢闷渥詈笮薷臅r間來記錄命令最近一次執(zhí)行的時間,這是通過使用touch命令更新目標文件來達到的。print: foo.c bar.c lpr -p $? touch print利用這條規(guī)則,執(zhí)行make print時如果自上次make print之后任一文件改變了,lpr
43、命令會執(zhí)行。自動變量$?是為了只打印出那些變化了的文件。3.8 內建的特殊目標某些名字作為目標存在時有特殊含義。 .PHONY該目標的依賴被認為是phony目標,處理這些目標時,命令無條件被執(zhí)行,不管文件名是否存在及其最后修改時間 .SUFFIXES該目標的依賴被認為是一個后綴列表,在檢查后綴規(guī)則時使用 .DEFAULT該目標的規(guī)則被使用在沒有規(guī)則(顯式的或隱含的)的目標上。如果DEFAULT命令定義了,則對所有不是規(guī)則目標的依賴文件都會執(zhí)行該組命令 .PRECIOUS該目標的依賴文件會受到特別對待:如果make被kill或命令的執(zhí)行被中止,這些目標并不刪除;而且如果該目標是中間文件,在不需要
44、時不會被刪除??梢詫㈦[含規(guī)則的目標模式(如%.o)做為.PRECIOUS的依賴文件,這樣可以保存這些規(guī)則產生的中間文件。 .INTERMEDIATE該目標的依賴文件被當作中間文件;如果該目標沒有依賴文件,則makefile中所有的目標文件均被認為是中間文件。 .IGNORE在執(zhí)行該目標的依賴規(guī)則的命令時,make會忽略錯誤,此規(guī)則本身的命令沒有意義。如果該規(guī)則沒有依賴關系,表示忽略所有命令執(zhí)行的錯誤,這種用法只是為了向后兼容;由于會影響到所有的命令,所以不是特別有用,推薦使用其它更有選擇性忽略錯誤的方法。 .SILENT在執(zhí)行該目標的依賴規(guī)則的命令時,make并不打印命令本身。該規(guī)則的命令沒有
45、意義。在.SILIENT沒有依賴關系時,表示執(zhí)行makefile中的所有命令都不會打印,該規(guī)則只是為了向后兼容提供的。 .EXPORT_ALL_VARIABLES只是作為一個目標存在,指示make將所有變量輸出到子進程中。定義的隱含規(guī)則的后綴作為目標時,也認為它是特殊目標;兩個后綴的連接也是一樣,比如.c.o。這些目標是后綴規(guī)則,一中定義隱式規(guī)則的過時方法(但仍然廣泛使用)。后綴通常以.開始,所以特殊目標也以.開始。3.9 一個規(guī)則多個目標一條有多個目標的規(guī)則和寫多條規(guī)則,每條一個目標作用是等同的。同樣的命令應用于所有目標,但其效用會因將實際目標以$代替而不同。規(guī)則中所有目標的依賴關系是一樣的
46、。這在兩種情況下有用:只有依賴關系,不需要命令。例如:kbd.o command.o files.o: command.h 所有的目標同樣的命令。命令不需要完全相同,因為在命令中可以使用$:bigoutput littleoutput : text.g generate text.g -$(subst output,$) > $和bigoutput : text.g generate text.g -big > bigoutputlittleoutput : text.g generate text.g -little > littleoutput等同。這里假設程序gener
47、ate產生兩種輸出:一種使用-big選項,一種使用-little選項。如果想象使用$變化命令那樣來變化依賴關系,不能通過多目標的普通規(guī)則實現,但是可以通過模式規(guī)則來實現。3.10 一個目標多條規(guī)則一個文件可以是多條規(guī)則的目標,所有規(guī)則的依賴關系被合并。如果目標比任一個依賴文件舊,命令被執(zhí)行。一個文件只能有一組命令執(zhí)行。如果多個規(guī)則對于同一個文件都給出了命令,make使用最后一組并打印錯誤信息(特殊情況:如果文件名以.開始,并不打印錯誤信息,這一點是為了和其它make兼容)。沒有任何理由需要將makefile寫成這樣,這是make給出錯誤信息的理由。一條只有依賴關系的附加規(guī)則可以一次給出許多文件
48、的附加依賴文件。例如objects變量表示系統(tǒng)中編譯器的所有輸出.,說明當config.h更改時所有文件必須重做的簡單方法如下: objects = foo.o bar.o foo.o : defs.h bar.o : defs.h test.h $(objects) : config.h不用改變實際目標文件生成的規(guī)則,這條規(guī)則可以在需要增刪附加的依賴關系時插入或提出。另一個訣竅是附加的依賴關系可以用變量表示,在make執(zhí)行時,可以給變量賦值:extradeps=$(objects) : $(extradeps)當命令make extradeps=foo.h'執(zhí)行時會認為foo.h是每
49、個目標文件的依賴文件,但簡單的make命令不是這樣。3.11 靜態(tài)模式規(guī)則靜態(tài)模式規(guī)則(static pattern rules)可以指定多個目標,并且使用目標名字來建議依賴文件的名字;比普通多目標規(guī)則更通用因為不需要依賴關系是相同的:依賴關系必須類似但不需要相同。3.11.1 語法TARGETS .: TARGET-PATTERN: DEP-PATTERNS . COMMANDS .TARGETS列表指出規(guī)則應用的目標,可以包含通配符,于普通規(guī)則的目標相同。TARGET-PATTERN和DEP-PATTERNS來表明目標的依賴關系如何計算:匹配TARGET-PATTERN的目標從名字中抽出一
50、部分,叫做詞干(stem),詞干被替換到DEP-PATTERNS來形成依賴文件名。每個模式通常包含一個%字符。當TARGET-PATTERN匹配一個目標時,%字符可以匹配目標名中的任何部分;這部分即是詞干,模式的其余部分必須完全匹配。例如foo.o匹配%.o,foo是詞干;目標foo.c和foo.out并不匹配這個模式。目標的依賴文件名通過將DEP-PATTERNS中的%替換為詞干形成:如果依賴模式為%.c,在替換詞干foo可以得到foo.c。依賴模式中不包含%也是合法的,此依賴文件對所有的目標均有效。如果需要在模式規(guī)則中使用%字符,必須在其前面加字符,如果%前的字符是有實際意義的,必須在其前
51、面加,其它的不必如此處理。如the%weird%pattern在有效的%前是the%weird,其后是pattern。最后的保持原樣是因為其并不影響%字符。以下例子從相應的.c文件編譯foo.o和bar.o:objects = foo.o bar.o$(objects): %.o: %.c $(CC) -c $(CFLAGS) $< -o $每個目標必須匹配目標模式,對于不匹配的目標會給出警告。如果列表中只有部分文件匹配模式,可以使用filter函數移去不匹配的文件名: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)' 結果是bar.o lose.o; $(filter %.elc,$(files)' 的結果是foo.elc'。以下例子說明$*的使用:bigoutput littleoutput : %output : text.g generate text.g -$* > $命令generate'執(zhí)行時,$*擴展為詞干big
53、或little。3.11.2 靜態(tài)模式規(guī)則和隱式規(guī)則靜態(tài)模式規(guī)則和隱式規(guī)則在作為模式規(guī)則是具有很多共同點,都有目標模式和構造依賴文件名的模式,不同之處在于make決定何時應用規(guī)則的方法。隱式規(guī)則可應用于匹配其模式的任何目標,但只限于沒有指定命令的目標,如果有多條可應用的隱式規(guī)則,只有一條被使用,取決于規(guī)則的順序。反之,靜態(tài)模式規(guī)則適用于規(guī)則中明確目標列表,不適用于其它目標且總是適用于指定的每個目標。如果有兩條沖突的規(guī)則,且都有命令,這是一個錯誤。靜態(tài)模式規(guī)則比隱式規(guī)則優(yōu)越之處如下: 可為一些不能按句法分類,但可以顯式列出的文件重載隱式規(guī)則 不能判定目錄中的精確內容,一些無關的文件可能導致make適用錯誤的隱式規(guī)則;最終結果可能依賴于隱式規(guī)則的次序。適用靜態(tài)模式規(guī)則時,這種不確定性是不存在的:規(guī)則適用于明確指定的目標。3.12 雙冒號規(guī)則雙冒號規(guī)則(Double-colon rules)的目標后是:而不是:,當一個目標出現在多條規(guī)則中時,其處理和普通規(guī)則的處理不同。當一個目標出現在多條規(guī)則中時,所有規(guī)則必須是相同類型的:都是普通的或者都是雙冒號的。如果是雙冒號,規(guī)則之間相互獨立;如果目標需要更新,則規(guī)則的命令被執(zhí)行;結果可能是沒有執(zhí)行,或者執(zhí)行了其中一些,
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯系上傳者。文件的所有權益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網頁內容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
- 4. 未經權益所有人同意不得將文件中的內容挪作商業(yè)或盈利用途。
- 5. 人人文庫網僅提供信息存儲空間,僅對用戶上傳內容的表現方式做保護處理,對用戶上傳分享的文檔內容本身不做任何修改或編輯,并不能對任何下載內容負責。
- 6. 下載文件中如有侵權或不適當內容,請與我們聯系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 納迪克酸酐相關行業(yè)投資規(guī)劃報告范本
- 洗滌劑用4A沸石相關項目投資計劃書范本
- 基于《黃帝內經》重陽思想對心系疾病的探索與研究
- 退市新規(guī)下ST企業(yè)審計風險及應對研究
- 課題開題報告:鄉(xiāng)村教師數字素養(yǎng)與技能提升路徑研究
- 課題開題報告:現代網絡信息技術在學校安全管理工作中的應用研究
- 課題開題報告:縣域學前教育普及普惠督導評估機制的研究
- 藍斑核中γ氨基丁酸能神經元介導小鼠體溫調節(jié)的研究
- 質量協會成立領導發(fā)言稿
- 課題開題報告:提取練習策略優(yōu)化小學生數學規(guī)則樣例學習的效果及機制研究
- RRU設計原理與實現
- 工程質量責任制和考核辦法
- 《室內展示設計》課件
- 服裝店售后培訓課件
- 新舊系統(tǒng)數據遷移方案
- nfc果汁加工工藝
- 人為因素和航空法規(guī)-第二版-第7章
- 《中國十大元帥》課件
- 福建省服務區(qū)標準化設計指南
- 新課程關鍵詞
- 糧油倉儲企業(yè)一規(guī)定兩守則試題(新改版附答案)
評論
0/150
提交評論