日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

GUN Make指南

發(fā)布時(shí)間:2025/3/14 编程问答 37 豆豆
生活随笔 收集整理的這篇文章主要介紹了 GUN Make指南 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

GUN Make介紹

1 GUN Make makefile簡(jiǎn)介

在大型的開發(fā)項(xiàng)目中,通常有幾十到上百個(gè)的源文件,如果每次均手工鍵入 gcc 命令進(jìn)行編譯的話,則會(huì)非常不方便。因此,人們通常利用 make 工具來自動(dòng)完成編譯工作。這些工作包括:如果僅修改了某幾個(gè)源文件,則只重新編譯這幾個(gè)源文件;如果某個(gè)頭文件被修改了,則重新編譯所有包含該頭文件的源 文件。
利用這種自動(dòng)編譯可大大簡(jiǎn)化開發(fā)工作,避免不必要的重新編譯。
實(shí)際上,make 工具通過一個(gè)稱為 makefile 的文件來完成并自動(dòng)維護(hù)編譯工作。makefile 需要按照某種語法進(jìn)行編寫,其中說明了如何編譯各個(gè)源文件并連接生成可執(zhí)行文件,并定義了源文件之間的依賴關(guān)系。
當(dāng)修改了其中某個(gè)源文件時(shí),如果其他源文件依賴于該文件,則也要重新編譯所有依賴該文件的源文件。
makefile 文件是許多編譯器,包括 Windows NT 下的編譯器維護(hù)編譯信息的常用方法,只是在集成開發(fā)環(huán)境中,用戶通過友好的界面修改 makefile 文件而已。
默認(rèn)情況下,GNU make 工具在當(dāng)前工作目錄中按如下順序搜索 makefile
* GNUmakefile
* makefile
* Makefile
UNIX 系統(tǒng)中,習(xí)慣使用 Makefile 作為 makfile 文件。如果要使用其他文件作為 makefile,則可利用類
似下面的 make 命令選項(xiàng)指定 makefile 文件:
$ make -f Makefile.debug

2 GNU Make 工具
~~~~~~~~~~~~~~~~
?
2.1 基本 makefile 結(jié)構(gòu)
GNU Make 的主要工作是讀進(jìn)一個(gè)文本文件, makefile 。這個(gè)文件里主要是有關(guān)哪些文件(‘target’目的文件)是從哪些別的 文件(‘dependencies’依靠文件)中產(chǎn)生的,用什么命令來進(jìn)行這個(gè)產(chǎn)生過程。有了這些信息, make 會(huì)檢查磁碟上的文件,如果 目的文件的時(shí)間戳(該文件生成或被改動(dòng)時(shí)的時(shí)間)比至少它的一個(gè)依靠文件舊的話, make 就執(zhí)行相應(yīng)的命令,以便更新目的文件。 (目的文件不一定是最后的可執(zhí)行檔,它可以是任何一個(gè)文件。)
?
makefile 一般被叫做“makefile”“Makefile”。當(dāng)然你可以 make 的命令行指定別的文件名。如果你不特別指定,它會(huì)尋 “makefile”“Makefile”,因此使用這兩個(gè)名字是最簡(jiǎn)單 的。
一個(gè) makefile 主要含有一系列的規(guī)則,如下:

:?
(tab)
<command>
(tab)
<command>
.
.
.


?
例如,考慮以下的 makefile

===?makefile?開始?===
myprog?:?foo.o?bar.o
?gcc?foo.o?bar.o?
-o?myprog
?
foo.o?:?foo.c?foo.h?bar.h
?gcc?
-c?foo.c?-o?foo.o
?
bar.o?:?bar.c?bar.h
?gcc?
-c?bar.c?-o?bar.o
===?makefile?結(jié)束?===


?
是一個(gè)非常基本的 makefile —— make 從最上面開始,把上面第一個(gè)目的,‘myprog’,做為它的主要目標(biāo)(一個(gè)它需要保 證其總是最新的最終目標(biāo))。給出的規(guī)則說明只要文件‘myprog’ 比文件‘foo.o’‘bar.o’中的任何一個(gè)舊,下一行的命令將 會(huì)被執(zhí)行。
?
是,在檢查文件 foo.o bar.o 的時(shí)間戳之前,它會(huì)往下查找那些把 foo.o bar.o 做為目標(biāo)文件的規(guī)則。它找到的關(guān)于 foo.o 的規(guī)則,該文件的依靠文件是 foo.c, foo.h bar.h 它從下面再找不到生成這些依靠文件的規(guī)則,它就開始檢查磁碟 上這些依靠文件的時(shí)間戳。如果這些文件中任何一個(gè)的時(shí)間戳比 foo.o 的新,命令 'gcc -o foo.o foo.c' 將會(huì)執(zhí)行,從而更新 文件 foo.o
?
接下來對(duì)文件 bar.o 做類似的檢查,依靠文件在這里是文件 bar.c bar.h
?
現(xiàn)在, make 回到‘myprog’的規(guī)則。如果剛才兩個(gè)規(guī)則中的任 何一個(gè)被執(zhí)行,myprog 就需要重建(因?yàn)槠渲幸粋€(gè) .o 檔就會(huì)比 ‘myprog’新),因此連接命令將被執(zhí)行。
?
望到此,你可以看出使用 make 工具來建立程序的好處——前一章中所有繁瑣的檢查步驟都由 make 替你做了:檢查時(shí)間戳。 你的源碼文件里一個(gè)簡(jiǎn)單改變都會(huì)造成那個(gè)文件被重新編譯(因 .o 文件依靠 .c 文件),進(jìn)而可執(zhí)行文件被重新連接(因?yàn)?/span> .o 文件被改變了)。其實(shí)真正的得益是在當(dāng)你改變一個(gè) header 檔的時(shí)候——你不再需要記住那個(gè)源碼文件依靠它,因?yàn)樗械?/span> 資料都在 makefile 里。 make 會(huì)很輕松的替你重新編譯所有那些因依靠這個(gè) header 文件而改變了的源碼文件,如有需要,再 進(jìn)行重新連接。
?
當(dāng)然,你要確定你在 makefile 中所寫的規(guī)則是正確無誤的,只 列出那些在源碼文件中被 #include header ……
?
2.2 編寫 make 規(guī)則 (Rules)
?
明顯的(也是最簡(jiǎn)單的)編寫規(guī)則的方法是一個(gè)一個(gè)的查看源碼文件,把它們的目標(biāo)文件做為目的,而C源碼文件和被它 #include header 檔做為依靠文件。但是你也要把其它被這些 header #include header 檔也列為依靠文件,還有那些被 包括的文件所包括的文件……然后你會(huì)發(fā)現(xiàn)要對(duì)越來越多的文件進(jìn)行管理,然后你的頭發(fā)開始脫落,你的脾氣開始變壞,你的臉 色變成菜色,你走在路上開始跟電線桿子碰撞,終于你搗毀你的電腦顯示器,停止編程。到低有沒有些容易點(diǎn)兒的方法呢?
?
當(dāng)然有!向編譯器 要!在編譯每一個(gè)源碼文件的時(shí)候,它實(shí)在應(yīng)該知道應(yīng)該包括什么樣的 header 檔。使用 gcc 的時(shí)候,用 -M 開關(guān),它會(huì)為每一個(gè)你給它的C文件輸出一個(gè)規(guī)則,把目標(biāo)文件做為目的,而這個(gè)C文件和所有應(yīng)該被 #include header 件將做為依靠文件。注意這個(gè)規(guī)則會(huì)加入所有 header 文件,包括被角括號(hào)(`<', `>')和雙引號(hào)(`"')所包圍的文件。其實(shí)我們可以 相當(dāng)肯定系統(tǒng) header 檔(比如 stdio.h, stdlib.h 等等)不會(huì) 被我們更改,如果你用 -MM 來代替 -M 傳遞給 gcc,那些用角括 號(hào)包圍的 header 檔將不會(huì)被包括。(這會(huì)節(jié)省一些編譯時(shí)間)
?
gcc 輸出的規(guī)則不會(huì)含有命令部分;你可以自己寫入你的命令 或者什么也不寫,而讓 make 使用它的隱含的規(guī)則(參考下面的 2.4 節(jié))。
?
2.3 Makefile 變量
?
上面提到 makefiles 里主要包含一些規(guī)則。它們包含的其它的東 西是變量定義。
?
makefile 里的變量就像一個(gè)環(huán)境變量(environment variable) 事實(shí)上,環(huán)境變量在 make 過程中被解釋成 make 的變量。這些變量是大小寫敏感的,一般使用大寫字母。它們可以從幾乎任何 地方被引用,也可以被用來做很多事情,比如:
i) 貯存一個(gè)文件名列表。在上面的例子里,生成可執(zhí)行文件的 規(guī)則包含一些目標(biāo)文件名做為依靠。在這個(gè)規(guī)則的命令行 里同樣的那些文件被輸送給 gcc 做為命令參數(shù)。如果在這 里使用一個(gè)變數(shù)來貯存所有的目標(biāo)文件名,加入新的目標(biāo) 文件會(huì)變的簡(jiǎn)單而且較不易出錯(cuò)。
?
ii) 貯存可執(zhí)行文件名。如果你的項(xiàng)目被用在一個(gè)非 gcc 的系 統(tǒng)里,或者如果你想使用一個(gè)不同的編譯器,你必須將所 有使用編譯器的地方改成用新的編譯器名。但是如果使用一 個(gè)變量來代替編譯器名,那么你只需要改變一個(gè)地方,其 它所有地方的命令名就都改變了。
?
iii) 貯存編譯器旗標(biāo)。假設(shè)你想給你所有的編譯命令傳遞一組 相同的選項(xiàng)(例如 -Wall -O -g);如果你把這組選項(xiàng)存 入一個(gè)變量,那么你可以把這個(gè)變量放在所有呼叫編譯器 的地方。而當(dāng)你要改變選項(xiàng)的時(shí)候,你只需在一個(gè)地方改 變這個(gè)變量的內(nèi)容。
要設(shè)定一個(gè)變量,你只要在一行的開始寫下這個(gè)變量的名字,后 面跟一個(gè) = 號(hào),后面跟你要設(shè)定的這個(gè)變量的值。以后你要引用 這個(gè)變量,寫一個(gè) $ 符號(hào),后面是圍在括號(hào)里的變量名。比如在 下面,我們把前面的 makefile 利用變量重寫一遍:
?

===?makefile?開始?===
OBJS?
=?foo.o?bar.o
CC?
=?gcc
CFLAGS?
=?-Wall?-O?-g
?
myprog?:?$(OBJS)
?$(CC)?$(OBJS)?
-o?myprog
?
foo.o?:?foo.c?foo.h?bar.h
?$(CC)?$(CFLAGS)?
-c?foo.c?-o?foo.o
?
bar.o?:?bar.c?bar.h
?$(CC)?$(CFLAGS)?
-c?bar.c?-o?bar.o
===?makefile?結(jié)束?===


?
有一些設(shè)定好的內(nèi)部變量,它們根據(jù)每一個(gè)規(guī)則內(nèi)容定義。三個(gè) 比較有用的變量是 $@, $< $^ (這些變量不需要括號(hào)括住)。 $@ 擴(kuò)展成當(dāng)前規(guī)則的目的文件名, $< 擴(kuò)展成依靠列表中的第一個(gè)依靠文件,而 $^ 擴(kuò)展成整個(gè)依靠的列表(除掉了里面所有重 復(fù)的文件名)。利用這些變量,我們可以把上面的 makefile 寫成:
?

===?makefile?開始?===
OBJS?
=?foo.o?bar.o
CC?
=?gcc
CFLAGS?
=?-Wall?-O?-g
?
myprog?:?$(OBJS)
?$(CC)?$
^?-o?$@
?
foo.o?:?foo.c?foo.h?bar.h
?$(CC)?$(CFLAGS)?
-c?$<?-o?$@
?
bar.o?:?bar.c?bar.h
?$(CC)?$(CFLAGS)?
-c?$<?-o?$@
===?makefile?結(jié)束?===


?
你可以用變量做許多其它的事情,特別是當(dāng)你把它們和函數(shù)混合 使用的時(shí)候。如果需要更進(jìn)一步的了解,請(qǐng)參考 GNU Make 手冊(cè)。 ('man make', 'man makefile')
?
2.4 隱含規(guī)則 (Implicit Rules)
?
請(qǐng) 注意,在上面的例子里,幾個(gè)產(chǎn)生 .o 文件的命令都是一樣的。 都是從 .c 文件和相關(guān)文件里產(chǎn)生 .o 文件,這是一個(gè)標(biāo)準(zhǔn)的步 驟。其實(shí) make 已經(jīng)知道怎么做——它有一些叫做隱含規(guī)則的內(nèi)置的規(guī)則,這些規(guī)則告訴它當(dāng)你沒有給出某些命令的時(shí)候,應(yīng)該 怎么辦。
?
如果你把 生成 foo.o bar.o 的命令從它們的規(guī)則中刪除, make 將會(huì)查找它的隱含規(guī)則,然后會(huì)找到一個(gè)適當(dāng)?shù)拿睢K拿顣?huì) 使用一些變量,因此你可以按照你的想法來設(shè)定它:它使用變量 CC 做為編譯器(象我們?cè)谇懊娴睦?#xff09;,并且傳遞變量 CFLAGS (給 C 編譯器,C++ 編譯器用 CXXFLAGS ),CPPFLAGS C 預(yù) 處理器旗標(biāo)), TARGET_ARCH (現(xiàn)在不用考慮這個(gè)),然后它加 入旗標(biāo) '-c' ,后面跟變量 $< (第一個(gè)依靠名),然后是旗 標(biāo) '-o' 跟變量 $@ (目的文件名)。一個(gè)C編譯的具體命令將 會(huì)是:
?
$(CC) $(CFLAGS) $(CPPFLAGS) $(TARGET_ARCH) -c $< -o $@
?
當(dāng)然你可以按照你自己的需要來定義這些變量。這就是為什么用 gcc -M -MM 開關(guān)輸出的碼可以直接用在一個(gè) makefile 里。

假象目的 (Phony Targets)
?
設(shè)你的一個(gè)項(xiàng)目最后需要產(chǎn)生兩個(gè)可執(zhí)行文件。你的主要目標(biāo)是產(chǎn)生兩個(gè)可執(zhí)行文件,但這兩個(gè)文件是相互獨(dú)立的——如果一 個(gè)文件需要重建,并不影響另一個(gè)。你可以使用假象目的來達(dá)到這種效果。一個(gè)假象目的跟一個(gè)正常的目的幾乎是一樣的, 只是這個(gè)目的文件是不存在的。因此, make 總是會(huì)假設(shè)它需要被生成,當(dāng)把它的依賴文件更新后,就會(huì)執(zhí)行它的規(guī)則里的命令 行。
?
如果在我們的 makefile 開始處輸入:
?
all : exec1 exec2
?
exec1 exec2 是我們做為目的的兩個(gè)可執(zhí)行文件。 make 把這個(gè) 'all' 做為它的主要目的,每次執(zhí)行時(shí)都會(huì)嘗試把 'all' 更新。但既然這行規(guī)則里沒有哪個(gè)命令來作用在一個(gè)叫 'all' 的實(shí)際文件(事實(shí)上 all 并不會(huì)在磁碟上實(shí)際產(chǎn)生),所以這個(gè)規(guī) 則并不真的改變 'all' 的狀態(tài)。可既然這個(gè)文件并不存在,所以 make 會(huì)嘗試更新 all 規(guī)則,因此就檢查它的依靠 exec1, exec2 是否需要更新,如果需要,就把它們更新,從而達(dá)到我們的目的。
?
假象目的也可以用來描述一組非預(yù)設(shè)的動(dòng)作。例如,你想把所有由 make 產(chǎn)生的文件刪除,你可以在 makefile 里設(shè)立這樣一個(gè)規(guī)則:
?
veryclean :
?rm *.o
?rm myprog
?
前提是沒有其它的規(guī)則依靠這個(gè) 'veryclean' 目的,它將永遠(yuǎn) 不會(huì)被執(zhí)行。但是,如果你明確的使用命令 'make veryclean' make 會(huì)把這個(gè)目的做為它的主要目標(biāo),執(zhí)行那些 rm 命令。
?
果你的磁碟上存在一個(gè)叫 veryclean 文件,會(huì)發(fā)生什么事?這時(shí)因?yàn)樵谶@個(gè)規(guī)則里沒有任何依靠文件,所以這個(gè)目的文件一定是 最新的了(所有的依靠文件都已經(jīng)是最新的了),所以既使用戶明 確命令 make 重新產(chǎn)生它,也不會(huì)有任何事情發(fā)生。解決方法是標(biāo) 明所有的假象目的(用 .PHONY),這就告訴 make 不用檢查它們是否存在于磁碟上,也不用查找任何隱含規(guī)則,直接假設(shè)指定的目 的需要被更新。在 makefile 里加入下面這行包含上面規(guī)則的規(guī)則:
?
.PHONY : veryclean
?
就可以了。注意,這是一個(gè)特殊的 make 規(guī)則,make 知道 .PHONY 是一個(gè)特殊目的,當(dāng)然你可以在它的依靠里加入你想用的任何假象 目的,而 make 知道它們都是假象目的。
?
2.6 函數(shù) (Functions)
?
makefile 里的函數(shù)跟它的變量很相似——使用的時(shí)候,你用一個(gè) $ 符號(hào)跟開括號(hào),函數(shù)名,空格后跟一列由逗號(hào)分隔的參數(shù),最后 用關(guān)括號(hào)結(jié)束。例如,在 GNU Make 里有一個(gè)叫 'wildcard' 的函數(shù),它有一個(gè)參數(shù),功能是展開成一列所有符合由其參數(shù)描述的文 件名,文件間以空格間隔。你可以像下面所示使用這個(gè)命令:
?
SOURCES = $(wildcard *.c)
?
這行會(huì)產(chǎn)生一個(gè)所有以 '.c' 結(jié)尾的文件的列表,然后存入變量 SOURCES 里。當(dāng)然你不需要一定要把結(jié)果存入一個(gè)變量。
?
另一個(gè)有用的函數(shù)是 patsubst patten substitude, 匹配替 換的縮寫)函數(shù)。它需要3個(gè)參數(shù)——第一個(gè)是一個(gè)需要匹配的 式樣,第二個(gè)表示用什么來替換它,第三個(gè)是一個(gè)需要被處理的由空格分隔的字列。例如,處理那個(gè)經(jīng)過上面定義后的變量,
?
OBJS = $(patsubst %.c,%.o,$(SOURCES))
?
行將處理所有在 SOURCES 字列中的字(一列文件名),如果它的 結(jié)尾是 '.c' ,就用 '.o' '.c' 取代。注意這里的 % 符號(hào)將匹 配一個(gè)或多個(gè)字符,而它每次所匹配的字串叫做一個(gè)’(stem) 。在第二個(gè)參數(shù)里, % 被解讀成用第一參數(shù)所匹配的那個(gè)柄。
?
2.7 一個(gè)比較有效的 makefile
?
利用我們現(xiàn)在所學(xué)的,我們可以建立一個(gè)相當(dāng)有效的 makefile 這個(gè) makefile 可以完成大部分我們需要的依靠檢查,不用做太大 的改變就可直接用在大多數(shù)的項(xiàng)目里。
?
首先我們需要一個(gè)基本的 makefile 來建我們的程序。我們可以讓它搜索當(dāng)前目錄,找到源碼文件,并且假設(shè)它們都是屬于我們的項(xiàng) 目的,放進(jìn)一個(gè)叫 SOURCES 的變量。這里如果也包含所有的 *.cc 文件,也許會(huì)更保險(xiǎn),因?yàn)樵创a文件可能是 C++ 碼的。
?
SOURCES = $(wildcard *.c *.cc)
?
利用 patsubst ,我們可以由源碼文件名產(chǎn)生目標(biāo)文件名,我們需 要編譯出這些目標(biāo)文件。如果我們的源碼文件既有 .c 文件,也有 .cc 文件,我們需要使用相嵌的 patsubst 函數(shù)呼叫:
?
OBJS = $(patsubst %.c,%.o,$(patsubst %.cc,%.o,$(SOURCES)))
?
最里面一層 patsubst 的呼叫會(huì)對(duì) .cc 文件進(jìn)行后綴替代,產(chǎn)生的結(jié) 果被外層的 patsubst 呼叫處理,進(jìn)行對(duì) .c 文件后綴的替代。
?
現(xiàn)在我們可以設(shè)立一個(gè)規(guī)則來建可執(zhí)行文件:
?
myprog : $(OBJS)
?gcc -o myprog $(OBJS)
?
進(jìn)一步的規(guī)則不一定需要, gcc 已經(jīng)知道怎么去生成目標(biāo)文件 (object files) 。下面我們可以設(shè)定產(chǎn)生依靠信息的規(guī)則:
?
depends : $(SOURCES)
?gcc -M $(SOURCES) > depends
?
這里如果一個(gè)叫 'depends' 的文件不存在,或任何一個(gè)源碼文件比一個(gè)已存在的 depends 文件新,那么一個(gè) depends 文件會(huì)被生 成。depends 文件將會(huì)含有由 gcc 產(chǎn)生的關(guān)于源碼文件的規(guī)則(注 -M 開關(guān))。現(xiàn)在我們要讓 make 把這些規(guī)則當(dāng)做 makefile 的一部分。這里使用的技巧很像 C 語言中的 #include 系統(tǒng)—— 們要求 make 把這個(gè)文件 include makefile 里,如下:
?
include depends
?
GNU Make 看到這個(gè),檢查 'depends' 目的是否更新了,如果沒有, 它用我們給它的命令重新產(chǎn)生 depends 檔。然后它會(huì)把這組(新) 規(guī)則包含進(jìn)來,繼續(xù)處理最終目標(biāo) 'myprog' 。當(dāng)看到有關(guān) myprog 的規(guī)則,它會(huì)檢查所有的目標(biāo)文件是否更新——利用 depends 文件里的規(guī)則,當(dāng)然這些規(guī)則現(xiàn)在已經(jīng)是更新過的了。
?
這個(gè)系統(tǒng)其實(shí)效率很低,因?yàn)槊慨?dāng)一個(gè)源碼文件被改動(dòng),所有的源碼 文件都要被預(yù)處理以產(chǎn)生一個(gè)新的 'depends' 文件。而且它也不是 100% 的安全,這是因?yàn)楫?dāng)一個(gè) header 檔被改動(dòng),依靠信息并不會(huì) 被更新。但就基本工作來說,它也算相當(dāng)有用的了。

2.8 一個(gè)更好的 makefile
?
這是一個(gè)我為我大多數(shù)項(xiàng)目設(shè)計(jì)的 makefile 。它應(yīng)該可以不需要修改的用在大部分項(xiàng)目里。我主要把它用在 djgpp 上,那是一個(gè) DOS 版的 gcc 編譯器。因此你可以看到執(zhí)行的命令名、 'alleg' 程序包、 RM -F 變量都反映了這一點(diǎn)。
?

===?makefile?開始?===
?
######################################
#
#?Generic?makefile
#
#?by?George?Foot
#?email:?george.foot@merton.ox.ac.uk
#
#?Copyright?(c)?
1997?George?Foot
#?All?rights?reserved.
#?保留所有版權(quán)
#
#?No?warranty,?no?liability;
#?you?use?
this?at?your?own?risk.
#?沒保險(xiǎn),不負(fù)責(zé)
#?你要用這個(gè),你自己擔(dān)風(fēng)險(xiǎn)
#
#?You?are?free?to?modify?and
#?distribute?
this?without?giving
#?credit?to?the?original?author.
#?你可以隨便更改和散發(fā)這個(gè)文件
#?而不需要給原作者什么榮譽(yù)。
#?(你好意思?)
#
######################################
?
###?Customising
#?用戶設(shè)定
#
#?Adjust?the?following?
if?necessary;?EXECUTABLE?is?the?target
#?executable
's?filename,?and?LIBS?is?a?list?of?libraries?to?link?in
#?(e.g.?alleg,?stdcx,?iostr,?etc).?You?can?override?these?on?make's
#?command?line?of?course,?if?you?prefer?to?do?it?that?way.
#
#?如果需要,調(diào)整下面的東西。?EXECUTABLE?是目標(biāo)的可執(zhí)行文件名,?LIBS
#?是一個(gè)需要連接的程序包列表(例如?alleg,?stdcx,?iostr?等等)。當(dāng)然你
#?可以在?make?的命令行覆蓋它們,你愿意就沒問題。
#
?
EXECUTABLE?:
=?mushroom.exe
LIBS?:
=?alleg
?
#?Now?alter?any?
implicit?rules'?variables?if?you?like,?e.g.:
#
#?現(xiàn)在來改變?nèi)魏文阆敫膭?dòng)的隱含規(guī)則中的變量,例如
?
CFLAGS?:
=?-g?-Wall?-O3?-m486
CXXFLAGS?:
=?$(CFLAGS)
?
#?The?next?bit?checks?to?see?whether?rm?
is?in?your?djgpp?bin
#?directory;?
if?not?it?uses?del?instead,?but?this?can?cause?(harmless)
#?`File?not?found
'?error?messages.?If?you?are?not?using?DOS?at?all,
#?set?the?variable?to?something?which?will?unquestioningly?remove
#?files.
#
#?下面先檢查你的?djgpp?命令目錄下有沒有?rm?命令,如果沒有,我們使用
#?del?命令來代替,但有可能給我們?
'File?not?found'?這個(gè)錯(cuò)誤信息,這沒
#?什么大礙。如果你不是用?DOS?,把它設(shè)定成一個(gè)刪文件而不廢話的命令。
#?(其實(shí)這一步在?UNIX?類的系統(tǒng)上是多余的,只是方便?DOS?用戶。?UNIX
#?用戶可以刪除這5行命令。)
?
ifneq?($(wildcard?$(DJDIR)
/bin/rm.exe),)
RM
-F?:=?rm?-f
else
RM
-F?:=?del
endif
?
#?You?shouldn
't?need?to?change?anything?below?this?point.
#
#?從這里開始,你應(yīng)該不需要改動(dòng)任何東西。(我是不太相信,太NB了!)
?
SOURCE?:
=?$(wildcard?*.c)?$(wildcard?*.cc)
OBJS?:
=?$(patsubst?%.c,%.o,$(patsubst?%.cc,%.o,$(SOURCE)))
DEPS?:
=?$(patsubst?%.o,%.d,$(OBJS))
MISSING_DEPS?:
=?$(filter-out?$(wildcard?$(DEPS)),$(DEPS))
MISSING_DEPS_SOURCES?:
=?$(wildcard?$(patsubst?%.d,%.c,$(MISSING_DEPS))?\
$(patsubst?
%.d,%.cc,$(MISSING_DEPS)))
CPPFLAGS?
+=?-MD
?
.PHONY?:?everything?deps?objs?clean?veryclean?rebuild
?
everything?:?$(EXECUTABLE)
?
deps?:?$(DEPS)
?
objs?:?$(OBJS)
?
clean?:
?@$(RM
-F)?*.o
?@$(RM
-F)?*.d
?
veryclean:?clean
?@$(RM
-F)?$(EXECUTABLE)
?
rebuild:?veryclean?everything
?
ifneq?($(MISSING_DEPS),)
$(MISSING_DEPS)?:
?@$(RM
-F)?$(patsubst?%.d,%.o,$@)
endif
?
-include?$(DEPS)
?
$(EXECUTABLE)?:?$(OBJS)
?gcc?
-o?$(EXECUTABLE)?$(OBJS)?$(addprefix?-l,$(LIBS))
?
===?makefile?結(jié)束?===


?
有幾個(gè)地方值得解釋一下的。首先,我在定義大部分變量的時(shí)候使 用的是 := 而不是 = 符號(hào)。它的作用是立即把定義中參考到的函 數(shù)和變量都展開了。如果使用 = 的話,函數(shù)和變量參考會(huì)留在那 兒,就是說改變一個(gè)變量的值會(huì)導(dǎo)致其它變量的值也被改變。例 如:
?
A = foo
B = $(A)
# 現(xiàn)在 B $(A) ,而 $(A) 'foo'
A = bar
# 現(xiàn)在 B 仍然是 $(A) ,但它的值已隨著變成 'bar' 了。
B := $(A)
# 現(xiàn)在 B 的值是 'bar'
A = foo
# B 的值仍然是 'bar'
?
make 會(huì)忽略在 # 符號(hào)后面直到那一行結(jié)束的所有文字。
?
ifneg...else...endif 系統(tǒng)是 makefile 里讓某一部分碼有條件的 失效/有效的工具。 ifeq 使用兩個(gè)參數(shù),如果它們相同,它把直 else (或者 endif ,如果沒有 else 的話)的一段碼加進(jìn) makefile 里;如果不同,把 else endif 間的一段碼加入 makefile (如果有 else )。 ifneq 的用法剛好相反。
?
'filter-out' 函數(shù)使用兩個(gè)用空格分開的列表,它把第二列表中所 有的存在于第一列表中的項(xiàng)目刪除。我用它來處理 DEPS 列表,把所 有已經(jīng)存在的項(xiàng)目都刪除,而只保留缺少的那些。
?
前面說過, CPPFLAGS 存有用于隱含規(guī)則中傳給預(yù)處理器的一些 旗標(biāo)。而 -MD 開關(guān)類似 -M 開關(guān),但是從源碼文件 .c .cc 形成的文件名是使用后綴 .d 的(這就解釋了我形成 DEPS 變量的步驟)。DEPS 里提到的文件后來用 '-include' 加進(jìn)了 makefile 里,它隱藏了所有因文件不存在而產(chǎn)生的錯(cuò)誤信息。
?
如果任何依靠文件不存在, makefile 會(huì)把相應(yīng)的 .o 文件從磁碟 上刪除,從而使得 make 重建它。因?yàn)?/span> CPPFLAGS 指定了 -MD 它的 .d 文件也被重新產(chǎn)生。
?
最后, 'addprefix' 函數(shù)把第二個(gè)參數(shù)列表的每一項(xiàng)前綴上第一 個(gè)參數(shù)值。
?
這個(gè) makefile 的那些目的是(這些目的可以傳給 make 的命令行 來直接選用):
?
everything:(預(yù)設(shè)) 更新主要的可執(zhí)行程序,并且為每一個(gè) 源碼文件生成或更新一個(gè) '.d' 文件和一個(gè) '.o' 文件。
?
deps: 只是為每一個(gè)源碼程序產(chǎn)生或更新一個(gè) '.d' 文件。
?
objs: 為每一個(gè)源碼程序生成或更新 '.d' 文件和目標(biāo)文件。
?
clean: 刪除所有中介/依靠文件( *.d *.o )。
?
veryclean: `clean' 和刪除可執(zhí)行文件。
?
rebuild: 先做 `veryclean' 然后 `everything' ;既完全重建。
?
除了預(yù)設(shè)的 everything 以外,這里頭只有 clean veryclean rebuild 對(duì)用戶是有意義的。
?
還沒有發(fā)現(xiàn)當(dāng)給出一個(gè)源碼文件的目錄,這個(gè) makefile 會(huì)失敗的情況,除非依靠文件被弄亂。如果這種弄亂的情況發(fā)生了,只要輸入 `make clean' ,所有的目標(biāo)文件和依靠文件會(huì)被刪除,問題就應(yīng)該被解決了。當(dāng)然,最好不要把它們弄亂。如果你發(fā)現(xiàn)在某種情況下這 個(gè) makefile 文件不能完成它的工作,請(qǐng)告訴我,我會(huì)把它整好的。
?

3 總結(jié)
~~~~~~~~~~~~~~~
?
我希望這篇文章足夠詳細(xì)的解釋了多文件項(xiàng)目是怎么運(yùn)作的,也說明了 怎樣安全而合理的使用它。到此,你應(yīng)該可以輕松的利用 GNU Make 具來管理小型的項(xiàng)目,如果你完全理解了后面幾個(gè)部分的話,這些對(duì)于 你來說應(yīng)該沒什么困難。

4 轉(zhuǎn)自:http://oss.org.cn/ossdocs/gnu/linux/gmake.html

轉(zhuǎn)載于:https://www.cnblogs.com/itech/archive/2009/09/15/1567001.html

總結(jié)

以上是生活随笔為你收集整理的GUN Make指南的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。