深入學(xué)習(xí)Make命令和Makefile_第1頁
深入學(xué)習(xí)Make命令和Makefile_第2頁
深入學(xué)習(xí)Make命令和Makefile_第3頁
深入學(xué)習(xí)Make命令和Makefile_第4頁
深入學(xué)習(xí)Make命令和Makefile_第5頁
已閱讀5頁,還剩6頁未讀, 繼續(xù)免費閱讀

下載本文檔

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

文檔簡介

深入學(xué)習(xí)Make命令和Makefile(下)makefilemake是Linux下的一款程序自動維護工具,配合makefile的使用,就能夠根據(jù)程序中模塊的修改情況,自動判斷應(yīng)該對那些模塊重新編譯,從而保證軟件是由最新的模塊構(gòu)成。本文分為上下兩部分,我們在上一篇文章中分別介紹了make和makefile的一些基本用法,在本文中,我們會對make和makefile的功能做進一步的介紹。一、構(gòu)建多個目標(biāo)有時候,我們想要在一個makefile中生成多個單獨的目標(biāo)文件,或者將多個命令放在一起,比如,在下面的示例mymakefile3中我們將添加一個clean選項來清除不需要的目標(biāo)文件,然后用install選項將生成的應(yīng)用程序移動到另一個目錄中去。這個makefile跟前面的mymakefile較為相似,不同之處筆者用黑體加以標(biāo)識:all:main#使用的編譯器CC=gcc#安裝位置INSTDIR=/usr/local/bin#include文件所在位置INCLUDE=.#開發(fā)過程中所用的選項CFLAGS=-g-Wall-ansi#發(fā)行時用的選項#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在這個makefile中需要注意的是,雖然這里有一個特殊的目標(biāo)all,但是最終還是將main作為目標(biāo)。因此,如果執(zhí)行make命令時沒有在命令行中給出一個特定目標(biāo)的話,仍然會編譯連接main程序。其次要注意后面的兩個目標(biāo):clean和install。目標(biāo)clean沒有依賴模塊,因為沒有時間標(biāo)記可供比較,所以它總被執(zhí)行;它的實際意圖是引出后面的rm命令來刪除某些目標(biāo)文件。我們看到rm命令以-開頭,這時即使表示make將忽略命令結(jié)果,所以即使沒有目標(biāo)供rm命令刪除而返回錯誤時,makeclean依然繼續(xù)向下執(zhí)行。接下來的目標(biāo)install依賴于main,所以make知道必須在執(zhí)行安裝命令前先建立main。用于安裝的指令由一些shell命令組成。因為make調(diào)用shell來執(zhí)行規(guī)則,并且為每條規(guī)則生成一個新的shell,所以要用一個shell來執(zhí)行這些命令的話,必須添加反斜杠,以使所有命令位于同一個邏輯行上。這條命令用@開頭,表示在執(zhí)行規(guī)則前不會向標(biāo)準(zhǔn)輸出打印命令。為了安裝應(yīng)用程序,目標(biāo)install會一條接一條地執(zhí)行若干命令,并且執(zhí)行下一個之前,不會檢查上一條命令是否成功。若想只有當(dāng)前面的命令取得成功時,隨后的命令才得以執(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)在前的命令成功時隨后的命令才被執(zhí)行。這里不必關(guān)心前面命令是否取得成功,只需注意這種用法就可以了。要想在/usr/local/bin目錄安裝新命令必須具有特權(quán),所以調(diào)用makeinstall命令之前,可以讓Makefile使用一個不同的安裝目錄,或者修改該目錄的權(quán)限,或切換到root用戶。如下所示:$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$讓我們對此作一簡單介紹,首先刪除main和所有目標(biāo)文件程序,由于將all作為目標(biāo),所以make命令會重新編譯main。當(dāng)我們再次執(zhí)行make命令時,由于main是最新的,所以make什么也不做。之后,我們刪除main程序文件,并執(zhí)行makeinstall,這會重新建立二進制文件main并將其復(fù)制到安裝目錄。最后,運行makeclean命令,來刪去所有目標(biāo)程序。二、內(nèi)部規(guī)則迄今為止,我們已經(jīng)能夠在makefile中給出相應(yīng)的規(guī)則來指出具體的處理過程。實際上,除了我們顯式給出的規(guī)則外,make還具有許多內(nèi)部規(guī)則,這些規(guī)則是由預(yù)先規(guī)定的目標(biāo)、依賴文件及其命令組成的相關(guān)行。在內(nèi)部規(guī)則的幫助下,可以使makefile變得更加簡潔,尤其是在具有許多源文件的時候?,F(xiàn)在以實例加以說明,首先建立一個名為foo.c的C程序源文件,文件內(nèi)容如下所示:#include<stdio.h>intmain()TOC\o"1-5"\h\z{printf(,HelloWorld'n");exit(EXIT_SUCCESS);}現(xiàn)在讓我們用make命令來編譯它:$makefooccfoo.c-ofoo$

您會驚奇地發(fā)現(xiàn),盡管我們沒有指定makefile,但是make仍然能知道如何調(diào)用編譯器,并且調(diào)用的是cc而不是gcc編譯器。這在Linux上沒有問題,因為cc常常會鏈接到gcc程序。這完全得益于make內(nèi)建的內(nèi)部規(guī)則,另外這些內(nèi)部規(guī)則通常使用宏,所以只要為這些宏指定新的值,就可以改變內(nèi)部規(guī)則的默認(rèn)動作,如下所示:$rmfoo$makeCC=gccCFLAGS="-Wall-g"foogcc-Wall-gfoo.c-ofoo$用make命令加-p選項后,可以打印出系統(tǒng)缺省定義的內(nèi)部規(guī)則。它們包括系統(tǒng)預(yù)定義的宏、以及產(chǎn)生某些種類后綴的文件的內(nèi)部相關(guān)行。內(nèi)部規(guī)則涉及的文件種類很多,它不僅包括C源程序文件及其目標(biāo)文件,還包括SCCS文件、yacc文件和lex文件,甚至還包括Shell文件。當(dāng)然,我們更關(guān)心的是如何利用內(nèi)部規(guī)則來簡化makefile,比如讓內(nèi)部規(guī)則來負責(zé)生成目標(biāo),而只指定依賴關(guān)系,這樣makefile就簡潔多了,如下所示:main.o:main.cdef1.hf1.o:f1.cdef1.hdef2.hf2.o:f2.cdef2.hdef3.h三、后綴規(guī)則前面我們已經(jīng)看到,有些內(nèi)部規(guī)則會根據(jù)文件的后綴(相當(dāng)于Windows系統(tǒng)中的文件擴展名)來采取相應(yīng)的處理。換句話說,這樣當(dāng)make見到帶有一種后綴的文件時,就知道使用哪些規(guī)則來建立一個帶有另外一種后綴的文件,最常見的是用以.c結(jié)尾的文件來建立以.o結(jié)尾的文件,即把源文件編譯成目標(biāo)程序,但是不連接?,F(xiàn)在舉例說明后綴規(guī)則的應(yīng)用。有時候,我們需要在不同的平臺下編譯源文件,例如Windows和Linux。假設(shè)我們的源代碼是C++編寫的,那么Windows下其后綴則為.cpp。不過Linux使用的make版本沒有編譯.cpp文件的內(nèi)部規(guī)則,倒是有一個用于.cc的規(guī)則,因為在UNIX操作系統(tǒng)中c++文件擴展名通常為.cc。這時候,要么為每個源文件單獨指定一條規(guī)則,要么為make建立一條新規(guī)則,告訴它如何用.cpp為擴展名的源文件來生成目標(biāo)文件。如果項目中的源文件較多的話,后綴規(guī)則就可以派上用場了。要添加一條新后綴規(guī)則,首先在makefile文件中加入一行來告訴make新后綴是什么;然后就可以添加使用這個新后綴的規(guī)則了。這時,make要用到一條專用的語法:1..〈舊后綴名>.<新后綴名〉:它的作用是定義一條通用規(guī)則,用來將帶有舊后綴名的文件變成帶有新后綴名的文件,文件名保持不變,如要將.cpp文件編譯成.o文件,可以使用一個新的通用規(guī)則:

.SUFFIXES:.cpp.cpp.o:$(CC)-xc++$(CFLAGS)-I$(INCLUDE)-c$<上面的.cpp.o:告訴make這些規(guī)則用于把后綴為.cpp的文件轉(zhuǎn)換成后綴為.o的文件。其中的標(biāo)志-xc++的作用是告訴gcc這次要編譯的源文件是c++源文件。這里,我們使用一個宏$<來通指需要編譯的文件的名稱,不管這些文件名具體是什么。我們只需知道,所有以.cpp為后綴的文件將被編譯成以.o為后綴的文件,例如以是app.cpp的文件將變成app.o。注意,我們只跟make說明如何把.cpp文件變成.o文件就行了,至于如何從目標(biāo)程序文件變成二進制可執(zhí)行文件,因為make早已知曉,所以就不用我們費心了。所以,當(dāng)我們調(diào)用make程序時,它會使用新規(guī)則把類似app.cpp這樣的程序變成app.o,然后使用內(nèi)部規(guī)則將app.o文件連接成一個可執(zhí)行文件app?,F(xiàn)在,make已經(jīng)知道如何處理擴展名為.cpp的c++源文件,除此之外,我們還可以通過后綴規(guī)則將文件從一種類型轉(zhuǎn)換為另一種類型。不過,較新版本的make包含一個語法可以達到同樣的效果。例如,模式規(guī)則使用%作為匹配文件名的通配符,而不單獨依賴于文件擴展名。以下模式規(guī)則相當(dāng)于上面處理.cpp的規(guī)則,具體如下所示:%.cpp:%o$(CC)-xc++$(CFLAGS)-I$(INCLUDE)-c$<四、用make管理程序庫一般來說,程序庫也是一種由一組目標(biāo)程序構(gòu)成的以.a為擴展名的文件,所以,Make命令也可以用來管理這些程序庫。實際上,為了簡化程序庫的管理,make程序還專門設(shè)有一個語法:lib(file.o)這意味著目標(biāo)文件file.o以庫文件lib.a的形式存放,這意味著lib.a庫依賴于目標(biāo)程序file.o。此外,make命令還具有一個內(nèi)部規(guī)則用來管理程序庫,該規(guī)則相當(dāng)于如下內(nèi)容:.c.a:$(CC)-c$(CFLAGS)$<$(AR)$(ARFLAGS)$@$*.o其中,宏$(AR)和$3日「1入6,)分別表示指令A(yù)R和選項rv。如上所見,要告訴make用.c文件生成.a庫,必須用到兩個規(guī)則:第一個規(guī)則是說把源文件編譯成一個目標(biāo)程序文件。第二個規(guī)則表示使用ar指令向庫中添加新的目標(biāo)文件。所以,如果我們有一個名為filed的庫,其中含有bar.o文件,那么第一規(guī)則中的$<會被替換為bar.c;在第二個規(guī)則中的$@被庫名filed.a所替代,而$*將被bar所替代。

下面舉例說明如何用make來管理庫。實際上,用make來管理程序庫的規(guī)則是很簡單的。比如,我們可以將前面示例加以修改,讓fl.o和f2.o放在一個稱為mylib.a的程序庫中,這時的Makefile幾乎無需改變,而新的mymakefile4看上去是這樣的:all:main#使用的編譯器CC=gcc#安裝位置INSTDIR=/usr/local/bin#include文件所在位置INCLUDE=.#開發(fā)過程中使用的選項CFLAGS=-g-Wall-ansi#用于發(fā)行時的選項#CFLAGS=-O-Wall-ansi#本地庫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ī)則來替我們完成大部分工作的。如今,我們可以試一下新版的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)在對上面的例子做必要的說明。首先刪除全部目標(biāo)程序文件和程序庫,然后讓make重新構(gòu)建main,因為當(dāng)連接main.o時需要用到庫,所以要先編譯和創(chuàng)建庫。此后,我們還測試f2.o的依賴關(guān)系,我們知道如果def3.h發(fā)生了改變,那么必須重新編譯f2.c,事實表明make在重新構(gòu)建main可執(zhí)行文件之前,正確地編譯了f2.c并更新了庫。五、Makefile和子目錄如果你的項目比較大的話,可以考慮將某些文件組成一個庫,然后單獨存放到一個子目錄內(nèi)。這時,對于makefile有兩種處理方法,下面分別介紹。第一種方法:在子目錄中放置一個輔助makefile,然后把這個子目錄中的源文件編譯成一個程序庫,最后將這個庫復(fù)制到主目錄中。上級目錄中的主要makefile可以放上一個規(guī)則,通過調(diào)用輔助makefile來建立該庫:mylib.a:(cdmylibdirectory;$(MAKE))這樣的話,我們就會總是構(gòu)建mylib.a,因為冒號右邊為空。當(dāng)make調(diào)用該規(guī)則構(gòu)建該庫時,它會切換到子目錄mylibdirectory中,然后調(diào)用一個新的make命令來管理該庫。因為調(diào)用了一個新的shell來完成此任務(wù),所以使用makefile的程序不必進行目錄切換。不過,被調(diào)用的shell是在一個不同的目錄中利用該規(guī)則構(gòu)建該庫的,所以括孤能確保所有處理都是由一個shell完成的。第二種方法:在單個makefile中使用更多的宏,不過這些附加的宏需要在目錄名上加D并且為文件名加上F。例如,可以用下面的命令來覆蓋內(nèi)建的.c.o后綴規(guī)則:

.c.o:$(CC)$(CFLAGS)-c$(@D)/$(為在子目錄編譯文件,并將目標(biāo)放在子目錄中,可以用像下面這樣的依賴關(guān)系和規(guī)則來更新當(dāng)前目錄中的庫:myli

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

最新文檔

評論

0/150

提交評論