嵌入式系統(tǒng)設(shè)計(jì)與開發(fā)Make項(xiàng)目管理工具使用及Makefile文件編寫_第1頁
嵌入式系統(tǒng)設(shè)計(jì)與開發(fā)Make項(xiàng)目管理工具使用及Makefile文件編寫_第2頁
嵌入式系統(tǒng)設(shè)計(jì)與開發(fā)Make項(xiàng)目管理工具使用及Makefile文件編寫_第3頁
嵌入式系統(tǒng)設(shè)計(jì)與開發(fā)Make項(xiàng)目管理工具使用及Makefile文件編寫_第4頁
嵌入式系統(tǒng)設(shè)計(jì)與開發(fā)Make項(xiàng)目管理工具使用及Makefile文件編寫_第5頁
已閱讀5頁,還剩86頁未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡(jiǎn)介

嵌入式系統(tǒng)設(shè)計(jì)與開發(fā)Make項(xiàng)目管理工具使用及Makefile文件編寫第1頁/共91頁第5章Make及makefile文件的編寫

1.概述2.Makefile3.Makefile的規(guī)則4.規(guī)則的命令5.Makefile中的變量6.執(zhí)行make第2頁/共91頁什么是make?程序的編譯和鏈接源程序(.c/.cpp/.s)編譯(compile)鏈接(linker)形成目標(biāo)文件語法正確、變量和函數(shù)聲明正確Windows:.objUNIX/Linux:.o形成可執(zhí)行程序鏈接函數(shù)和全局變量,鏈接只關(guān)心目標(biāo)文件。多個(gè)目標(biāo)文件形成一個(gè)庫Windows:.libUNIX/Linux:.a、.o第3頁/共91頁什么是make?Make是大型程序維護(hù)工具M(jìn)ake工作時(shí),需要名字為“makefile”的makefile文件。Make就是一個(gè)解釋makefile文件中指令的命令工具。第4頁/共91頁程序文件之間的依賴關(guān)系第5頁/共91頁makefile文件在makefile(Makefile)文件中,采用自頂向下到的方法來說明依賴關(guān)系network:network.osubrs.o(1)

gcc–onetworknetwork.osubrs.o(2)network.o:etdefs.h(3)

gcc–cnetwork.c(4)subrs.o:etdefs.h(5)

gcc–csubrs.c(6)第6頁/共91頁執(zhí)行make在makefile(Makefile)文件所在的目錄中,執(zhí)行make命令語法:make[選項(xiàng)][宏定義][目標(biāo)文件]第7頁/共91頁Make的工作過程1.make在當(dāng)前目錄下找名字叫“Makefile”或“makefile”的文件2.如果找到,它會(huì)找文件中的第一個(gè)目標(biāo)文件(target),比如找到“network”這個(gè)文件,并把這個(gè)文件作為最終的目標(biāo)文件。3.如果network文件不存在,或是network所依賴的后面的.o文件的文件修改時(shí)間要比network這個(gè)文件新,那么,他就會(huì)執(zhí)行后面所定義的命令來生成network這個(gè)文件。4.如果network所依賴的.o文件也存在,那么make會(huì)在當(dāng)前文件中找目標(biāo)為.o文件的依賴性,如果找到則再根據(jù)那一個(gè)規(guī)則生成.o文件(使用源文件和.h文件)。(這有點(diǎn)像一個(gè)堆棧的過程)第8頁/共91頁make時(shí),哪些文件被重新編譯1.所有的源文件沒有被編譯過,則對(duì)各個(gè)C源文件進(jìn)行編譯并進(jìn)行鏈接,生成最后的可執(zhí)行程序;2.每一個(gè)在上次執(zhí)行make之后修改過的C源代碼文件在本make時(shí)將會(huì)被重新編譯;3.頭文件在上一次執(zhí)行make之后被修改。則所有包含此頭文件的C源文件在本次執(zhí)行make時(shí)將會(huì)被重新編譯。第9頁/共91頁關(guān)于Makefile文件名默認(rèn)的情況下,make命令會(huì)在當(dāng)前目錄下按順序找尋文件名為“GNUmakefile”、“makefile”、“Makefile”的文件,找到了解釋這個(gè)文件。也可以使用別的文件名來書寫Makefile,這是執(zhí)行Make命令時(shí),需使用“-f”和“--file”參數(shù)。如:make-fMake.Linux或make--fileMake.AIX第10頁/共91頁makefile規(guī)則介紹一個(gè)簡(jiǎn)單的Makefile描述規(guī)則組成:TARGET...:PREREQUISITES... <tab>COMMAND ...--target:規(guī)則的目標(biāo)。--通常是程序中間文件(.o)或者最后可執(zhí)行文件名--目標(biāo)也可以是一個(gè)make執(zhí)行的動(dòng)作的名稱,如目標(biāo)“clean”,這樣的目標(biāo)是“偽目標(biāo)--prerequisites:規(guī)則的依賴。--生成規(guī)則目標(biāo)所需要的文件名列表。通常一個(gè)目標(biāo)依賴于一個(gè)或者多個(gè)文件。--command:規(guī)則的命令行--是make程序所有執(zhí)行的動(dòng)作(任意的shell命令或者可在shell下執(zhí)行的程序)--一個(gè)規(guī)則可以有多個(gè)命令行,每一條命令占一行。注意:每一個(gè)命令行必須以[Tab]字符開始第11頁/共91頁對(duì)“規(guī)則”的再認(rèn)識(shí)在Makefile中“規(guī)則”就是描述在什么情況下、如何重建規(guī)則的目標(biāo)文件,通常規(guī)則中包括了目標(biāo)的依賴關(guān)系(目標(biāo)的依賴文件)和重建目標(biāo)的命令。make執(zhí)行重建目標(biāo)的命令,來創(chuàng)建或者重建規(guī)則的目標(biāo)(此目標(biāo)文件也可以是觸發(fā)這個(gè)規(guī)則的上一個(gè)規(guī)則中的依賴文件)。規(guī)則包含了目標(biāo)和依賴的關(guān)系以及更新目標(biāo)所要求的命令。第12頁/共91頁一個(gè)簡(jiǎn)單的例子#sampleMakefileedit:main.okbd.ocommand.odisplay.o\insert.osearch.ofiles.outils.occ-oeditmain.okbd.ocommand.odisplay.o\insert.osearch.ofiles.outils.omain.o:main.cdefs.hcc-cmain.c

kbd.o:kbd.cdefs.hcommand.hcc-ckbd.ccommand.o:command.cdefs.hcommand.hcc-ccommand.cdisplay.o:display.cdefs.hbuffer.hcc-cdisplay.cinsert.o:insert.cdefs.hbuffer.hcc-cinsert.csearch.o:search.cdefs.hbuffer.hcc-csearch.cfiles.o:files.cdefs.hbuffer.hcommand.hcc-cfiles.cutils.o:utils.cdefs.hcc-cutils.cclean:rmeditmain.okbd.ocommand.odisplay.o\insert.osearch.ofiles.outils.o1.注釋以#開頭2.一個(gè)較長(zhǎng)行可以使用反斜線(\)分解為多行,\后不能有空格3.目標(biāo)“clean”不是一個(gè)文件,它僅僅代表了執(zhí)行一個(gè)動(dòng)作的標(biāo)識(shí)。Makefile中把那些沒有任何依賴只有執(zhí)行動(dòng)作的目標(biāo)稱為“偽目標(biāo)”在執(zhí)行make時(shí),它所指定的動(dòng)作不會(huì)被執(zhí)行。除非執(zhí)行make時(shí)明確地指定它作為重建目標(biāo)。而且目標(biāo)“clean”沒有任何依賴文件,它只有一個(gè)目的,就是通過這個(gè)目標(biāo)名來執(zhí)行它所定義的命令。Makefile中把執(zhí)行“clean”目標(biāo)所定義的命令,可在shell下輸入:makeclean。

第13頁/共91頁make工作過程的再分析-1當(dāng)在shell提示符下輸入“make”命令以后。make讀取當(dāng)前目錄下的Makefile文件,并將Makefile文件中的第一個(gè)目標(biāo)作為“終極目標(biāo)”,開始處理第一個(gè)規(guī)則。make在處理這個(gè)規(guī)則之前,首先將處理目標(biāo)“edit”的所有的依賴文件(例子中的那些.o文件)的更新規(guī)則對(duì).o文件所在的規(guī)則的處理有下列三種情況:1.目標(biāo).o文件不存在,使用其描述規(guī)則創(chuàng)建它;2.目標(biāo).o文件存在,目標(biāo).o文件所依賴的.c源文件、.h文件中的任何一個(gè)比目標(biāo).o文件“新”(在上一次make之后被修改)。則根據(jù)規(guī)則重新編譯生成它;3.目標(biāo).o文件存在,目標(biāo).o文件比它的任何一個(gè)依賴文件(的.c源文件、.h文件)“更新”(它的依賴文件在上一次make之后沒有被修改),則什么也不做。第14頁/共91頁make工作過程的再分析-2完成了對(duì).o文件的創(chuàng)建(第一次編譯),make程序?qū)⑻幚斫K極目標(biāo)“edit”所在的規(guī)則,分為以下三種情況:1.目標(biāo)文件“edit”不存在,則執(zhí)行規(guī)則創(chuàng)建目標(biāo)“edit”。2.目標(biāo)文件“edit”存在,其依賴文件中有一個(gè)或者多個(gè)文件比它“更新”,則根據(jù)規(guī)鏈接生成“edit”。3.目標(biāo)文件“edit”存在,它比它的任何一個(gè)依賴文件都“更新”,則什么也要正確的編譯一個(gè)工程。需要在提供給make程序的Makefile中來保證其依賴關(guān)系的正確性、和執(zhí)行命令的正確性。第15頁/共91頁使用變量在上例的Makefile中可是添加這樣一行:objects=main.okbd.ocommand.odisplay.oinsert.o\search.ofiles.outils.o“objects”作為一個(gè)變量,它代表所有的.o文件的列表,在需要使用這些.o文件列表的地方使用“$(objects)”來表示它objects=main.okbd.ocommand.odisplay.o\insert.osearch.ofiles.outils.oedit:$(objects)cc-oedit$(objects)…….…….clean:rmedit$(objects)第16頁/共91頁使用變量的例子exe:main.oio.ogccmain.oio.o-oexemain.o:main.c

gcc-g-cmain.c–o\main.oio.o:io.c

gcc-g-cio.c-oio.oOBJS=main.oio.oCC=gccCFLAGS=-gexe:$(OBJS)

$(CC)$(OBJS)-oexemain.o:main.c

$(CC)$(CFLAGS)–cmain.c-omain.oio.o:io.c$(CC)$(CFLAGS)-cio.c-oio.o第17頁/共91頁自動(dòng)推導(dǎo)規(guī)則(隱含規(guī)則)make中,編譯.o文件時(shí),make會(huì)認(rèn)為其源程序就是同文件名的.c源文件,因此依賴列表中可以省略.c文件,這是make的隱含規(guī)則書寫Makefile時(shí),對(duì)于一個(gè).c文件如果使用make的隱含規(guī)則,那么它會(huì)被自動(dòng)作為對(duì)應(yīng).o文件的一個(gè)依賴文件(對(duì)應(yīng)是指:文件名除后綴外,其余都相同的兩個(gè)文件)。因此可以在規(guī)則中省略目標(biāo)的倚賴.c文件。第18頁/共91頁使用隱含規(guī)則和變量的例子#sampleMakefileobjects=main.okbd.ocommand.odisplay.o\insert.osearch.ofiles.outils.o

edit:$(objects)cc-oedit$(objects)

main.o:defs.hkbd.o:defs.hcommand.hcommand.o:defs.hcommand.hdisplay.o:defs.hbuffer.hinsert.o:defs.hbuffer.hsearch.o:defs.hbuffer.hfiles.o:defs.hbuffer.hcommand.hutils.o:defs.h

.PHONY:cleanclean:rmedit$(objects)第19頁/共91頁清洗工作目錄過程文件clean:rmedit$(objects)一般寫為:.PHONY:cleanclean:-rmedit$(objects)兩個(gè)實(shí)現(xiàn)有兩點(diǎn)不同:

1.通過“.PHONY”特殊目標(biāo)將“clean”目標(biāo)聲明為偽目標(biāo)。防止當(dāng)磁盤上存在一個(gè)名為“clean”文件時(shí),“clean”所在規(guī)則的命令無法執(zhí)行。2.在命令行之前使用“-”,意思是忽略命令“rm”的執(zhí)行錯(cuò)誤第20頁/共91頁第7章Make及makefile文件的編寫

1.概述2.Makefile3.Makefile的規(guī)則4.規(guī)則的命令5.Makefile中的變量6.執(zhí)行make第21頁/共91頁Makefile的內(nèi)容在一個(gè)完整的Makefile中,包含了5個(gè)東東:顯式規(guī)則隱含規(guī)則變量的定義指示符注釋它描述了在何種情況下如何更新一個(gè)或者多個(gè)被稱為目標(biāo)的文件。在書寫Makefile是需要明確地給出目標(biāo)文件、目標(biāo)的依賴文件列表以及更新目標(biāo)文件所需要的命令。它是make根據(jù)此類目標(biāo)文件的命名(典型的是文件名的后綴)而自動(dòng)推導(dǎo)出來的規(guī)則。make根據(jù)目標(biāo)文件的名字,自動(dòng)產(chǎn)生目標(biāo)的依賴文件并使用默認(rèn)的命令來對(duì)目標(biāo)進(jìn)行更新。就是使用一個(gè)字符串代表一段文本串,當(dāng)定義了變量以后,Makefile后續(xù)在需要使用此文本串的地方,通過引用這個(gè)變量來實(shí)現(xiàn)對(duì)文本串的使用指明在make程序讀取makefile文件過程中所要執(zhí)行的一個(gè)動(dòng)作。包括:1.讀取給定文件名的文件。2.決定(通常是根據(jù)一個(gè)變量的得值)處理或忽略Makefile中的某一特定部分3.定義一個(gè)多行變量。Makefile中“#”字符后的內(nèi)容被作為是注釋內(nèi)容注釋行的結(jié)尾如果存在反斜線(\),那么下一行也被作為注釋行當(dāng)在Makefile中需要使用字符“#”時(shí),可以使用反斜線加“#”(\#)來實(shí)現(xiàn)第22頁/共91頁makefile文件的命名執(zhí)行make命令時(shí),默認(rèn)的情況下,make會(huì)在工作目錄(執(zhí)行make的目錄)下按照文件名順序?qū)ふ襪akefile文件讀取并執(zhí)行,查找的文件名順序?yàn)椋骸癎NUmakefile”、“makefile”、“Makefile”。通常應(yīng)該使用“makefile”或者“Makefile”作為一個(gè)makefile的文件名,“GNUmakefile”不推薦使用,因?yàn)橐源嗣奈募挥小癎NUmake”才可以識(shí)別。當(dāng)makefile文件的命名不是這三個(gè)任何一個(gè)時(shí),需要通過make的“-f”或者“--file”選項(xiàng)來指定make讀取的makefile文件。第23頁/共91頁包含其它的MakefileincludeFILENAMES...make暫停讀取當(dāng)前的Makefile,轉(zhuǎn)而去讀取include下的Makefile,結(jié)束后,繼續(xù)當(dāng)前的Makefile書寫在獨(dú)立的一行,不可以tab開頭可使用“-include”來代替“include”,忽略由于包含文件不存在或者無法創(chuàng)建時(shí)的錯(cuò)誤提示(“-”的意思是告訴make,忽略此操作的錯(cuò)誤。make繼續(xù)執(zhí)行)第24頁/共91頁MAKEFILES變量如果當(dāng)前環(huán)境定義了一個(gè)“MAKEFILES”的環(huán)境變量,make執(zhí)行時(shí)首先將此變量的值作為需要讀入的Makefile文件,多個(gè)文件之間使用空格分開。類似使用指示符“include”包含其它Makefile文件一樣變量“MAKEFILES”主要用在“make”的遞歸調(diào)用過程中的的通信,實(shí)際應(yīng)用中很少設(shè)置此變量。第25頁/共91頁MAKEFILE_LIST變量make程序在讀取多個(gè)makefile文件時(shí),在對(duì)這些文件進(jìn)行解析執(zhí)行之前,將會(huì)被自動(dòng)的追加到變量“MAKEFILE_LIST”的定義域中。第26頁/共91頁make如何解析Makefile分為兩個(gè)階段第1階段:讀取所有的Makefile文件,內(nèi)建所有的變量、明確規(guī)則和隱含規(guī)則,并建立所有目標(biāo)和依賴之間的依賴關(guān)系結(jié)構(gòu)鏈表。第2階段:根據(jù)第1階段建立的目標(biāo)和依賴之間的依賴關(guān)系結(jié)構(gòu)鏈表決定哪些目標(biāo)需要更新,并使用響應(yīng)的規(guī)則,對(duì)該目標(biāo)進(jìn)行更新。理解make執(zhí)行過程的兩個(gè)階段是很重要的。它能幫助我們更深入的了解執(zhí)行過程中變量以及函數(shù)是如何被展開的。在make的第1階段,變量和函數(shù)被展開的,稱為立即展開,否則為延后展開。第27頁/共91頁第7章Make及makefile文件的編寫

1.概述2.Makefile3.Makefile的規(guī)則4.規(guī)則的命令5.Makefile中的變量6.執(zhí)行make第28頁/共91頁Makefile規(guī)則Makefile中,規(guī)則描述了何種情況下使用什么命令來重建一個(gè)特定的文件,此文件被稱為規(guī)則“目標(biāo)”(通常規(guī)則中的目標(biāo)只有一個(gè))。規(guī)則所羅列的其他文件稱為“目標(biāo)”的依賴規(guī)則中的命令是用來更新或者創(chuàng)建此規(guī)則的目標(biāo)終極目標(biāo)所在的規(guī)則,應(yīng)該是Makefile中的第1個(gè)規(guī)則,其余規(guī)則不分次序。第29頁/共91頁終極目標(biāo)終極目標(biāo),就是執(zhí)行make時(shí),沒有指明具體目標(biāo)時(shí),make默認(rèn)的那個(gè)目標(biāo)。第1個(gè)規(guī)則有多個(gè)目標(biāo)時(shí),第1個(gè)目標(biāo)為終極目標(biāo),除非以下兩種情況1.目標(biāo)名以點(diǎn)號(hào)”.”隔開,其后沒有斜線”/”2.作為模式規(guī)則的目標(biāo)“終極目標(biāo)“是執(zhí)行make的唯一目的,其所在的規(guī)則作為第一個(gè)規(guī)則。第30頁/共91頁規(guī)則的語法通常規(guī)則的語法格式如下:TARGETS:PREREQUISITESCOMMAND...或者是這樣:TARGETS:PREREQUISITES;COMMANDCOMMAND...第31頁/共91頁規(guī)則的核心思想規(guī)則的中心思想就是:目標(biāo)文件的內(nèi)容是由依賴文件決定,依賴文件的任何一處改動(dòng),將導(dǎo)致目前已經(jīng)存在的目標(biāo)文件的內(nèi)容過期。規(guī)則的命令為重建目標(biāo)提供了方法。這些命令運(yùn)行在系統(tǒng)shell之上。規(guī)則中的命令被執(zhí)行有兩種情況1.目標(biāo)文件不存在;

2.存在一個(gè)依賴的最后修改時(shí)間比目標(biāo)的最后修改時(shí)間晚第32頁/共91頁依賴的類型常規(guī)依賴常規(guī)依賴中的任何一個(gè)文件更新,都會(huì)導(dǎo)致重建目標(biāo)。常用的形式order-only依賴在更新目標(biāo)(目標(biāo)文件已經(jīng)存在)時(shí),只需要根據(jù)依賴文件中的部分來決定目標(biāo)是否需要被重建,而不是在依賴文件的任何一個(gè)被修改后都重建目標(biāo)。依賴的改動(dòng)不會(huì)導(dǎo)致目標(biāo)重建,稱為order-only依賴在書寫規(guī)則時(shí),“order-only”依賴使用管道符號(hào)“|”開始,左邊是常規(guī)依賴,管道符右邊的全部是order-only依賴。第33頁/共91頁舉例LIBS=libtest.afoo:foo.c|$(LIBS)$(CC)$(CFLAGS)$<-o$@$(LIBS)執(zhí)行make時(shí),如果foo.c修改了,目標(biāo)foo會(huì)重建,libtest.a修改了,foo不會(huì)重建libtest.a只有在foo不存在的情況下,才會(huì)參與規(guī)則的執(zhí)行。第34頁/共91頁文件名使用通配符可使用的通配符有:“*”、“?”Makefile中統(tǒng)配符可以出現(xiàn)在以下兩種場(chǎng)合:1.可以用在規(guī)則的目標(biāo)、依賴中,此時(shí)make會(huì)自動(dòng)將其展開;2.可出現(xiàn)在規(guī)則的命令中,其展開是在shell在執(zhí)行此命令時(shí)完成。變量定義中使用的通配符不會(huì)被展開。變量objects=*.o”。那么變量“objects”的值就是“*.o”。需要變量“objects”代表所有的.o文件,使用函數(shù)“wildcard”來實(shí)現(xiàn)(objects=$(wildcard*.o))。第35頁/共91頁函數(shù)wildcard在規(guī)則中,通配符會(huì)被自動(dòng)展開。在變量的定義和使用函數(shù)時(shí),通配符不會(huì)被自動(dòng)展開。這種情況下需要通配符有效,要用到函數(shù)“wildcard”語法格式:$(wildcardPATTERN...)第36頁/共91頁目錄搜索在一個(gè)較大的工程中,一般會(huì)把源碼文件和2進(jìn)制文件(.o文件和可執(zhí)行文件)安排在不同的目錄來進(jìn)行區(qū)分管理。需要使用make提供的目錄自動(dòng)搜索依賴文件功能第37頁/共91頁VPATH變量通過變量“VPATH”可以指定依賴文件的搜索路徑。在規(guī)則的依賴文件在當(dāng)前目錄不存在時(shí),make會(huì)在此變量所指定的目錄下去尋找這些依賴文件變量“VPATH”的定義中,使用空格或者冒號(hào)(:)將多個(gè)目錄分開。make搜索的目錄順序按照變量“VPATH”定義中順序進(jìn)行(當(dāng)前目錄永遠(yuǎn)是第一搜索目錄)。舉例:VPATH=src:../headers,指定兩個(gè)搜索目錄,分別是src和../headers第38頁/共91頁Makefile的偽目標(biāo)偽目標(biāo):它不代表一個(gè)真正的文件名,在執(zhí)行make時(shí)可以指定這個(gè)目標(biāo)來執(zhí)行其所在規(guī)則定義的命令有時(shí)我們也可以將一個(gè)偽目標(biāo)稱為標(biāo)簽使用偽目標(biāo)的原因1.避免在Makefile中定義的只執(zhí)行命令的的目標(biāo)(此目標(biāo)的目的為了執(zhí)行執(zhí)行一些列命令,而不需要?jiǎng)?chuàng)建這個(gè)目標(biāo))和工作目錄下的實(shí)際文件出現(xiàn)名字沖突。2.提高執(zhí)行make時(shí)的效率。第39頁/共91頁避免和實(shí)際文件名沖突clean:rm*.otemp執(zhí)行makeclean,如果目錄下沒有clean文件,執(zhí)行結(jié)果與要求一致,刪除所有.o文件和temp目錄如果目錄下有clean文件,會(huì)怎么樣?規(guī)則沒有依賴文件,目標(biāo)會(huì)被認(rèn)為是最新的,而不去執(zhí)行規(guī)則的命令。這不是我們的初衷。把clean明確聲明為偽目標(biāo)。將一個(gè)目標(biāo)聲明為偽目標(biāo)需要將它作為特殊目標(biāo)“.PHONY”的依賴.PHONY:clean第40頁/共91頁偽目標(biāo)規(guī)則的書寫首先需要聲明目標(biāo)是一個(gè)偽目標(biāo)然后是偽目標(biāo)的規(guī)則定義。舉例:.PHONY:cleanclean:rm*.otemp這里clean是人為定義的偽目標(biāo),可以是任何一個(gè)合法的名字。第41頁/共91頁偽目標(biāo)的依賴應(yīng)用場(chǎng)合1.創(chuàng)建當(dāng)前目錄下的多個(gè)應(yīng)用程序2.分類執(zhí)行不同的動(dòng)作第42頁/共91頁創(chuàng)建當(dāng)前目錄下的多個(gè)應(yīng)用程序約定的做法是使用一個(gè)稱為“all”的偽目標(biāo)來作為終極目標(biāo)all:prog1prog2prog3.PHONY:allprog1:prog1.outils.occ-oprog1prog1.outils.oprog2:prog2.occ-oprog2prog2.oprog3:prog3.osort.outils.occ-oprog3prog3.osort.outils.omake,更新全部makeprog1,只更新prog1第43頁/共91頁分類執(zhí)行不同的動(dòng)作把一個(gè)偽目標(biāo)作為另外一個(gè)偽目標(biāo)的依賴,make將其作為另外一個(gè)偽目標(biāo)的子例程來處理,類似函數(shù)調(diào)用。.PHONY:cleanallcleanobjcleandiffcleanall:cleanobjcleandiffrmprogramcleanobj:rm*.ocleandiff:rm*.diff執(zhí)行makecleanall時(shí),會(huì)調(diào)用執(zhí)行makecleanobj和makecleandiff。也可單獨(dú)執(zhí)行makecleanobj,刪除所有的obj文件。第44頁/共91頁多目標(biāo)一個(gè)規(guī)則中可以有多個(gè)目標(biāo),規(guī)則所定義的命令對(duì)所有的目標(biāo)有效。一個(gè)具有多目標(biāo)的規(guī)則相當(dāng)于多個(gè)規(guī)則。多目標(biāo)通常用在以下兩種情況:1.僅需要一個(gè)描述依賴關(guān)系的規(guī)則,而不需要在規(guī)則中定義命令kbd.ocommand.ofiles.o:command.h2.對(duì)于多個(gè)具有類似重建命令的目bigoutputlittleoutput:text.ggeneratetext.g-$(substoutput,,$@)>$@等價(jià)于bigoutput:text.ggeneratetext.g-big>bigoutputlittleoutput:text.ggeneratetext.g-little>littleoutput第45頁/共91頁多規(guī)則目標(biāo)Makefile中,一個(gè)文件作為多個(gè)規(guī)則的目標(biāo)出現(xiàn)。此目標(biāo)文件的所有依賴文件將會(huì)被合并成此目標(biāo)一個(gè)依賴文件列表,其中任何一個(gè)依賴文件比目標(biāo)更新(比較目標(biāo)文件和依賴文件的時(shí)間戳)時(shí),make將會(huì)執(zhí)行特定的命令來重建這個(gè)目標(biāo)。重建此目標(biāo)的命令只能出現(xiàn)在一個(gè)規(guī)則中。如果多個(gè)規(guī)則同時(shí)給出重建此目標(biāo)的命令,make將使用最后一個(gè)規(guī)則所用的命令,同時(shí)提示錯(cuò)誤信息如果目標(biāo)的任何一個(gè)規(guī)則沒有定義重建此目標(biāo)的命令,make將會(huì)尋找一個(gè)合適的隱含規(guī)則來重建此目標(biāo)。第46頁/共91頁多規(guī)則目標(biāo)舉例objects=foo.obar.ofoo.o:defs.hbar.o:defs.htest.h$(objects):config.h這是一個(gè)描述規(guī)則,僅僅用來描述依賴關(guān)系foo.o和bar.o都是多規(guī)則的目標(biāo),如果config.h文件發(fā)生變化,則foo.o和bar.o都會(huì)自動(dòng)重建。第47頁/共91頁靜態(tài)模式規(guī)則靜態(tài)模式規(guī)則是這樣一個(gè)規(guī)則:規(guī)則存在多個(gè)目標(biāo),并且不同的目標(biāo)可以根據(jù)目標(biāo)文件的名字來自動(dòng)構(gòu)造出依賴文件?;菊Z法TARGETS...:TARGET-PATTERN:PREREQ-PATTERNSCOMMANDS...--“TAGETS”列出了此規(guī)則的一系列目標(biāo)文件--可以使用通配符--目標(biāo)模式(TAGET-PATTERN)--依賴模式(PREREQ-PATTERNS)--說明了如何為目標(biāo)文件生成依賴文件--生成方法:從目標(biāo)模式的目標(biāo)文件中抽取一部分字符(稱為莖)來代替依賴模式中的相應(yīng)部分。第48頁/共91頁自動(dòng)生成依賴文件的過程在目標(biāo)模式和依賴模式中,一般需要包含模式字符%”。在目標(biāo)模式(TAGET-PATTERN)中“%”可以匹配目標(biāo)文件的任何部分,模式字符“%”匹配的部分就是“莖”。比如目標(biāo)“foo.o”符合模式“%.o”,其“莖”為“foo”。而目標(biāo)“foo.c”和“foo.out”就不符合此目標(biāo)模式。每一個(gè)目標(biāo)的依賴文件是使用此目標(biāo)的“莖”代替依賴模式PREREQ-PATTERNS)中的模式字符“%”而得到。如果依賴模式(PREREQ-PATTERNS)為“%.c”,那么使用“foo”替代依賴模式中的“%”得到的依賴文件就是“foo.c”。第49頁/共91頁靜態(tài)模式舉例objects=foo.obar.oall:$(objects)$(objects):%.o:%.c$(CC)-c$(CFLAGS)$<-o$@

對(duì)目標(biāo)foo.o,根據(jù)目標(biāo)模式”%.o”,所以其莖應(yīng)為foo,使用該莖,替代依賴模式”%.c”中的模式字符“%”,因此foo.o的依賴文件就是foo.c命令行中“$<”和“$@”是自動(dòng)化變量,“$<”表示規(guī)則中的第一個(gè)依賴文件。$@表示規(guī)則中的目標(biāo)文件foo.o:foo.c

$(CC)-c$(CFLAGS)foo.c-ofoo.obar.o:bar.c$(CC)-c$(CFLAGS)bar.c-obar.o第50頁/共91頁雙冒號(hào)規(guī)則雙冒號(hào)規(guī)則就是使用“::”代替普通規(guī)則的“:”得到的規(guī)則雙冒號(hào)規(guī)則允許在多個(gè)規(guī)則中為同一個(gè)目標(biāo)指定不同的重建目標(biāo)的命令注意:Makefile中,一個(gè)目標(biāo)可以出現(xiàn)在多個(gè)規(guī)則中。但是這些規(guī)則必須是同一種規(guī)則,要么都是普通規(guī)則,要么都是雙冒號(hào)規(guī)則。而不允許一個(gè)目標(biāo)同時(shí)出現(xiàn)在兩種不同的規(guī)則中第51頁/共91頁雙冒號(hào)規(guī)則和普通規(guī)則的區(qū)別對(duì)于一個(gè)沒有依賴而只有命令行的雙冒號(hào)規(guī)則,當(dāng)引用此目標(biāo)時(shí),規(guī)則的命令將會(huì)被無條件執(zhí)行。普通規(guī)則呢?當(dāng)同一個(gè)文件作為多個(gè)雙冒號(hào)規(guī)則的目標(biāo)時(shí)。這些不同的規(guī)則會(huì)被獨(dú)立的處理。就是說多個(gè)雙冒號(hào)規(guī)則中的每一個(gè)的依賴文件被改變之后,make只執(zhí)行此規(guī)則定義的命令,而其它的以這個(gè)文件作為目標(biāo)的雙冒號(hào)規(guī)則將不會(huì)被執(zhí)行普通規(guī)則呢?第52頁/共91頁雙冒號(hào)規(guī)則舉例Newprog::foo.c$(CC)$(CFLAGS)$<-o$@Newprog::bar.c$(CC)$(CFLAGS)$<-o$@如果foo.c更改,執(zhí)行make,根據(jù)foo.c文件重建目標(biāo)newprog如果bar.c更改,執(zhí)行make,根據(jù)bar.c文件重建目標(biāo)newprog如果是普通規(guī)則,執(zhí)行make時(shí)會(huì)怎樣?執(zhí)行make時(shí)出錯(cuò),并提示錯(cuò)誤信息第53頁/共91頁自動(dòng)生成依賴描述.o文件和頭文件的依賴關(guān)系。比如main.c中#include“def.h”,因此在Makefile的依賴關(guān)系中需要如下描述mai.o:main.cdef.h。有什么缺點(diǎn):1.如果很多源程序文件中用到了頭文件,就需要做很多這樣的依賴關(guān)系描述2.如果修改了源文件中使用的頭文件,那么這么依賴關(guān)系描述也需要修改。自動(dòng)產(chǎn)生依賴,使用GCC的-M選項(xiàng),GCC將自動(dòng)找尋源文件中包含的頭文件,并生成一個(gè)依賴關(guān)系gcc-Mmain.c,輸出main.o:main.cdef.h第54頁/共91頁第7章Make及makefile文件的編寫

1.概述2.Makefile3.Makefile的規(guī)則4.規(guī)則的命令5.Makefile中的變量6.執(zhí)行make第55頁/共91頁規(guī)則中書寫命令規(guī)則的命令由一些shell命令行組成每一行命令行必需一[Tab]字符開始對(duì)所有規(guī)則中命令行的解析默認(rèn)使用“/bin/sh”來完成第56頁/共91頁命令的回顯make在執(zhí)行命令行之前會(huì),把要執(zhí)行的命令行進(jìn)行輸出。稱之為“回顯”如果要執(zhí)行的命令行以字符“@”開始,則make在執(zhí)行時(shí)這個(gè)命令就不會(huì)被回顯@echo開始編譯XXX模塊......echo開始編譯XXX模塊......使用make的命令行參數(shù)“-n”或“--just-print”,make執(zhí)行時(shí)只顯示所要執(zhí)行的命令,但不會(huì)真正的去執(zhí)行這些命令make參數(shù)“-s”或“--slient”,禁止所有執(zhí)行命令的顯示第57頁/共91頁命令行的執(zhí)行書寫在同一行中的多個(gè)命令(各命令用分號(hào)分隔)屬于一個(gè)完整的shell命令行寫在獨(dú)立行的一條命令是一個(gè)獨(dú)立的shell命令行多行命令之間的執(zhí)行是相互獨(dú)立的,相互之間不存在依賴。比如,前行的cd命令,并不會(huì)影響到下一行。為了實(shí)現(xiàn)這個(gè)目的,應(yīng)該在一行上書寫,用分號(hào)分隔foo:bar/losecdbar;gobblelose>../foofoo:bar/losecdbar;\gobblelose>../foo或第58頁/共91頁命令執(zhí)行的錯(cuò)誤規(guī)則中的命令在運(yùn)行結(jié)束后,make會(huì)檢測(cè)命令執(zhí)行的返回狀態(tài)返回成功,就執(zhí)行下一條命令出錯(cuò)(返回狀態(tài)非0),make就會(huì)放棄對(duì)當(dāng)前規(guī)則的執(zhí)行,也有可能會(huì)終止所有規(guī)則的執(zhí)行。在命令之前加一個(gè)減號(hào)“-”(在[Tab]字符之后),make忽略此命令的執(zhí)行失敗。clean:-rm*.o即使刪除.o文件失敗,make也繼續(xù)執(zhí)行第59頁/共91頁命令執(zhí)行的錯(cuò)誤在執(zhí)行make時(shí),如果使用命令行選項(xiàng)“-i”或者“—ignore-errors”,make會(huì)忽略所有規(guī)則中命令執(zhí)行的錯(cuò)誤。但會(huì)提示有錯(cuò)誤出現(xiàn),并提示該錯(cuò)誤被忽略。后續(xù)命令可能不能繼續(xù)執(zhí)行,退出make。使用make的命令行選項(xiàng)“-k”或者“--keep-going”,當(dāng)出現(xiàn)錯(cuò)誤時(shí)不立即退出,而是繼續(xù)后續(xù)命令的執(zhí)行。直到無法繼續(xù)執(zhí)行命令時(shí)才異常退出。在make執(zhí)行失敗時(shí),修改錯(cuò)誤之后再次執(zhí)行make之前,使用“makeclean”明確的刪除第一次錯(cuò)誤重建的所有目標(biāo)。為什么?第60頁/共91頁中斷make的執(zhí)行CTRL+C再次執(zhí)行make之前,請(qǐng)先使用makeclean來清除中斷make時(shí)產(chǎn)生的目標(biāo)文件。第61頁/共91頁make的遞歸執(zhí)行在Makefile中使用“make”作為一個(gè)命令來執(zhí)行本身或者其它makefile文件。一般用在一個(gè)存在有多級(jí)子目錄的項(xiàng)目中。舉例:當(dāng)前目錄下,包含一個(gè)子目錄subdir,子目錄中也有一個(gè)Makefile,當(dāng)前目錄下make時(shí),完成包括子目錄的所有編譯,在當(dāng)前目錄下的Makefile中,就可以使用make的遞歸subsystem:cdsubdir&&$(MAKE)subsystem:$(MAKE)-Csubdir或第62頁/共91頁變量MAKE在使用make的遞歸調(diào)用時(shí),在Makefile中規(guī)則的命令行中應(yīng)該使用變量“MAKE”來代替直接使用“make”使用MAKE變量的目的保證最上層使用的make程序和其子目錄下執(zhí)行的make保持一致對(duì)某些make的選項(xiàng)不起作用subsystem:cdsubdir&&$(MAKE)make–t時(shí),直接使用make,和使用MAKE變量,會(huì)有很大的區(qū)別。第63頁/共91頁變量和遞歸上層Makefile中,使用“export變量名”聲明的變量,會(huì)傳遞給子make過程中。變量“SHELL”和“MAKEFLAGS”除非使用指示符“unexport”對(duì)它們進(jìn)行聲明,否則在整個(gè)make的執(zhí)行過程中它們會(huì)始終被自動(dòng)的傳遞給子make指示符“export”或者“unexport”的參數(shù)(變量部分),如果它是對(duì)一個(gè)變量或者函數(shù)的引用,這些變量或者函數(shù)將會(huì)被立即展開。并賦值給export或者unexport的變量第64頁/共91頁export的用法定義變量時(shí),同時(shí)進(jìn)行聲明。例如1.exportVARIABLE=value等效于:VARIABLE=valueexportVARIABLE2.exportVARIABLE:=value等效于:VARIABLE:=valueexportVARIABLE不帶任何參數(shù)的指示符“export”,表示將此Makefile中定義的所有變量傳遞給子make過程第65頁/共91頁變量MAKELEVEL在多級(jí)遞歸調(diào)用的make執(zhí)行過程中。變量“MAKELEVEL”代表了調(diào)用的深度。最上一級(jí)時(shí)“MAKELEVEL”的值為“0”、下一級(jí)時(shí)為“1”、再下一級(jí)為“2”:第66頁/共91頁命令行選項(xiàng)和遞歸在make的遞歸執(zhí)行過程中。最上層(可以稱之為主控)make的命令行選項(xiàng)“-k”、“-s”等被自動(dòng)的通過環(huán)境變量“MAKEFLAGS”傳遞給子make進(jìn)程。在主控執(zhí)行make時(shí)使用“-k”和“-s”選項(xiàng),那么“MAKEFLAGS”的值就為“ks”“-C”、“-f”、“-o”和“-W,這些命令行選項(xiàng)不會(huì)被賦值給變量“MAKEFLAGS”第67頁/共91頁定義命令包什么是命令包?類似C語言中的自定義函數(shù)語法格式:define名稱命令塊endef命令包的使用和對(duì)變量的使用一樣foo.c:foo.y$(run-yacc)definerun-yaccyacc$(firstword$^)mvy.tab.c$@endef自動(dòng)化變量第68頁/共91頁空命令規(guī)則中,只有目標(biāo)文件(可以有依賴文件,但一般不用),但沒有命令行。這就是空命令規(guī)則。格式:target:;使用空命令行可以防止make在執(zhí)行時(shí)圖重建這個(gè)目標(biāo)而查找隱含命令第69頁/共91頁第7章Make及makefile文件的編寫

1.概述2.Makefile3.Makefile的規(guī)則4.規(guī)則的命令5.Makefile中的變量6.執(zhí)行make第70頁/共91頁使用變量/宏Makefile中的變量有如下特征1.Makefile中變量和函數(shù)的展開(除規(guī)則的命令行以外),是在make讀取makefile文件時(shí)進(jìn)行的2.變量名是不包括“:”、“#”、“=”、前置空白和尾空白的任何字符串,但建議只使用字母、數(shù)字、下劃線3.變量名是大小寫敏感的4.自動(dòng)化變量。第71頁/共91頁變量的引用“$(VARIABLE_NAME)”或者“${VARIABLE_NAME}”來引用一個(gè)變量,變量的引用展開過程完全和c語言中的宏展開的過程一樣,是一個(gè)嚴(yán)格的文本替換過程。objects=program.ofoo.outils.oprogram:$(objects)cc-oprogram$(objects)$(objects):defs.hprogram:program.ofoo.outils.occ-oprogramprogram.ofoo.outils.oprogram.ofoo.outils.o:defs.h展開后第72頁/共91頁兩種變量定義一個(gè)變量的定義有兩種方式(或者稱為風(fēng)格)遞歸展開式變量直接展開式變量變量的這兩種不同的風(fēng)格的區(qū)別在于:1.定義方式;2.展開時(shí)機(jī)。第73頁/共91頁遞歸展開式變量變量的定義使用“=”或者“define”指示符來定義在引用的地方是嚴(yán)格的文本替換過程如果此變量定義中存在對(duì)其他變量的引用,這些被引用的變量會(huì)在它被展開的同時(shí)被展開foo=$(bar)bar=$(ugh)ugh=Huh?all:;echo$(foo)執(zhí)行make時(shí),顯示“Huh?”替換過程為:首先“$(foo)”被替換“$(bar)”,接下來“$(bar)”被替換為“$(ugh)”,最后“$(ugh)”被替換為“Hug?”。整個(gè)替換的過程是在執(zhí)行“echo$(foo)”時(shí)進(jìn)行的。第74頁/共91頁優(yōu)缺點(diǎn)優(yōu)點(diǎn):可以引用其它的之前沒有定義的變量,可能在后續(xù)部分定義,或者是通過make的命令行選項(xiàng)傳遞的變量缺點(diǎn):1.可能會(huì)由于出現(xiàn)變量的遞歸定義而導(dǎo)致make陷入到無限的變量展開過程中,最終使make執(zhí)行失敗。例如x=$(y)y=$(x)$(z)2.如果引用了函數(shù),那么函數(shù)總會(huì)在其被引用的地方被執(zhí)行。第75頁/共91頁直接展開式變量使用“:=”來定義的變量該類型變量值中對(duì)另外變量的引用或者函數(shù)的引用在定義時(shí)被展開不能實(shí)現(xiàn)對(duì)其后定義變量的引用推薦使用這種方式定義變量x:=fooy:=$(x)barx:=latery:=foobarx:=later第76頁/共91頁“?=”操作符只有此變量在之前沒有賦值的情況下才會(huì)對(duì)這個(gè)變量進(jìn)行賦值FOO?=bar如果變量“FOO”沒有定義過,就給它賦值“bar”。否則不改變它的值第77頁/共91頁追加變量的值在便令定義時(shí),賦給一個(gè)基本的值,后續(xù)根據(jù)需要,給它增加一些必要的值使用“+=”操作符objects=main.ofoo.obar.outils.oobjects+=another.o會(huì)把a(bǔ)nother.o追加到objects的末尾,并以空格分隔第78頁/共91頁目標(biāo)指定變量在Makefile中定義一個(gè)變量,這個(gè)變量對(duì)此Makefile的所有規(guī)則都是有效的。是一個(gè)“全局的”變量。另一種變量是目標(biāo)指定變量“Target-specificVariable)”。允許對(duì)于相同變量根據(jù)目標(biāo)指定不同的值,目標(biāo)指定的變量值只在指定它的目標(biāo)的上下文中有效。此種變量是“局部的”。.設(shè)置一個(gè)目標(biāo)指定變量的語法為:TARGET...:VARIABLE-ASSIGNMENT或者:TARGET...:overrideVARIABLE-ASSIGNMENT第79頁/共91頁目標(biāo)指定變量說明“VARIABLE-ASSIGNMENT”可以使用任何一個(gè)有效的賦值方式,“=”(遞歸)、“:=”(靜態(tài))、“+=”(追加)或者“?=”(條件)。使用目標(biāo)指定變量值時(shí),目標(biāo)指定的變量值不會(huì)影響同名的那個(gè)全局變量的值。只對(duì)指定的這些目標(biāo)有效目標(biāo)指定的變量變量會(huì)作用到由這個(gè)目標(biāo)所引發(fā)的所有的規(guī)則中去。prog:CFLAGS=-gprog:prog.ofoo

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(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ǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。

最新文檔

評(píng)論

0/150

提交評(píng)論