Makefile學(xué)習(xí)筆記

Makefile學(xué)習(xí)筆記

概述


什么是makefile?或許很多Windows程序員都不知道這個(gè)東西,因?yàn)槟切¦indows端IDE都為你做了這個(gè)工作,但我覺得要做一個(gè)professional的程序員,makefile還是要懂。這就好像現(xiàn)在有這么多的HTML的編輯器澳腹,但如果你想成為一個(gè)專業(yè)人士,你還是要了解HTML的能力杨何。特別在Unix下的軟件編譯酱塔,你就不能不自己寫makefile,會(huì)不會(huì)寫makefile危虱,從一個(gè)側(cè)面說明了一個(gè)程序員是否具備完成大型工程的能力羊娃。

因?yàn)閙akefile關(guān)系到整個(gè)工程的編譯規(guī)則。一個(gè)工程中的源文件不計(jì)其數(shù)埃跷,其按類型蕊玷、功能、模塊分別放在若干個(gè)目錄中弥雹,makefile定義了一系列的規(guī)則來指定垃帅,哪些文件需要先編譯,哪些文件需要重新編譯剪勿,甚至于進(jìn)行更復(fù)雜的功能操作贸诚,因?yàn)閙akefile就像一個(gè)shell腳本一樣,其中也可以執(zhí)行操作系統(tǒng)的命令窗宦。

makefile帶來的好處就是“自動(dòng)化編譯”赦颇,一旦寫好,只需要一個(gè)make命令赴涵,整個(gè)工程完全自動(dòng)編譯,極大的提高了軟件開發(fā)的效率订讼。make是一個(gè)命令工具髓窜,是一個(gè)解釋makefile中指令的命令工具,一般來說,大多數(shù)的IDE都有這個(gè)命令寄纵,比如:Delphi的make鳖敷,Visual C++的nmake,Linux下GNU 的make程拭《猓可見,makefile都成為了一種在工程方面的編譯方法恃鞋。

不同廠商的make各不相同崖媚,也有不同的語法,但是本質(zhì)都是在文件依賴性上做文章恤浪,這里僅對(duì)GNU的make進(jìn)行講述畅哑,版本make3.80.該make是應(yīng)用最為廣泛的,也是用的最多的水由,而且還是最遵循與IEEE 1003.2-1992標(biāo)準(zhǔn)的(POSIX2)荠呐。

這篇文檔中,以C/C++源碼作為講述基礎(chǔ)砂客,其中必然涉及一些關(guān)于C/C++編譯的知識(shí)泥张,相關(guān)內(nèi)容可查閱相關(guān)編譯器文檔獲得,這里默認(rèn)為gcc和g++鞠值。

關(guān)于程序的編譯和鏈接


一般來說媚创,無論是C、C++齿诉,首先要把源文件編譯成中間代碼文件筝野,Windows下.obj或Unix下.o,即Object File粤剧,這個(gè)動(dòng)作叫做編譯(compile)歇竟。然后再把大量的Object File合成執(zhí)行文件,這個(gè)動(dòng)作叫做鏈接(link)抵恋。

編譯時(shí)焕议,編譯器需要的是語法的正確,函數(shù)與變量聲明的正確弧关。對(duì)于后者盅安,通常是你需要告訴編譯器頭文件的所在位置(頭文件中應(yīng)該只是聲明,而定義應(yīng)該放在C/C++文件中)世囊,只要所有語法正確别瞭,編譯器就可以編譯出中間目標(biāo)文件。一般來說株憾,每個(gè)源文件都應(yīng)該對(duì)應(yīng)于中間目標(biāo)文件蝙寨。

鏈接時(shí)晒衩,主要是鏈接函數(shù)和全局變量,所以墙歪,我們可以使用這些中間目標(biāo)文件來鏈接我們的應(yīng)用程序听系。連接器并不管函數(shù)所在的源文件,只管函數(shù)的中間目標(biāo)文件虹菲,在大多數(shù)時(shí)候靠胜,由于源文件太多,編譯生成的中間目標(biāo)文件太多毕源,而在鏈接時(shí)需要明確的指出中間目標(biāo)文件名浪漠,這對(duì)于編譯很不方便,所以我們要給中間目標(biāo)文件打個(gè)包脑豹,在Windows下這種包叫庫文件(Library File, * .lib)郑藏,在Unix下是Archive File,* .a瘩欺。

總結(jié)一下必盖,源文件首先會(huì)生成中間目標(biāo)文件,再由中間目標(biāo)文件生成執(zhí)行文件俱饿。在編譯時(shí)歌粥,編譯器只檢測(cè)程序語法,和函數(shù)拍埠、變量是否被聲明失驶。如果函數(shù)未被聲明,編譯器會(huì)給出一個(gè)警告枣购,但可以生成Object File嬉探。而在鏈接程序時(shí),鏈接器會(huì)在所有的Object File中找尋函數(shù)的實(shí)現(xiàn)棉圈。如果找不到涩堤,那就會(huì)報(bào)鏈接錯(cuò)誤碼(Linker Error),在VC下分瘾,這種錯(cuò)誤一般是:Link2001胎围,意思是,鏈接器未能找到函數(shù)實(shí)現(xiàn)德召,你需要指定函數(shù)的Object File白魂。

Makefile介紹


make命令執(zhí)行時(shí),需要一個(gè)Makefile文件上岗,以告訴make命令需要怎樣去編譯和鏈接程序福荸。

首先,我們用一個(gè)示例來說明Makefile的書寫規(guī)則肴掷。以便給大家一個(gè)感性認(rèn)識(shí)逞姿。這個(gè)示例來源于GNU的make使用手冊(cè)辞嗡,在這個(gè)示例中捆等,我們的工程有8個(gè)C文件滞造,和3個(gè)頭文件,我們要寫一個(gè)Makefile來告訴make命令如何編譯和鏈接這幾個(gè)文件栋烤。

我們的規(guī)則是:

  1. 如果這個(gè)工程沒有編譯過谒养,那么我們的所有C文件都要編譯并被鏈接;
  2. 如果這個(gè)工程的某幾個(gè)C文件被修改明郭,那么我們只編譯被修改的C文件买窟;
  3. 如果這個(gè)工程的頭文件被改變了,那么我們需要編譯引用了這幾個(gè)頭文件的C文件薯定,并鏈接目標(biāo)程序始绍。

只要我們的Makefile寫的夠好,所有的這一切话侄,我們只用一個(gè)make命令就可以完成亏推,make命令會(huì)自動(dòng)地根據(jù)當(dāng)前的文件修改的情況來確定哪些文件需要重編譯,從而自己編譯所需要的文件和鏈接目標(biāo)程序年堆。

一吞杭、Makefile的規(guī)則

target ... : prerequisites ...
command
...

target是一個(gè)目標(biāo)文件,可以是Object File变丧,也可以是執(zhí)行文件芽狗,還可以是一個(gè)標(biāo)簽(Label)。對(duì)于標(biāo)簽這種特性痒蓬,在后續(xù)的偽目錄章節(jié)中會(huì)有敘述童擎。

prequisites是生成target所需要的文件。

command是make需要執(zhí)行的命令(任意的Shell命令)攻晒。

這是一個(gè)文件的依賴關(guān)系顾复,也就是說,target中的一個(gè)或多個(gè)目標(biāo)文件依賴于prerequisites中的文件炎辨,其生成規(guī)則定義在command中捕透。因此,prerequisites中如果有一個(gè)及以上的文件比target要新的話碴萧,command中定義的命令就會(huì)被執(zhí)行乙嘀。這就是Makefile的最核心規(guī)則。

二破喻、一個(gè)示例

正如前面所說的虎谢,如果一個(gè)工程有3個(gè)頭文件,和8個(gè)C文件曹质,我們?yōu)榱送瓿汕懊嫠龅哪侨齻€(gè)規(guī)則婴噩,我們的Makefile應(yīng)該是下面的這個(gè)樣子的擎场。

edit : main.o kbd.o command.o display.o\
insert.o search.o files.o utils.o
cc -o edit main.o kbd.o command.o display.o\
insert.o search.o utils.o

main.o : main.c defs.h
cc -c main.c
kbd.o : kbd.c defs.h command.h
cc -c kbd.c
command.o : command.c defs.h command.h
cc -c command.c
display.o : display.c defs.h buffer.h
cc -c display.c
insert.o : insert.c defs.h buffer.h
cc -c insert.c
search.o : search.c defs.h buffer.h
cc -c search.c
files.o : files.c defs.h buffer.h command.h
cc -c files.c
utils.o : utils.c defs.h
cc -c utils.c 

clean : 
rm edit main.o kbd.o command.o display.o\
insert.o search.o files.o utils.o

反斜杠(\)是換行符的意思。這樣可以使Makefile易讀几莽。

把這個(gè)內(nèi)容保存在文件名為Makefilemakefile的文件中迅办,然后在該目錄下,直接輸入命令make命令就可以生成執(zhí)行文件edit章蚣。如果要?jiǎng)h除執(zhí)行文件和所有的中間目標(biāo)文件站欺,那么只要簡(jiǎn)單地執(zhí)行一下make clean就可以了。

在這個(gè)makefile中纤垂,目標(biāo)文件(target)包含:執(zhí)行文件edit和中間目標(biāo)文件* .o矾策,依賴文件(prerequisites)就是冒號(hào)后面的那些 .c和 .h文件。每一個(gè) .o文件都有一組依賴文件峭沦,而這些 .o文件又是執(zhí)行文件edit的依賴文件贾虽。依賴關(guān)系實(shí)質(zhì)上就是說明了目標(biāo)文件是由哪些文件生成的,換言之吼鱼,目標(biāo)文件是被哪些文件更新的蓬豁。

在定義好依賴依賴關(guān)系后,后續(xù)的那一行定義了如何生成文件的操作系統(tǒng)命令蛉抓,一定要以一個(gè)TAB鍵開頭庆尘。make并不管命令是怎么工作的,他只管執(zhí)行所定義的命令巷送。make會(huì)比較targets文件和prereuisites文件的修改日期驶忌,如果prerequisites文件的日期要比targets文件的日期要新,或者target不存在的話笑跛,make就會(huì)執(zhí)行后續(xù)指令付魔。

clean不是一個(gè)文件,而只是一個(gè)動(dòng)作名飞蹂。其冒號(hào)后什么也沒有几苍,make就不會(huì)自動(dòng)去找文件依賴性,也就不會(huì)自動(dòng)執(zhí)行其后所定義的命令陈哑。要執(zhí)行其后的命令妻坝,就要在make命令后明顯的指出這個(gè)label的名字。這樣的方法非常有用惊窖,使我們可以在一個(gè)makefile中定義不用的編譯或是和編譯無關(guān)的命令刽宪,比如程序打包和程序的備份等等。

三界酒、make是如何工作的

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末圣拄,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子毁欣,更是在濱河造成了極大的恐慌庇谆,老刑警劉巖岳掐,帶你破解...
    沈念sama閱讀 210,978評(píng)論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異饭耳,居然都是意外死亡串述,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 89,954評(píng)論 2 384
  • 文/潘曉璐 我一進(jìn)店門哥攘,熙熙樓的掌柜王于貴愁眉苦臉地迎上來剖煌,“玉大人,你說我怎么就攤上這事逝淹。” “怎么了桶唐?”我有些...
    開封第一講書人閱讀 156,623評(píng)論 0 345
  • 文/不壞的土叔 我叫張陵栅葡,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我尤泽,道長(zhǎng)欣簇,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,324評(píng)論 1 282
  • 正文 為了忘掉前任坯约,我火速辦了婚禮熊咽,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘闹丐。我一直安慰自己横殴,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,390評(píng)論 5 384
  • 文/花漫 我一把揭開白布卿拴。 她就那樣靜靜地躺著衫仑,像睡著了一般。 火紅的嫁衣襯著肌膚如雪堕花。 梳的紋絲不亂的頭發(fā)上文狱,一...
    開封第一講書人閱讀 49,741評(píng)論 1 289
  • 那天,我揣著相機(jī)與錄音缘挽,去河邊找鬼瞄崇。 笑死,一個(gè)胖子當(dāng)著我的面吹牛壕曼,可吹牛的內(nèi)容都是我干的苏研。 我是一名探鬼主播,決...
    沈念sama閱讀 38,892評(píng)論 3 405
  • 文/蒼蘭香墨 我猛地睜開眼窝稿,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼楣富!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起伴榔,我...
    開封第一講書人閱讀 37,655評(píng)論 0 266
  • 序言:老撾萬榮一對(duì)情侶失蹤纹蝴,失蹤者是張志新(化名)和其女友劉穎庄萎,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體塘安,經(jīng)...
    沈念sama閱讀 44,104評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡糠涛,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,451評(píng)論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了兼犯。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片忍捡。...
    茶點(diǎn)故事閱讀 38,569評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖切黔,靈堂內(nèi)的尸體忽然破棺而出砸脊,到底是詐尸還是另有隱情,我是刑警寧澤纬霞,帶...
    沈念sama閱讀 34,254評(píng)論 4 328
  • 正文 年R本政府宣布凌埂,位于F島的核電站,受9級(jí)特大地震影響诗芜,放射性物質(zhì)發(fā)生泄漏瞳抓。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,834評(píng)論 3 312
  • 文/蒙蒙 一伏恐、第九天 我趴在偏房一處隱蔽的房頂上張望孩哑。 院中可真熱鬧,春花似錦翠桦、人聲如沸横蜒。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,725評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽愁铺。三九已至,卻和暖如春闻鉴,著一層夾襖步出監(jiān)牢的瞬間茵乱,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,950評(píng)論 1 264
  • 我被黑心中介騙來泰國打工孟岛, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留瓶竭,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 46,260評(píng)論 2 360
  • 正文 我出身青樓渠羞,卻偏偏與公主長(zhǎng)得像斤贰,于是被迫代替她去往敵國和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子次询,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,446評(píng)論 2 348

推薦閱讀更多精彩內(nèi)容

  • 來自陳浩的一片老文荧恍,但絕對(duì)營(yíng)養(yǎng)。 示例工程:3 個(gè)頭文件*.h,和 8 個(gè) C 文件*.c送巡。 初 編譯過程摹菠,源文件...
    周筱魯閱讀 4,688評(píng)論 0 17
  • 1. 概述 1.1 前言 之前在Linux下寫C/C++都是直接輸命令行,雖然有使用make的經(jīng)歷骗爆,但沒有自己動(dòng)手...
    kophy閱讀 3,865評(píng)論 0 19
  • 本文章介紹了makefile跟kconfig文件次氨,包括編譯過程與makefile編碼規(guī)則。 編譯過程:我們?cè)谶M(jìn)行l(wèi)...
    超低空閱讀 17,424評(píng)論 0 5
  • makefile關(guān)系到整個(gè)工程的編譯規(guī)則摘投,一個(gè)工程中的源文件不計(jì)其數(shù)煮寡,按其類型、功能犀呼、模塊分別放在若干的目錄當(dāng)中幸撕,...
    Joe_HUST閱讀 1,876評(píng)論 0 3
  • 最近兩天花時(shí)間讀了一下陳皓老師的《跟我一起寫Makefile》,這篇文章非常地詳細(xì)地介紹了make的用法以及Mak...
    David栗子閱讀 3,400評(píng)論 0 3