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