Makefile的引入及規(guī)則

ARM裸機1期加強版視頻課程配套WiKi第9課第5節(jié)_Makefile的引入及規(guī)則。
文字不能完全替代視頻,所以如果你看了這些文章不太懂,建議購買視頻進一步學(xué)習(xí)。
視頻購買地址:http://100ask.taobao.com。
使用keil, mdk, avr等工具編譯程序時點點鼠標(biāo)就可以,它的內(nèi)部機制是什么?它怎么組織管理程序?怎么決定編譯哪一個文件?
答:實際上keil等IDE開發(fā)工具管理程序的內(nèi)部機制也是Makefile,在linux下開發(fā)裸板程序的時候,使用Makefile組織管理這些程序,本節(jié)講解Makefile最基本的規(guī)則。
Makefile要做什么事情呢? 組織管理程序和文件,不妨寫一個小程序?qū)嶒灒?/p>
文件a.c
#include <stdio.h>
int
main()
{
func_b();
return 0;
}
文件b.c
#include
<stdio.h>
void
func_b()
{
printf("This is B\n");
}
編譯:
gcc -o test a.c b.c
運行:
./test
結(jié)果:
This is B
gcc -o test a.c b.c這條命令雖然簡單,但是它完成的功能不簡單。
來看看它做了哪些事情。
我們知道.c程序 –> 得到可執(zhí)行程序
要經(jīng)過四個步驟:
1.預(yù)處理
2.編譯
3.匯編
4.鏈接
我們經(jīng)常把前三個步驟統(tǒng)稱為編譯。具體分析這條命令:gcc -o test a.c b.c
它們要經(jīng)過下面幾個步驟:
1).對于a.c執(zhí)行:預(yù)處理 編譯 匯編 的過程,a.c –>xxx.s –>xxx.o 文件。
2).對于b.c執(zhí)行:預(yù)處理 編譯 匯編 的過程,b.c –>yyy.s –>yyy.o 文件。
3).最后:xxx.o和yyy.o鏈接在一起得到一個test應(yīng)用程序。
提示:gcc -o test a.c b.c -v :加上一個‘-v’選項可以看到它們的處理過程
第一次編譯a.c得到xxx.o文件,這合乎情理, 執(zhí)行完第一次之后,如果修改a.c ,又再次執(zhí)行:gcc -o test a.c b.c,對于a.c應(yīng)該重新生成xxx.o,但是對于b.c,又會重新編譯一次,這完全沒必要:b.c根本沒有修改,直接使用第一次生成的yyy.o文件即可。
以上,不用Makefile的缺點:對所有的文件都會再處理一次,即使b.c沒有經(jīng)過修改,b.c也會被重新編譯一次, 當(dāng)文件比較少時,沒什么問題,文件非常多的時候,編譯的效率會很低。
如果文件非常多的時候,只是修改了一個文件,所有文件都會被重新編譯一次,編譯的時候就會需要很長時間。
對于這些源文件,我們應(yīng)該分別處理,執(zhí)行:預(yù)處理 編譯 匯編 ,先分別編譯它們,最后再把它們鏈接在一起,比如:
編譯:
gcc -o a.o a.c
gcc -o b.o b.c
鏈接:
gcc -o test a.o b.o
比如:上面的例子,當(dāng)我們修改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更加新的話,就表明應(yīng)該重新生成test。
Makefile 就是這樣做的。
現(xiàn)在寫出一個簡單的Makefile:
makefie最基本的語法是規(guī)則,規(guī)則:
目標(biāo) : 依賴1 依賴2 …
[TAB]命令
當(dāng)“依賴”比“目標(biāo)”新,執(zhí)行它們下面的命令。我們把上面三個命令寫成makefile規(guī)則,如下:
test :a.o b.o //test是目標(biāo),它依賴于a.o b.o文件,一旦a.o或者b.o比test新的時候,需要執(zhí)行下面的命令,重新生成test可執(zhí)行程序。
gcc -o test a.o b.o
a.o : a.c
//a.o依賴于a.c,當(dāng)a.c更加新的話,執(zhí)行下面的命令來生成a.o
gcc -c -o a.o a.c
b.o : b.c
//b.o依賴于b.c,當(dāng)b.c更加新的話,執(zhí)行下面的命令來生成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中的三條規(guī)則。makefile就是名字為“makefile”的文件。當(dāng)我們編譯程序時,直接執(zhí)行make命令即可,一執(zhí)行make命令它會生成第一個目標(biāo)test可執(zhí)行程序, 如果發(fā)現(xiàn)a.o 或者b.o沒有,會先生成a.o或者b.o,發(fā)現(xiàn)a.o依賴a.c,有a.c但是沒有a.o,它會認(rèn)為a.c比a.o新,則執(zhí)行它們下面的命令來生成a.o,同理,b.o和b.c的處理關(guān)系也是這樣的。
如果修改a.c ,再次執(zhí)行make,它的本意是想生成第一個目標(biāo)test應(yīng)用程序, 它需要先生成a.o, 發(fā)現(xiàn)a.o依賴a.c(假設(shè)我們修改了a.c),發(fā)現(xiàn)a.c比a.o更加新,就會執(zhí)行g(shù)cc -c -o a.o
a.c命令生成a.o文件。b.o依賴b.c,發(fā)現(xiàn)b.c并沒有被修改,則不會執(zhí)行g(shù)cc -c -o b.o b.c來重新生成b.o文件。
現(xiàn)在a.o b.o都有了,其中的a.o比test更加新,就會執(zhí)行g(shù)cc -o test a.o b.o重新鏈接得到test可執(zhí)行程序。所以當(dāng)執(zhí)行make命令,則會執(zhí)行下面兩條命令:
gcc -c -o a.o a.c
gcc -o test a.o b.o
第一次執(zhí)行make的時候,會執(zhí)行下面三條命令(三條命令都執(zhí)行):
gcc -c -o a.o a.c
gcc -c -o b.o b.c
gcc -o test a.o b.o
再次執(zhí)行make 會有下面的提示:
make: `test`
is up to date.
再次執(zhí)行make 會判斷Makefile文件中的依賴,發(fā)現(xiàn)依賴沒有更新,所以目標(biāo)文件就不會重新生成,于是有上面的提示。當(dāng)我們修改a.c后,重新執(zhí)行make會執(zhí)行下面兩條指令:
gcc -c -o a.o a.c
gcc -o test a.o b.o
同時修改a.c b.c,執(zhí)行make則會執(zhí)行下面三條指令。
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可執(zhí)行程序,makefile的規(guī)則其實不難.
規(guī)則是Makefie的核心,執(zhí)行make命令的時候,會在當(dāng)前目錄下找到名為:Makefile的文件,根據(jù)里面的內(nèi)容來執(zhí)行里面的判斷/命令。