閱讀83 返回首頁    go 阿裏雲 go 技術社區[雲棲]


Makefile劄記之:Makefile工作原理及隱含規則應用

從隻有一個Makefile的單級Makefile開始。



對於一個稍大的項目或者說軟件來說,源程序(.c文件或者是.h文件),以及源程序文件夾,絕對不隻是一個文件或者源程序文件夾,想想你寫的代碼隻有一個源程序或者程序文件夾還是什麼時候。一個好的程序員,總是希望自己寫的代碼文件,清晰,一目了然,通過不同的文件夾,不用的名字就能大致看出該程序的功能。

當隻有一個源程序文件的時候,比如main.h,main.c,這個時候,由於源程序文件少,我們可以手動對程序進行編譯:gcc  main.c   -o  main_exe。這個時候,手動編譯程序還是很方便的。但是,如果程序有幾十甚至幾百幾千個的時候,這個時候,通過gcc手動的對源程序進行編譯的時候,就有困難了。另外,好的程序員會去考慮到程序的可移植性和程序文件之間的關係,我們總是希望把源程序拿過來直接編譯然後就能運行,我們會把源程序放在不同的文件夾下。這樣一來,對於手動編譯程序就更加困難了。這個時候,Makefile優勢就顯現出來了。

下麵以實例來說明Makefile究竟如何編寫,

 

 

/*

*************************************

name:example-one.c

*************************************

*/

#include “example-one.h”

{

      …….

      ……..

}

 

 

*************************************

name:example-one.h

養成每個.c源程序都有一個與之同名的.h

與之對應來做一些聲明。

*************************************

*/

#include <>

#include <>

 

 

 

 

/*

*************************************

name:example-two.c

*************************************

*/

#include “example-two.h”

#include “example-one.h”

{

      …….

      ……..

}

 

 

*************************************

name:example-two.h

養成每個.c源程序都有一個與之同名的.h

與之對應來做一些聲明。

*************************************

*/

#include <>

#include <>

 

 

 

 

 

…..

…..

 

 

*************************************

name:main.c

*************************************

#include “example-two.h”

{

  

}

 

在這裏我不講Makefile的規則,對於這些規則,網上的關於Makefile的編寫都大同小異,我主要講講Makefile的工作原理。

按照上述文件之間的關係不難看出,example-two.c由於使用了example-one.c的東西,那麼當我們編譯example-two.c的時候就需要example-one.c。

還是先來說下幾個關鍵詞

target:cond

按照Makefile的規則,target就是目標,然後cond就是要編譯得到target目標所需要的條件。

其實在很多情況下,我們的Makefile可以隻寫出

%:%.o

這個規則就可以了。

以這個例子為例。雖然按照實際情況上來說,有個層次關係,main.o的編譯需要example-two.c, example-two.h作為必要條件,同理,example-two.o需要example-one.h和example-one.c作為必要條件。

但是,你可以試試,這個例子的Makefile可以簡化到如此簡單:

OBJS := main.o example-one.o example-two.o

EXEC := test

$(EXEC):$(OBJS)

tab           gcc –o $(EXEC)  $(OBJS)

 

寫好commamd之後,make就可以編譯出程序了,絕對沒問題。

Makefile其實也是一種腳本語言。他隻需要知道編譯成可執行程序EXEC所必須的目標文件OBJS有哪些(這裏對於將目標文件.o文件,源文件 .h, .c文件同名很重要,所以要養成這種習慣會給變成帶來很大的方便的)。

    GNU 的make 工作時的執行步驟入下:

1、讀入所有的Makefile。

2、讀入被include 的其它Makefile。

3、初始化文件中的變量。

4、推導隱晦規則,並分析所有規則。

5、為所有的目標文件創建依賴關係鏈。

6、根據依賴關係,決定哪些目標要重新生成。

7、執行生成命令。

當make一旦知道可執行文件所需的目標文件.o文件之後,他發現要生成可執行文件需要哪些.o文件,他就會在你所指定的目錄已經當前目錄中查找,當他找不到某一.o文件的時候,就會啟動隱含規則去試圖生成.o文件。同樣,當生成.o文件的時候就會去找相應的.c文件和.h文件。這才是這個例子會有如此簡單的Makefile的真正原因。而Makefile的編寫工作最終落實到你給出文件,讓make去找文件。而本身源程序.c文件中的include也同時告訴Makefile,.c文件需要哪些.h條件,所以在由.c文件到.o文件的過程中可以由它自動來完成,不需要我們明確的顯示的告訴他這些關係。

給個不恰當的比喻:.c  .h文件相當於人,通過#include  已經extern 等血緣關係,在make之後,構成了家庭這種.o文件。

family.o: zhang.c   wang.c   zhang_son.h

所有的人都用過這種關係來構成家庭。

然後那麼社區這種可執行文件是有家庭這種.o文件構成的。那麼在組裝可執行文件這一階段隻需要列出該社區的所有的家庭,於是也就自動完成了社區的組建。

community:family_one.o  family_two.o…

總之,在組裝可執行程序的規則中,要列出所需要的所有的.o文件。

 

 

 

 

 

 


版權申明:
轉載文章請注明原文出處https://blog.csdn.net/feiyinzilgd/archive/2010/02/07/5297161.aspx
並請聯係譚海燕本人或者前往譚海燕個人主頁留言 

 

 

最後更新:2017-04-02 04:01:45

  上一篇:go major=$(awk &quot;//$2= =/&quot;$module/&quot; {print //$1}&quot; /proc/devices)正確理解。
  下一篇:go QString和string類型相互轉換