版權(quán)說(shuō)明:本文檔由用戶(hù)提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡(jiǎn)介
深入學(xué)習(xí)Make命令和Makefile(下)makefilemake是Linux下的一款程序自動(dòng)維護(hù)工具,配合makefile的使用,就能夠根據(jù)程序中模塊的修改情況,自動(dòng)判斷應(yīng)該對(duì)那些模塊重新編譯,從而保證軟件是由最新的模塊構(gòu)成。本文分為上下兩部分,我們?cè)谏弦黄恼轮蟹謩e介紹了make和makefile的一些基本用法,在本文中,我們會(huì)對(duì)make和makefile的功能做進(jìn)一步的介紹。一、構(gòu)建多個(gè)目標(biāo)有時(shí)候,我們想要在一個(gè)makefile中生成多個(gè)單獨(dú)的目標(biāo)文件,或者將多個(gè)命令放在一起,比如,在下面的示例mymakefile3中我們將添加一個(gè)clean選項(xiàng)來(lái)清除不需要的目標(biāo)文件,然后用install選項(xiàng)將生成的應(yīng)用程序移動(dòng)到另一個(gè)目錄中去。這個(gè)makefile跟前面的mymakefile較為相似,不同之處筆者用黑體加以標(biāo)識(shí):all:main#使用的編譯器CC=gcc#安裝位置INSTDIR=/usr/local/bin#include文件所在位置INCLUDE=.#開(kāi)發(fā)過(guò)程中所用的選項(xiàng)CFLAGS=-g-Wall-ansi#發(fā)行時(shí)用的選項(xiàng)#CFLAGS=-O-Wall-ansimain:main.of1.of2.o$(CC)-omainmain.of1.of2.omain.o:main.cdef1.h$(CC)-I$(INCLUDE)$(CFLAGS)-cmain.cf1.o:f1.cdef1.hdef2.h$(CC)-I$(INCLUDE)$(CFLAGS)-cf1.cf2.o:f2.cdef2.hdef3.h$(CC)-I$(INCLUDE)$(CFLAGS)-cf2.cclean:-rmmain.of1.of2.o
install:main@if[-d$(INSTDIR)];\then\cpmain$(INSTDIR);\chmoda+x$(INSTDIR)/main;\chmodog-w$(INSTDIR)/main;\echoInstalledin$(INSTDIR);\else\echoSorry,$(INSTDIR)doesnotexist";'fi在這個(gè)makefile中需要注意的是,雖然這里有一個(gè)特殊的目標(biāo)all,但是最終還是將main作為目標(biāo)。因此,如果執(zhí)行make命令時(shí)沒(méi)有在命令行中給出一個(gè)特定目標(biāo)的話,仍然會(huì)編譯連接main程序。其次要注意后面的兩個(gè)目標(biāo):clean和install。目標(biāo)clean沒(méi)有依賴(lài)模塊,因?yàn)闆](méi)有時(shí)間標(biāo)記可供比較,所以它總被執(zhí)行;它的實(shí)際意圖是引出后面的rm命令來(lái)刪除某些目標(biāo)文件。我們看到rm命令以-開(kāi)頭,這時(shí)即使表示make將忽略命令結(jié)果,所以即使沒(méi)有目標(biāo)供rm命令刪除而返回錯(cuò)誤時(shí),makeclean依然繼續(xù)向下執(zhí)行。接下來(lái)的目標(biāo)install依賴(lài)于main,所以make知道必須在執(zhí)行安裝命令前先建立main。用于安裝的指令由一些shell命令組成。因?yàn)閙ake調(diào)用shell來(lái)執(zhí)行規(guī)則,并且為每條規(guī)則生成一個(gè)新的shell,所以要用一個(gè)shell來(lái)執(zhí)行這些命令的話,必須添加反斜杠,以使所有命令位于同一個(gè)邏輯行上。這條命令用@開(kāi)頭,表示在執(zhí)行規(guī)則前不會(huì)向標(biāo)準(zhǔn)輸出打印命令。為了安裝應(yīng)用程序,目標(biāo)install會(huì)一條接一條地執(zhí)行若干命令,并且執(zhí)行下一個(gè)之前,不會(huì)檢查上一條命令是否成功。若想只有當(dāng)前面的命令取得成功時(shí),隨后的命令才得以執(zhí)行的話,可以在命令中加入&&,如下所示:@if[-d$(INSTDIR)];\then\cpmain$(INSTDIR)&&\chmoda+x$(INSTDIR)/main&&\chmodog-w$(INSTDIR/main&&\echoInstalledin$(INSTDIR);\else\echoSorry,$(INSTDIR)doesnotexist";false;\fi這是shell的“與”指令,只有當(dāng)在前的命令成功時(shí)隨后的命令才被執(zhí)行。這里不必關(guān)心前面命令是否取得成功,只需注意這種用法就可以了。要想在/usr/local/bin目錄安裝新命令必須具有特權(quán),所以調(diào)用makeinstall命令之前,可以讓Makefile使用一個(gè)不同的安裝目錄,或者修改該目錄的權(quán)限,或切換到root用戶(hù)。如下所示:$rm*.omain
$make-fMymakefile3gcc -I. -g -Wall -ansi -c main.cgcc -I. -g -Wall -ansi -c fl.cgcc -I. -g -Wall -ansi -c f2.cgcc -omainmain.of1.of2.o$make-fMymakefile3make:Nothingtobedonefor‘a(chǎn)ll’.$rmmain$make-fMymakefile3installgcc-omainmain.of1.of2.oInstalledin/usr/local/bin$make-fMymakefile3cleanrmmain.of1.of2.o$讓我們對(duì)此作一簡(jiǎn)單介紹,首先刪除main和所有目標(biāo)文件程序,由于將all作為目標(biāo),所以make命令會(huì)重新編譯main。當(dāng)我們?cè)俅螆?zhí)行make命令時(shí),由于main是最新的,所以make什么也不做。之后,我們刪除main程序文件,并執(zhí)行makeinstall,這會(huì)重新建立二進(jìn)制文件main并將其復(fù)制到安裝目錄。最后,運(yùn)行makeclean命令,來(lái)刪去所有目標(biāo)程序。二、內(nèi)部規(guī)則迄今為止,我們已經(jīng)能夠在makefile中給出相應(yīng)的規(guī)則來(lái)指出具體的處理過(guò)程。實(shí)際上,除了我們顯式給出的規(guī)則外,make還具有許多內(nèi)部規(guī)則,這些規(guī)則是由預(yù)先規(guī)定的目標(biāo)、依賴(lài)文件及其命令組成的相關(guān)行。在內(nèi)部規(guī)則的幫助下,可以使makefile變得更加簡(jiǎn)潔,尤其是在具有許多源文件的時(shí)候?,F(xiàn)在以實(shí)例加以說(shuō)明,首先建立一個(gè)名為foo.c的C程序源文件,文件內(nèi)容如下所示:#include<stdio.h>intmain()TOC\o"1-5"\h\z{printf(,HelloWorld'n");exit(EXIT_SUCCESS);}現(xiàn)在讓我們用make命令來(lái)編譯它:$makefooccfoo.c-ofoo$
您會(huì)驚奇地發(fā)現(xiàn),盡管我們沒(méi)有指定makefile,但是make仍然能知道如何調(diào)用編譯器,并且調(diào)用的是cc而不是gcc編譯器。這在Linux上沒(méi)有問(wèn)題,因?yàn)閏c常常會(huì)鏈接到gcc程序。這完全得益于make內(nèi)建的內(nèi)部規(guī)則,另外這些內(nèi)部規(guī)則通常使用宏,所以只要為這些宏指定新的值,就可以改變內(nèi)部規(guī)則的默認(rèn)動(dòng)作,如下所示:$rmfoo$makeCC=gccCFLAGS="-Wall-g"foogcc-Wall-gfoo.c-ofoo$用make命令加-p選項(xiàng)后,可以打印出系統(tǒng)缺省定義的內(nèi)部規(guī)則。它們包括系統(tǒng)預(yù)定義的宏、以及產(chǎn)生某些種類(lèi)后綴的文件的內(nèi)部相關(guān)行。內(nèi)部規(guī)則涉及的文件種類(lèi)很多,它不僅包括C源程序文件及其目標(biāo)文件,還包括SCCS文件、yacc文件和lex文件,甚至還包括Shell文件。當(dāng)然,我們更關(guān)心的是如何利用內(nèi)部規(guī)則來(lái)簡(jiǎn)化makefile,比如讓內(nèi)部規(guī)則來(lái)負(fù)責(zé)生成目標(biāo),而只指定依賴(lài)關(guān)系,這樣makefile就簡(jiǎn)潔多了,如下所示:main.o:main.cdef1.hf1.o:f1.cdef1.hdef2.hf2.o:f2.cdef2.hdef3.h三、后綴規(guī)則前面我們已經(jīng)看到,有些內(nèi)部規(guī)則會(huì)根據(jù)文件的后綴(相當(dāng)于Windows系統(tǒng)中的文件擴(kuò)展名)來(lái)采取相應(yīng)的處理。換句話說(shuō),這樣當(dāng)make見(jiàn)到帶有一種后綴的文件時(shí),就知道使用哪些規(guī)則來(lái)建立一個(gè)帶有另外一種后綴的文件,最常見(jiàn)的是用以.c結(jié)尾的文件來(lái)建立以.o結(jié)尾的文件,即把源文件編譯成目標(biāo)程序,但是不連接。現(xiàn)在舉例說(shuō)明后綴規(guī)則的應(yīng)用。有時(shí)候,我們需要在不同的平臺(tái)下編譯源文件,例如Windows和Linux。假設(shè)我們的源代碼是C++編寫(xiě)的,那么Windows下其后綴則為.cpp。不過(guò)Linux使用的make版本沒(méi)有編譯.cpp文件的內(nèi)部規(guī)則,倒是有一個(gè)用于.cc的規(guī)則,因?yàn)樵赨NIX操作系統(tǒng)中c++文件擴(kuò)展名通常為.cc。這時(shí)候,要么為每個(gè)源文件單獨(dú)指定一條規(guī)則,要么為make建立一條新規(guī)則,告訴它如何用.cpp為擴(kuò)展名的源文件來(lái)生成目標(biāo)文件。如果項(xiàng)目中的源文件較多的話,后綴規(guī)則就可以派上用場(chǎng)了。要添加一條新后綴規(guī)則,首先在makefile文件中加入一行來(lái)告訴make新后綴是什么;然后就可以添加使用這個(gè)新后綴的規(guī)則了。這時(shí),make要用到一條專(zhuān)用的語(yǔ)法:1..〈舊后綴名>.<新后綴名〉:它的作用是定義一條通用規(guī)則,用來(lái)將帶有舊后綴名的文件變成帶有新后綴名的文件,文件名保持不變,如要將.cpp文件編譯成.o文件,可以使用一個(gè)新的通用規(guī)則:
.SUFFIXES:.cpp.cpp.o:$(CC)-xc++$(CFLAGS)-I$(INCLUDE)-c$<上面的.cpp.o:告訴make這些規(guī)則用于把后綴為.cpp的文件轉(zhuǎn)換成后綴為.o的文件。其中的標(biāo)志-xc++的作用是告訴gcc這次要編譯的源文件是c++源文件。這里,我們使用一個(gè)宏$<來(lái)通指需要編譯的文件的名稱(chēng),不管這些文件名具體是什么。我們只需知道,所有以.cpp為后綴的文件將被編譯成以.o為后綴的文件,例如以是app.cpp的文件將變成app.o。注意,我們只跟make說(shuō)明如何把.cpp文件變成.o文件就行了,至于如何從目標(biāo)程序文件變成二進(jìn)制可執(zhí)行文件,因?yàn)閙ake早已知曉,所以就不用我們費(fèi)心了。所以,當(dāng)我們調(diào)用make程序時(shí),它會(huì)使用新規(guī)則把類(lèi)似app.cpp這樣的程序變成app.o,然后使用內(nèi)部規(guī)則將app.o文件連接成一個(gè)可執(zhí)行文件app?,F(xiàn)在,make已經(jīng)知道如何處理擴(kuò)展名為.cpp的c++源文件,除此之外,我們還可以通過(guò)后綴規(guī)則將文件從一種類(lèi)型轉(zhuǎn)換為另一種類(lèi)型。不過(guò),較新版本的make包含一個(gè)語(yǔ)法可以達(dá)到同樣的效果。例如,模式規(guī)則使用%作為匹配文件名的通配符,而不單獨(dú)依賴(lài)于文件擴(kuò)展名。以下模式規(guī)則相當(dāng)于上面處理.cpp的規(guī)則,具體如下所示:%.cpp:%o$(CC)-xc++$(CFLAGS)-I$(INCLUDE)-c$<四、用make管理程序庫(kù)一般來(lái)說(shuō),程序庫(kù)也是一種由一組目標(biāo)程序構(gòu)成的以.a為擴(kuò)展名的文件,所以,Make命令也可以用來(lái)管理這些程序庫(kù)。實(shí)際上,為了簡(jiǎn)化程序庫(kù)的管理,make程序還專(zhuān)門(mén)設(shè)有一個(gè)語(yǔ)法:lib(file.o)這意味著目標(biāo)文件file.o以庫(kù)文件lib.a的形式存放,這意味著lib.a庫(kù)依賴(lài)于目標(biāo)程序file.o。此外,make命令還具有一個(gè)內(nèi)部規(guī)則用來(lái)管理程序庫(kù),該規(guī)則相當(dāng)于如下內(nèi)容:.c.a:$(CC)-c$(CFLAGS)$<$(AR)$(ARFLAGS)$@$*.o其中,宏$(AR)和$3日「1入6,)分別表示指令A(yù)R和選項(xiàng)rv。如上所見(jiàn),要告訴make用.c文件生成.a庫(kù),必須用到兩個(gè)規(guī)則:第一個(gè)規(guī)則是說(shuō)把源文件編譯成一個(gè)目標(biāo)程序文件。第二個(gè)規(guī)則表示使用ar指令向庫(kù)中添加新的目標(biāo)文件。所以,如果我們有一個(gè)名為filed的庫(kù),其中含有bar.o文件,那么第一規(guī)則中的$<會(huì)被替換為bar.c;在第二個(gè)規(guī)則中的$@被庫(kù)名filed.a所替代,而$*將被bar所替代。
下面舉例說(shuō)明如何用make來(lái)管理庫(kù)。實(shí)際上,用make來(lái)管理程序庫(kù)的規(guī)則是很簡(jiǎn)單的。比如,我們可以將前面示例加以修改,讓fl.o和f2.o放在一個(gè)稱(chēng)為mylib.a的程序庫(kù)中,這時(shí)的Makefile幾乎無(wú)需改變,而新的mymakefile4看上去是這樣的:all:main#使用的編譯器CC=gcc#安裝位置INSTDIR=/usr/local/bin#include文件所在位置INCLUDE=.#開(kāi)發(fā)過(guò)程中使用的選項(xiàng)CFLAGS=-g-Wall-ansi#用于發(fā)行時(shí)的選項(xiàng)#CFLAGS=-O-Wall-ansi#本地庫(kù)MYLIB=mylib.amain:main.o$(MYLIB)$(CC)-omainmain.o$(MYLIB)$(MYLIB):$(MYLIB)(f1.o)$(MYLIB)(f2.o)main.o:main.cdef1.hf1.o:f1.cdef1.hdef2.hf2.o:f2.cdef2.hdef3.hclean:-rmmain.of1.of2.o$(MYLIB)install:main@if[-d$(INSTDIR)];\then\cpmain$(INSTDIR);\chmoda+x$(INSTDIR)/main;\chmodog-w$(INSTDIR)/main;\echo,Installedin$(INSTDIR),;\else\echo,Sorry,$(INSTDIR)doesnotexist";'fi注意:我們是如何讓省缺規(guī)則來(lái)替我們完成大部分工作的。如今,我們可以試一下新版的makefile的工作情況:1.$rm-fmain*.omylib.1.$rm-fmain*.omylib.a2.3.$make-fMymakefile44.gcc-g-Wall-ansi-c-omain.omain.c5.5.gcc-g-Wall-ansi-c-of1.of1.carrvmylib.afl.oa-fl.ogcc-g-Wall-ansi-c-of2.of2.carrvmylib.af2.oa-f2.ogcc-omainmain.omylib.a12.$touchdef3.h14.$make-fMymakefile4gcc-g-Wall-ansi-c-of2.of2.carrvmylib.af2.or-f2.ogcc-omainmain.omylib.a$現(xiàn)在對(duì)上面的例子做必要的說(shuō)明。首先刪除全部目標(biāo)程序文件和程序庫(kù),然后讓make重新構(gòu)建main,因?yàn)楫?dāng)連接main.o時(shí)需要用到庫(kù),所以要先編譯和創(chuàng)建庫(kù)。此后,我們還測(cè)試f2.o的依賴(lài)關(guān)系,我們知道如果def3.h發(fā)生了改變,那么必須重新編譯f2.c,事實(shí)表明make在重新構(gòu)建main可執(zhí)行文件之前,正確地編譯了f2.c并更新了庫(kù)。五、Makefile和子目錄如果你的項(xiàng)目比較大的話,可以考慮將某些文件組成一個(gè)庫(kù),然后單獨(dú)存放到一個(gè)子目錄內(nèi)。這時(shí),對(duì)于makefile有兩種處理方法,下面分別介紹。第一種方法:在子目錄中放置一個(gè)輔助makefile,然后把這個(gè)子目錄中的源文件編譯成一個(gè)程序庫(kù),最后將這個(gè)庫(kù)復(fù)制到主目錄中。上級(jí)目錄中的主要makefile可以放上一個(gè)規(guī)則,通過(guò)調(diào)用輔助makefile來(lái)建立該庫(kù):mylib.a:(cdmylibdirectory;$(MAKE))這樣的話,我們就會(huì)總是構(gòu)建mylib.a,因?yàn)槊疤?hào)右邊為空。當(dāng)make調(diào)用該規(guī)則構(gòu)建該庫(kù)時(shí),它會(huì)切換到子目錄mylibdirectory中,然后調(diào)用一個(gè)新的make命令來(lái)管理該庫(kù)。因?yàn)檎{(diào)用了一個(gè)新的shell來(lái)完成此任務(wù),所以使用makefile的程序不必進(jìn)行目錄切換。不過(guò),被調(diào)用的shell是在一個(gè)不同的目錄中利用該規(guī)則構(gòu)建該庫(kù)的,所以括孤能確保所有處理都是由一個(gè)shell完成的。第二種方法:在單個(gè)makefile中使用更多的宏,不過(guò)這些附加的宏需要在目錄名上加D并且為文件名加上F。例如,可以用下面的命令來(lái)覆蓋內(nèi)建的.c.o后綴規(guī)則:
.c.o:$(CC)$(CFLAGS)-c$(@D)/$(為在子目錄編譯文件,并將目標(biāo)放在子目錄中,可以用像下面這樣的依賴(lài)關(guān)系和規(guī)則來(lái)更新當(dāng)前目錄中的庫(kù):myli
溫馨提示
- 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶(hù)所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶(hù)上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶(hù)上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶(hù)因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 衛(wèi)生室藥房管理制度
- 回轉(zhuǎn)窯衛(wèi)生管理制度
- 品牌衛(wèi)生巾代理制度
- 外包工職業(yè)衛(wèi)生管理制度
- 水果店衛(wèi)生管理制度
- 物業(yè)公司衛(wèi)生間管理制度
- 衛(wèi)生院醫(yī)療票據(jù)管理制度
- 衛(wèi)生院醫(yī)保檔案制度
- 新農(nóng)村環(huán)境衛(wèi)生管理制度
- 2026湖北十堰市丹江口市衛(wèi)生健康局所屬事業(yè)單位選聘14人參考考試題庫(kù)及答案解析
- 手術(shù)區(qū)消毒和鋪巾
- 國(guó)家中醫(yī)藥管理局《中醫(yī)藥事業(yè)發(fā)展“十五五”規(guī)劃》全文
- 師德師風(fēng)個(gè)人總結(jié)課件
- 化學(xué)-江蘇省蘇州市2024-2025學(xué)年第一學(xué)期學(xué)業(yè)質(zhì)量陽(yáng)光指標(biāo)調(diào)研卷暨高二上學(xué)期期末考試試題和答案
- 精神科疑難病例討論
- 騰訊00后研究報(bào)告
- 固體廢物 鉛和鎘的測(cè)定 石墨爐原子吸收分光光度法(HJ 787-2016)
- DB45-T 2675-2023 木薯米粉加工技術(shù)規(guī)程
- 板材眼鏡生產(chǎn)工藝
- Unit 3 My weekend plan B Let's talk(教案)人教PEP版英語(yǔ)六年級(jí)上冊(cè)
評(píng)論
0/150
提交評(píng)論