今天寫C語(yǔ)言的時(shí)候,我突然遇到需要做一個(gè)項(xiàng)目.以前沒有接觸過(guò),通過(guò)簡(jiǎn)單的了解,Windows下可以通過(guò)IDE來(lái)進(jìn)行共同編譯 vs就是很好的選擇.
而我們今天討論的重點(diǎn)是如何在Linux中進(jìn)行多文件編譯,一般簡(jiǎn)單的項(xiàng)目會(huì)有三個(gè)文件 (xxx.c ,xxx.c,xxx.h)其中一個(gè)執(zhí)行程序主要功能,一個(gè)描述抽象數(shù)據(jù)類型的函數(shù),一個(gè)進(jìn)行函數(shù)原型的聲明,在Linux下,大家都是手動(dòng)達(dá)人,我們?cè)诰幾g的時(shí)候是需要把怎么編譯都寫出來(lái),比如編譯順序,那個(gè)文件和那個(gè)文件進(jìn)行鏈接,那些文件在什么情況下需要重新編譯等等,或者一些更加復(fù)雜的操作,用來(lái)寫這些具體操作的文件就是這個(gè)項(xiàng)目的makefile.
而且,我們?cè)趯懞昧艘粋€(gè)makefile之后就可以自動(dòng)編譯了,只需用一個(gè)make命令就行.而且更加建議先學(xué)了makefile之后用IDE,因?yàn)閷W(xué)習(xí)了mmakefile之后你就對(duì)其中怎樣把編程語(yǔ)言變成可執(zhí)行程序有了更加深刻的理解,基礎(chǔ)更加扎實(shí).好了,接下來(lái)我們就來(lái)一起看看怎么寫Makefile,
我是以c語(yǔ)言作為源碼,編譯器是Ubuntu 下默認(rèn)的gcc.
首先我們來(lái)聊聊有關(guān)程序的編譯和鏈接 無(wú)論是 C场刑、 C++伊履、還是 pas巴刻,首先要把源文件編譯成中間代碼文件,在 Windows 下也就是 .obj 文件,UNIX 下是 .o 文件,即 Object File,這個(gè)動(dòng)作叫做編譯( compile)世吨。然后再把大量的 Object File合成執(zhí)行文件,這個(gè)動(dòng)作叫做鏈接( link),windows下大部分的IDE都將這兩個(gè)動(dòng)作結(jié)合成一個(gè)并且集合到一個(gè)快捷鍵上,這樣對(duì)初學(xué)者友好但是對(duì)于深刻理解缺有點(diǎn)缺陷呻征。
Makefile就是一個(gè)怎樣編譯多文件的腳本,我們寫好之后在終端下輸入make 這個(gè)命令就可以開始編譯了.
target ... : prerequisites ... command ... ...
形如這樣的就是一個(gè)Makefile,其中 target 也就是一個(gè)目標(biāo)文件耘婚,可以是 Object File,也可以是執(zhí)行文件陆赋。還可以是一個(gè)標(biāo)簽( Label)沐祷。prerequisites 就是,要生成那個(gè) target 所需要的文件或是目標(biāo)攒岛。command 也就是 make 需要執(zhí)行的命令赖临。(任意的 Shell 命令)
這 是 一 個(gè) 文 件 的 依 賴 關(guān) 系 , 也 就 是 說(shuō) 灾锯, target 這 一 個(gè) 或 多 個(gè) 的 目 標(biāo) 文 件 依 賴 于prerequisites 中 的 文 件 兢榨, 其 生 成 規(guī) 則 定 義 在 command 中 。 說(shuō) 白 一 點(diǎn) 就 是 說(shuō) ,prerequisites 中如果有一個(gè)以上的文件比 target 文件要新的話吵聪, command 所定義的命令就會(huì)被執(zhí)行凌那。這就是 Makefile 的規(guī)則。
好了,我說(shuō)完了,Makefile的核心內(nèi)容就是這樣了,
這就是一個(gè)實(shí)例,其中film 就是編譯之后要生成的文件,它依賴的就是后面的film4.c ,list.c和list.h這三個(gè)文件.
make 的具體工作方式是這樣,當(dāng)你在默認(rèn)界面或者是終端中輸入了make命令之后,
make 會(huì)在當(dāng)前目錄下找名字叫“ Makefile”或“ makefile”的文件
如果找到吟逝,它會(huì)找文件中的第一個(gè)目標(biāo)文件( target)帽蝶,在上面的例子中,他會(huì)找到“ film”這個(gè)文件块攒,并把這個(gè)文件作為最終的目標(biāo)文件励稳。
如果 film 文件不存在,或是 film 所依賴的后面的文件的文件修改時(shí)間要比f(wàn)ilm這個(gè)文件新囱井,那么驹尼,他就會(huì)執(zhí)行后面所定義的命令來(lái)生成 film這個(gè)文件。
好了,這樣就通過(guò)編譯器生成了film 這個(gè)文件.
Makefile中還可以使用變量,讓我們看這樣一個(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 files.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
我們可以看到[.o]文件的字符串被重復(fù)了兩次琅绅,如果我們的工程需要加入一個(gè)新的[.o]文
件扶欣,那么我們需要在兩個(gè)地方加,但如果 makefile 變得復(fù)雜鹅巍,那么我們就有可能會(huì)忘掉一個(gè)需要加入的地方千扶,而導(dǎo)致編譯失敗所以,為了 makefile 的易維護(hù)骆捧,在 makefile 中我們可以使用變量澎羞。 makefile 的變量也就是一個(gè)字符串,理解成 C語(yǔ)言中的宏可能會(huì)更好敛苇。比如妆绞,我們聲明一個(gè)變量,叫 objects, OBJECTS, objs, OBJS, obj, 或是 OBJ枫攀,反
正不管什么啦括饶,只要能夠表示 obj 文件就行了。我們?cè)?makefile 一開始就這樣定義:
objects = main.o kbd.o command.o display.o \ insert.o search.o files.o utils.o
于是来涨,我們就可以很方便地在我們的 makefile 中以“ $(objects)”的方式來(lái)使用這個(gè)變
量了图焰,于是我們的改良版 makefile 就變成下面這個(gè)樣子:
objects = main.o kbd.o command.o display.o \ insert.o search.o files.o utils.o edit : $(objects) cc -o edit $(objects) 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 $(objects)
如果有新的.o文件加入,我們只用在開始的變量聲明中修改就可以了.
最后我告訴大家一下Makefile的書寫規(guī)則
它的語(yǔ)法就是下面這個(gè)樣子
targets : prerequisites command ...
或是這樣:
targets : prerequisites ; command command ...
targets 是文件名,以空格分開蹦掐,可以使用通配符技羔。一般來(lái)說(shuō),我們的目標(biāo)基本上是一個(gè)文件卧抗,但也有可能是多個(gè)文件藤滥。command 是命令行,如果其不與“ target:prerequisites”在一行社裆,那么拙绊,必須以[Tab鍵]開頭,如果和 prerequisites 在一行,那么可以用分號(hào)做為分隔标沪。(見上)prerequisites 也就是目標(biāo)所依賴的文件(或依賴目標(biāo))张漂。如果其中的某個(gè)文件要比目標(biāo)文件要新,那么谨娜,目標(biāo)就被認(rèn)為是“過(guò)時(shí)的”航攒,被認(rèn)為是需要重生成的。這個(gè)在前面已經(jīng)講過(guò)了趴梢。如果命令太長(zhǎng)漠畜,你可以使用反斜框(‘ \’)作為換行符。 make 對(duì)一行上有多少個(gè)字符沒有限制坞靶。規(guī)則告訴 make 兩件事憔狞,文件的依賴關(guān)系和如何成成目標(biāo)文件。
一般來(lái)說(shuō)彰阴, make 會(huì)以 UNIX 的標(biāo)準(zhǔn) Shell瘾敢,也就是/bin/sh 來(lái)執(zhí)行命令。
好了,簡(jiǎn)單的Makefile的就到這,看過(guò)這個(gè)之后大家就學(xué)會(huì)在linux下進(jìn)行件簡(jiǎn)單的工程的編譯,如果想要對(duì)于Makefile進(jìn)行系統(tǒng)的學(xué)習(xí)可以去參考一下相關(guān)的書籍.