Makefile的引入及規則

首發平台:微信公眾號baiwenkeji

ARM裸機1期加強版視頻課程配套WiKi第9課第5節_Makefile的引入及規則。

文字不能完全替代視頻,所以如果你看了這些文章不太懂,建議購買視頻進一步學習。

視頻購買地址:100ask.taobao.com

使用keil, mdk, avr等工具編譯程序時點點滑鼠就可以,它的內部機制是什麼?它怎麼組織管理程序?怎麼決定編譯哪一個文件?

答:實際上keil等IDE開發工具管理程序的內部機制也是Makefile,在linux下開發裸板程序的時候,使用Makefile組織管理這些程序,本節講解Makefile最基本的規則。

Makefile要做什麼事情呢? 組織管理程序和文件,不妨寫一個小程序實驗:

文件a.c

#include <stdio.h>

int

main()

{

func_b();

return 0;

}

文件b.c

#include

<stdio.h>

void

func_b()

{

printf("This is B
");

}

編譯:

gcc -o test a.c b.c

運行:

./test

結果:

This is B

gcc -o test a.c b.c這條命令雖然簡單,但是它完成的功能不簡單。

來看看它做了哪些事情。

我們知道.c程序 –> 得到可執行程序

要經過四個步驟:

1.預處理

2.編譯

3.彙編

4.鏈接

我們經常把前三個步驟統稱為編譯。具體分析這條命令:gcc -o test a.c b.c

它們要經過下面幾個步驟:

1).對於a.c執行:預處理 編譯 彙編 的過程,a.c –>xxx.s –>xxx.o 文件。

2).對於b.c執行:預處理 編譯 彙編 的過程,b.c –>yyy.s –>yyy.o 文件。

3).最後:xxx.o和yyy.o鏈接在一起得到一個test應用程序。

提示:gcc -o test a.c b.c -v :加上一個『-v』選項可以看到它們的處理過程

第一次編譯a.c得到xxx.o文件,這合乎情理, 執行完第一次之後,如果修改a.c ,又再次執行:gcc -o test a.c b.c,對於a.c應該重新生成xxx.o,但是對於b.c,又會重新編譯一次,這完全沒必要:b.c根本沒有修改,直接使用第一次生成的yyy.o文件即可。

以上,不用Makefile的缺點:對所有的文件都會再處理一次,即使b.c沒有經過修改,b.c也會被重新編譯一次, 當文件比較少時,沒什麼問題,文件非常多的時候,編譯的效率會很低。

如果文件非常多的時候,只是修改了一個文件,所有文件都會被重新編譯一次,編譯的時候就會需要很長時間。

對於這些源文件,我們應該分別處理,執行:預處理 編譯 彙編 ,先分別編譯它們,最後再把它們鏈接在一起,比如:

編譯:

gcc -o a.o a.c

gcc -o b.o b.c

鏈接:

gcc -o test a.o b.o

比如:上面的例子,當我們修改a.c之後,a.c會重新編譯, 然後再把它們鏈接在一起就可以,b.c 不需要重新編譯。

問題又來了,怎麼知道哪些文件被更新了/被修改了?

比較時間:比較a.o和a.c的時間,如果a.c的時間比a.o的時間更加新的話,就表明a.c被修改了。

同理,b.o和b.c也會進行同樣的比較。比較test和a.o, b.o的時間,如果a.o或者b.o的時間比test更加新的話,就表明應該重新生成test。

Makefile 就是這樣做的。

現在寫出一個簡單的Makefile:

makefie最基本的語法是規則,規則:

目標 : 依賴1 依賴2 …

[TAB]命令

當「依賴」比「目標」新,執行它們下面的命令。我們把上面三個命令寫成makefile規則,如下:

test :a.o b.o //test是目標,它依賴於a.o b.o文件,一旦a.o或者b.o比test新的時候,需要執行下面的命令,重新生成test可執行程序。

gcc -o test a.o b.o

a.o : a.c

//a.o依賴於a.c,當a.c更加新的話,執行下面的命令來生成a.o

gcc -c -o a.o a.c

b.o : b.c

//b.o依賴於b.c,當b.c更加新的話,執行下面的命令來生成b.o

gcc -c -o b.o b.c

來做一個實驗:

在該目錄下寫一個Makefile文件:

文件:Makefile

test:a.o b.o

gcc -o test a.o b.o

a.o :a.c

gcc -c -o a.o a.c

b.o : b.c

gcc -c -o b.o b.c

上面是makefile中的三條規則。makefile就是名字為「makefile」的文件。當我們編譯程序時,直接執行make命令即可,一執行make命令它會生成第一個目標test可執行程序, 如果發現a.o 或者b.o沒有,會先生成a.o或者b.o,發現a.o依賴a.c,有a.c但是沒有a.o,它會認為a.c比a.o新,則執行它們下面的命令來生成a.o,同理,b.o和b.c的處理關係也是這樣的。

如果修改a.c ,再次執行make,它的本意是想生成第一個目標test應用程序, 它需要先生成a.o, 發現a.o依賴a.c(假設我們修改了a.c),發現a.c比a.o更加新,就會執行gcc -c -o a.o

a.c命令生成a.o文件。b.o依賴b.c,發現b.c並沒有被修改,則不會執行gcc -c -o b.o b.c來重新生成b.o文件。

現在a.o b.o都有了,其中的a.o比test更加新,就會執行gcc -o test a.o b.o重新鏈接得到test可執行程序。所以當執行make命令,則會執行下面兩條命令:

gcc -c -o a.o a.c

gcc -o test a.o b.o

第一次執行make的時候,會執行下面三條命令(三條命令都執行):

gcc -c -o a.o a.c

gcc -c -o b.o b.c

gcc -o test a.o b.o

再次執行make 會有下面的提示:

make: `test`

is up to date.

再次執行make 會判斷Makefile文件中的依賴,發現依賴沒有更新,所以目標文件就不會重新生成,於是有上面的提示。當我們修改a.c後,重新執行make會執行下面兩條指令:

gcc -c -o a.o a.c

gcc -o test a.o b.o

同時修改a.c b.c,執行make則會執行下面三條指令。

gcc -c -o a.o a.c

gcc -c -o b.o b.c

gcc -o test a.o b.o

a.c文件被修改了,重新編譯生成a.o,

b.c被修改了,重新編譯生成b.o,

a.o, b.o都更新了,則重新鏈接生成test可執行程序,makefile的規則其實不難.

規則是Makefie的核心,執行make命令的時候,會在當前目錄下找到名為:Makefile的文件,根據裡面的內容來執行裡面的判斷/命令


推薦閱讀:

震驚 | 聯想電腦上不可安裝Linux操作系統?
gnome2.x 和 gnome3 哪個更好?
如何學習及利用開源代碼?
Linux 用戶一打開終端就 sudo su 算是壞習慣嗎?
你是如何走上linux運維這條路的?

TAG:Linux | 嵌入式開發 |