最美情侣中文字幕电影,在线麻豆精品传媒,在线网站高清黄,久久黄色视频

歡迎光臨散文網(wǎng) 會員登陸 & 注冊

一文手把手教你寫一個 Makefile 文件

2023-02-11 15:20 作者:補給站Linux內(nèi)核  | 我要投稿

如果我們是在Linux下開發(fā),那Makefile肯定要知道,不懂Makefile,面對較大的工程項目的時候就會比較麻煩,懂得利用開發(fā)工具將會大大提高我們的開發(fā)效率,也可以說Makefile是必須掌握的一項技能。

?

一、了解什么是 Makefile

一個大型工程中的源文件不計其數(shù),各個功能或者模塊分別放在不同的目錄下,手動敲命令去編譯就帶來很大的麻煩,那么Makefile可以定義一系列的編譯規(guī)則,哪些文件需要先編譯,哪些文件需要后編譯,哪些文件需要重新編譯,甚至進行更復(fù)雜的功能操作,Makefile帶來的好處就是——“自動化編譯”,一旦寫好,只需要一個make命令,整個工程完全自動編譯,極大的提高軟件開發(fā)的效率。


make?是一個命令工具,是一個解釋Makefile中指令的命令工具,一般來說,大多數(shù)的IDE都有這個命令,比如:Linux下GNU的make、Visual C++的nmake、Delphi的make??梢?,Makefile都成為了一種在工程方面的編譯方法。當(dāng)然,不同產(chǎn)商的make各不相同,也有不同的語法,但其本質(zhì)都是在 “文件依賴性” 上做文章。

?

二、明白編譯鏈接過程

在編寫Makefile之前,還是要先了解清楚程序編譯鏈接過程,無論是c、c++,首先要把源文件編譯成中間代碼文件,在Windows下也就是 .obj 文件,Unix/Linux下是 .o 文件,即 Object File,這個動作叫做編譯(compile)。然后再把大量的Object File合成執(zhí)行文件,這個動作叫作鏈接(link)。


編譯時,編譯器需要的是語法的正確,函數(shù)與變量的聲明的正確。對于后者,通常是你需要告訴編譯器頭文件的所在位置(頭文件中應(yīng)該只是聲明,而定義應(yīng)該放在C/C++文件中),只要所有的語法正確,編譯器就可以編譯出中間目標文件。一般來說,每個源文件都應(yīng)該對應(yīng)于一個中間目標文件(O文件或是OBJ文件)。


鏈接時,主要是鏈接函數(shù)和全局變量,所以,我們可以使用這些中間目標文件(O文件或是OBJ文件)來鏈接我們的應(yīng)用程序。鏈接器并不管函數(shù)所在的源文件,只管函數(shù)的中間目標文件(Object File),在大多數(shù)時候,由于源文件太多,編譯生成的中間目標文件太多,而在鏈接時需要明顯地指出中間目標文件名,這對于編譯很不方便,所以,我們要給中間目標文件打個包,在Windows下這種包叫“庫文件”(Library File),也就是 .lib 文件,在Unix/Linux下是Archive File,也就是 .a 文件,也叫靜態(tài)庫文件。


總結(jié)一下,編譯鏈接的過程如下:

  1. 源文件首先會生成中間目標文件,再由中間目標文件生成執(zhí)行文件。

  2. 在編譯時,編譯器只檢測程序語法,和函數(shù)、變量是否被聲明。如果函數(shù)未被聲明,編譯器會給出一個警告,但可以生成Object File。

  3. 在鏈接程序時,鏈接器會在所有的Object File中找尋函數(shù)的實現(xiàn),如果找不到,那就會報鏈接錯誤碼(Linker Error),在VC下,這種錯誤一般是:Link 2001錯誤,意思是說,鏈接器未能找到函數(shù)的實現(xiàn)。你需要指定函數(shù)的Object File。

?【文章福利】小編推薦自己的Linux內(nèi)核技術(shù)交流群:【749907784】整理了一些個人覺得比較好的學(xué)習(xí)書籍、視頻資料共享在群文件里面,有需要的可以自行添加哦!?。。ê曨l教程、電子書、實戰(zhàn)項目及代碼)? ? ?

三、編寫一個簡單的 Makefile

1. Makefile?的基本語法規(guī)則:

  • 目標(target):就是一個目標文件,可以是Object 文件,也可以是執(zhí)行文件,還可以是一個標簽(Label);

  • 依賴(prerequisites):就是要生成那個target所需要的文件或是目標;

  • 命令(command):Shell命令,也就是make工具需要執(zhí)行的命令。

總結(jié)】:通過依賴(prerequisites)中的一些文件生成目標(target)文件,目標文件要按照命令(command)中定義的規(guī)則來生成。

2.?來看一個簡單的示例代碼

簡單寫三個方法文件(openFile.c、readFile.c、writeFile.c)、一個頭文件(operateFile.h)和一個主函數(shù)文件(main.c),代碼如下:

3. 根據(jù)上面的語法規(guī)則及編譯鏈接過程編寫一個Makefile文件

注意:Makefile的注釋符號是 ‘#’。


4. 編寫完成后,執(zhí)行make命令,make會在當(dāng)前目錄下找到名字為Makefile或makefile的文件,程序就會自動運行,產(chǎn)生相應(yīng)的中間文件和可執(zhí)行文件


a. 如果執(zhí)行make出現(xiàn)如下信息,那就是命令行(makefile中的gcc或者rm)前面沒有用tab鍵縮進,不能用空格:


b. 如果執(zhí)行make出現(xiàn)如下信息,那就是你的代碼沒有修改過,Makefile拒絕你的請求:


這里還會有一種情況就是如果只修改過其中一個文件,那么重新編譯就可以看到只編譯修改的那個文件,沒有編譯其他未修改的文件,避免了重復(fù)編譯。這里可以想象在一個大型源碼的工程或者一個內(nèi)核源碼,里面的源文件上千或上萬個,如果只修改了一個小問題,就要全部重新編譯,就會花費大量編譯的過程,Makefile就可以避免這個問題,而且支持多線程并發(fā)操作,可以減少很多編譯的時間,提高工作效率。


那么Makefile是如何判斷文件是否有修改過呢??

Makefile是通過對比時間戳,當(dāng)我們生成中間文件或可執(zhí)行文件之后,他們的創(chuàng)建時間肯定要比 .c文件最后修改的時間晚,如果某個 .c文件有新修改過,它的時間戳肯定會比原來生成中間文件或可執(zhí)行文件的時間戳晚,這樣就判斷這個 .c文件有被更新過,就會重新編譯它。


5. 正常運行后,執(zhí)行可執(zhí)行文件輸入 ./main 即可,就能看到代碼執(zhí)行的結(jié)果


6. 在makefile文件的最后可以看到有個clean,這個clean就是前面所說的標簽,它不是一個文件,所以make無法生成它的依賴關(guān)系和決定它是否要執(zhí)行,只能通過顯示指定這個目標才可以 ,通過make clean的指令就可以執(zhí)行clean下面的命令。


到這里,一個基礎(chǔ)版的Makefile就完成了。

?

四、Makefile的優(yōu)化

學(xué)會了編寫基礎(chǔ)版的Makefile后,就可以對剛剛寫的Makefile進行優(yōu)化。


優(yōu)化1:省略命令

我們將上面寫的基礎(chǔ)版Makefile改成下面這樣的省略版:

執(zhí)行make后的結(jié)果:


可以看到,這些文件都在同一目錄下的時候,省略版和基礎(chǔ)版的結(jié)果是一樣的,省略版的makefile中去掉了生成main.o、openFile.o、readFile.o和writeFile.o這些目標的依賴和生成命令,這就是make的隱含規(guī)則,make會試圖去自動推導(dǎo)產(chǎn)生這些目標的依賴和生成命令,這個行為就是隱含規(guī)則的自動推導(dǎo)。


優(yōu)化2:引入變量

這里引入變量的意思有點像使用宏替換,改成$(變量名),$是格式:

優(yōu)化3:引入函數(shù)格式:$(函數(shù)名? 實參列表)

引入函數(shù)后的Makefile版本可以改寫成:

優(yōu)化4:對文件進行分類管理在一個實際工程項目中程序文件比較多,我們就會對文件按照文件類型進行分類,分為頭文件、源文件、目標文件和可執(zhí)行文件,分別放在不同的目錄中,由Makefile統(tǒng)一管理這些文件,將生產(chǎn)的目標文件放在目標目錄下,可執(zhí)行文件放到可執(zhí)行目錄下,分類目錄如下圖:


  • bin目錄:放可執(zhí)行文件

  • include目錄:放頭文件

  • obj目錄:放中間目標文件

  • src目錄:放源文件


可見原來那些文件都不在同一目錄下了,那么這時候如果還用之前的Makefile,make就沒法處理了,自動推導(dǎo)也會無法進行,就需要改成如下:

在Makefile中,最終要生成可執(zhí)行文件main我們把它叫做終極目標,其它所有的 .o 文件本身也是一個目標,也需要編譯生成,工程里面許多的 .c 就會生成許多的 .o,每一個 .c 都寫一遍目標依賴命令顯然是不可行的,于是就有了類似for循環(huán)的東西,把所有目標變成一個集合,但不是真正用for循環(huán),而是使用一些抽象的符號表示,解釋如下:

  • %.o:所有 .o 結(jié)尾的文件

  • %.c:所有 .c 結(jié)尾的文件

  • $@:表示目標文件

  • $<:表示第一個依賴文件,也叫初級依賴

  • $^:表示所有的依賴文件,也叫終極依賴


當(dāng)然,不止只有這些符號,只是列舉了上面出現(xiàn)的或者常見的。

執(zhí)行make后的結(jié)果:


make執(zhí)行后bin目錄里面已經(jīng)生成了可執(zhí)行文件main,obj目錄里面已經(jīng)生成了中間目標文件 main.o、openFile.o、readFile.o、writeFile.o,最后執(zhí)行main后的結(jié)果也是和前面基礎(chǔ)版的Makefile的結(jié)果是一樣的。

原文作者:混說Linux



一文手把手教你寫一個 Makefile 文件的評論 (共 條)

分享到微博請遵守國家法律
察隅县| 姚安县| 昌乐县| 惠来县| 彰武县| 隆德县| 北碚区| 宁河县| 扶沟县| 德令哈市| 新丰县| 宝鸡市| 安国市| 盐边县| 花垣县| 商洛市| 永修县| 九龙城区| 腾冲县| 宁化县| 闽清县| 中方县| 利川市| 樟树市| 黄陵县| 阿鲁科尔沁旗| 沂水县| 株洲县| 元朗区| 奇台县| 怀来县| 通辽市| 彭水| 南康市| 淄博市| 新丰县| 民权县| 蓬溪县| 买车| 枞阳县| 祁东县|