MAKEFILE簡介

 Make是一個開發源代碼的Make工具。Make是什麼?在命令行下寫程序的人應該都知道,它是一個項目管理工具。它的最基本用途就是管理項目的編譯、連接。它會按照規則(定義在規則文件中)、依賴順序對項目中的文件進行編譯、連接或把它們安裝到系統中。GNU Make的可執行程序通常就是make.exe。
一個簡單的例子—基本規則
下面來看一個簡單的例子(以下內容均以Win32平臺爲例):
文件名:makefile
1. # makefile
2. # this is a example of make file
3. all:a1 a2
4.   @echo this is all!
5. a1:
6.   @echo this is a1!
7. a2:
8.   @echo this is a2!
運行make後,結果如下:
this is a1!
this is a2!
this is all
現在讓我們來分析一下這個簡單的規則文件。
第1、 2行不用說,一眼就可以看出是註釋。在Make規則文件中,註釋是以“#”開始,是行註釋,和C++中的“//”功能一樣。不過你可不能把它放到其它的語句之後,否則就錯了。第3行就是規則開始了!all:a1 a2一行中,規則的名字就是all,它通常是目標名(target)。一條規則可以有不止一個名字,像這一行,你也可以把它寫成all all2:a1 a2。這時,規則就有了兩個名稱—all和all2。當然,還可以有更多,都看你自己。後面的5、7兩行也分別是兩條規則的起始。在“:”之後的,就是依賴項。在這一行裏,依賴項有兩個,分別是a1和a2。這些依賴項可以是其它的規則名(目標名),也可以是文件名。依賴和目標之間的關係就是“依賴關係”。一條規則中,可以有零個(像後面的兩條規則)、一個或多個依賴。第4行@echo this is all!是命令行。它是執行all規則時要執行的命令。要注意的是,一條規則內的命令要以tab爲一行的起始,以表示命令是屬於一個規則。一條規則也可以有多條命令,每條命令佔一行(要以tab開頭)。至於可以使用哪些命令,這完全取決於你使用的OS和SHELL。
當執行make時,它會找到第一條規則。然後,make就會檢查依賴和目標之間的關係。如果目標比依賴舊,就執行規則,以更新目標。執行完規則就結束。如何判定目標和依賴的新舊呢?如果目標(文件)不存在,目標的時間就爲0;如果目標(文件存在),目標的時間就爲文件的修改時間。如果依賴項是一條規則,就執行依賴的規則(這裏是一個遞歸),然後依賴的時間就是當前最新時間;如果是一個存在的文件,就爲文件的修改時間,否則就報錯。之後,就可以比較目標和依賴之間的關係。不過,有一點特殊的是,在沒有依賴項時,依賴的時間爲1。
在這個例子中,make先找到規則“all”,發現目標不存在,所以目標的時間爲0;然後在查找依賴“a1”,結果“a1”不存在;於是,執行規則“a1”。“a1”不存在,所以它的時間爲0,而“a1”沒有依賴,它的依賴時間爲1;1>0,所以,執行規則“a1”。然後返回規則“all”,再檢查依賴“a2”。“a2”執行過程同“a1”。這時,“all”的目標時間爲0,依賴時間爲最新時間。於是,執行規則“all”的命令。
當然,大家也可以指定一條規則讓make執行,比如:make a1這個命令就是告訴make程序不去找第一條規則,而是規則“a1”來執行。並且我們還可以一次執行多條規則,比如:執行make a1 a2就會連續執行“a1”、“a2”兩條規則。
OK,雖然講得很混亂,但也費了我半天的力氣。大家應該有一點了解make規則的執行過程了吧。
現在來總結一下依賴的寫法。如下(中括號中的內容是可選內容):
Target : [dependence] [dependence2] […]
[command]
[command2]
[…]
Target可以是文件名。Dependence可以是其它的target名或文件名。Command就是操作系統所運行的命令行。
變量
 一個make規則文件有這些內容就已經基本可以工作了。可是,當我們在編譯一個程序時,如果有些內容要反覆用到,每次都要寫一長串的話,是很麻煩的。於是,make就引入了宏這個概念(其實也可以看成簡單的腳本語言)。
宏變量的定義如下:
var1 = this is a macro demo!
var1就是變量名,它的值就是“this is a macro demo!”
如果我們要使用這個變量的值,那只有通過$這個運算符才行—$(var1)代表的就是“this is a macro demo!”。
如下makefile
1. var1 = this is a macro demo!
2. all:
3.   @echo $(var1)
結果輸出:
this is a macro demo!
用戶在執行命令行時也可以定義宏變量。其形式如下:
make all var1=”this is a test”
執行結果爲:
this is a test
我們不僅可以使用自定義變量,還可以通過這種方式使用系統環境變量。這樣可以大大方便我們建議靈活的規則。如下makefile
1. all:
2.   @echo $(windir)
執行結果爲:
C:/WinNT
(注意:makefile中的變量是大小寫敏感的)
除此之外,makefile中還有一些內定的特殊變量。這些變量可以代替在不同的規則中的目標、依賴等內容。使得規則的建立更加便利。請看如下例子:
1. all : a.exe
2. a.exe : a.obj
3.   cl $< /Fo$@ /nologo
4. a.obj : a.c
5.   cl $< /c /Fo$@ /nologo
大家可以看到,這裏用了$<和$@這兩個奇怪的符號。運行一下吧!
cl a.c /c /Foa.obj /nologo
a.c
cl a.obj /Foa.exe /nologo
很明顯,$<變成了a.c和a.obj,$@變成了a.obj和a.exe。應該明白了吧?
$@代表規則中的目標名(也就是規則名)。
$<代表規則中的依賴項目。注意,它只代表規則所有依賴項目中的第一項!
其它還有:
$^代表規則中所有的依賴項目。
$?代表規則中時間新於目標的依賴項目。
不僅如此,還可以給這些特殊的變量加一些限制。
如:
在規則
debug/out.exe : out.obj
中,$@代表debug/out.exe,而$(@D)代表目錄名debug,$(@F)代表文件名out.exe。其它如$(<D)、$(<F)、$(^D)、$(^F)、$(?D)、$(?F)與此類似。
內建規則
爲了方便使用,makefile中加入了一些基本規則。在沒有寫明命令的情況下,程序會按目標以及依賴的類型自動選擇一些默認的命令來編譯程序。
如下表:
類型目標類型依賴類型命令
C程序*.o*.c$(CC) -c $(CPPFLAGS) $(CFLAGS)
C++程序*.o*.cc$(CXX) -c $(CPPFLAGS) $(CXXFLAGS)
彙編程序*.o*.s$(AS) $(ASFLAGS)
Frotran*.o*.f$(FC) -c $(FFLAGS)
Pascal*.o*.p$(PC) -c $(PFLAGS)
連接*.out*.o$(CC) $(LDFLAGS) name.o $(LOADLIBES) $(LDLIBS)
大家可以看到,在這個表中使用了很多不同的宏。這些宏都是編譯器內建的,我們也可以手工修改它們,這樣,就可以實現對內建規則的修改。
請看如下makefile:
1. CC = gcc
2. a : a.o
呵呵,是不是很奇怪?什麼都沒有寫,只寫了一個沒有內容的規則,怎麼能運行呢?試試吧!結果如下:
gcc    -c -o a.o a.c
gcc   a.o   -o a
在第1行中,我把內建變量CC的值改成了gcc(默認是cc)。這樣,在編譯時就會使用我所設定的gcc來工作。第2行,我給出了目標a和依賴a.o。由於有從a.c到a.o的默認規則,如果有a.c這個文件的話make就會自動使用內建規則來編譯。一切OK!
其它的規則你也可以試試。
除了這種傳統規則,還有一種內建規則,叫後綴規則。請看如下makefile:
1. a.exe : a.o
2.   cl a.o /MD /nologo
3. .c.o :
4.   cl $^ /c /Fo$@ /MD /nologo
在這個規則文件中,沒有說明a.o是由哪一個源文件生成,只給了一個.c.o的奇怪規則。這個規則的意思是對於以.o爲擴展名的目標,都以相應的.c源程序來生成。生成的命令就是規則中給出的那條命令。
  當然,make中並沒有包含所有的可用擴展名。它包含了.c、.o、.s、.cc等UNIX下常用的擴展名。在Windows下,我們還要手工添加幾個名稱,否則不是很方便。要添加擴展名,就要通過.SUFFIXES這個預處理標識來完成。比如我要添加.asm和.inc這兩種擴展名。只要在 makefile中加上.SUFFIXES .asm .inc就可以了。
 其它的內建規則大家可要自己去試了,不自己摸索,很難掌握好的!
常用的參數
 前面介紹了半天makefile的寫法,現在來說說make程序的基本參數吧。
-f參數可以指定makefile的名稱,這樣,就可以不用makefile做爲規則文件的名字了。
-i參數可以使make程序忽略運行時的錯誤,繼續運行。
-v參數用來顯示make程序的版本號。
--help參數可以顯示make程序的參數幫助。
好了,我只說這四個最常用的參數吧!其它的參數大家自己摸索吧!寫了一下午,頭都大了!還有,這只是一入門資料。Make中還有更復雜的控制語句和一些函數,有空再寫!想學的朋友最好還是到GNU的網站找文檔,自己學吧!
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章