文章目錄
- 1.9.1 GNU make
- 1.9.2 makefile 基本結構
- 1.9.3 makefile 變數
- 1.9.4 GNU make 的主要預定義變數
- 1.9.5 隱含規則
- 1.9.7 運行 make
GNU make 和 makefile
GNU make
makefile 基本結構
makefile 變數
GNU make 的主要預定義變數
隱含規則
makefile 範例
運行 make
1.9.1 GNU make
在大型的開發項目中,通常有幾十到上百個的源檔案,如果每次均手工鍵入 gcc 命令進行編譯的話,則會
非常不方便。因此,人們通常利用 make 工具來自動完成編譯工作。這些工作包括:如果僅修改了某幾個
源檔案,則只重新編譯這幾個源檔案;如果某個標頭檔被修改了,則重新編譯所有包含該標頭檔的源檔案。
利用這種自動編譯可大大簡化開發工作,避免不必要的重新編譯。
實際上,make 工具通過一個稱為 makefile 的檔案來完成並自動維護編譯工作。makefile 需要按照某種
文法進行編寫,其中說明了如何編譯各個源檔案並串連產生可執行檔,並定義了源檔案之間的依賴關係。
當修改了其中某個源檔案時,如果其他源檔案依賴於該檔案,則也要重新編譯所有依賴該檔案的源檔案。
makefile 檔案是許多編譯器,包括 Windows NT 下的編譯器維護編譯資訊的常用方法,只是在整合開發環
境中,使用者通過友好的介面修改 makefile 檔案而已。
預設情況下,GNU make 工具在當前工作目錄中按如下順序搜尋 makefile:
* GNUmakefile
* makefile
* Makefile
在 UNIX 系統中,習慣使用 Makefile 作為 makfile 檔案。如果要使用其他檔案作為 makefile,則可利用類
似下面的 make 命令選項指定 makefile 檔案:
$ make -f Makefile.debug
1.9.2 makefile 基本結構
makefile 中一般包含如下內容:
* 需要由 make 工具建立的項目,通常是目標檔案和可執行檔。通常使用“目標(target)”一詞來表示
要建立的項目。
* 要建立的項目依賴於哪些檔案。
* 建立每個項目時需要啟動並執行命令。
例如,假設你現在有一個 C++ 源檔案 test.C,該源檔案包含有自訂的標頭檔 test.h,則目標檔案 test.o
明確依賴於兩個源檔案:test.C 和 test.h。另外,你可能只希望利用 g++ 命令來產生 test.o 目標檔案。
這時,就可以利用如下的 makefile 來定義 test.o 的建立規則:
# This makefile just is a example.
# The following lines indicate how test.o depends
# test.C and test.h, and how to create test.o
test.o: test.C test.h
g++ -c -g test.C
從上面的例子注意到,第一個字元為 # 的行為注釋行。第一個非注釋行指定 test.o 為目標,並且依賴於
test.C 和 test.h 檔案。隨後的行指定了如何從目標所依賴的檔案建立目標。
當 test.C 或 test.h 檔案在編譯之後又被修改,則 make 工具可自動重新編譯 test.o,如果在前後兩次
編譯之間,test.C 和 test.h 均沒有被修改,而且 test.o 還存在的話,就沒有必要重新編譯。這種依賴
關係在多源檔案的程式編譯中尤其重要。通過這種依賴關係的定義,make 工具可避免許多不必要的編譯工
作。當然,利用 Shell 指令碼也可以達到自動編譯的效果,但是,Shell 指令碼將全部編譯任何源檔案,包括
哪些不必要重新編譯的源檔案,而 make 工具則可根據目標上一次編譯的時間和目標所依賴的源檔案的更新
時間而自動判斷應當編譯哪個源檔案。
一個 makefile 檔案中可定義多個目標,利用 make target 命令可指定要編譯的目標,如果不指定目標,
則使用第一個目標。通常,makefile 中定義有 clean 目標,可用來清除編譯過程中的中間檔案,例如:
clean:
rm -f *.o
運行 make clean 時,將執行 rm -f *.o 命令,最終刪除所有編譯過程中產生的所有中間檔案。
1.9.3 makefile 變數
GNU 的 make 工具除提供有建立目標的準系統之外,還有許多便於表達依賴性關係以及建立目標的命令的特
色。其中之一就是變數或宏的定義能力。如果你要以相同的編譯選項同時編譯十幾個 C 源檔案,而為每個目
標的編譯指定冗長的編譯選項的話,將是非常乏味的。但利用簡單的變數定義,可避免這種乏味的工作:
# Define macros for name of compiler
CC = gcc
# Define a macr o for the CC flags
CCFLAGS = -D_DEBUG -g -m486
# A rule for building a object file
test.o: test.c test.h
$(CC) -c $(CCFLAGS) test.c
在上面的例子中,CC 和 CCFLAGS 就是 make 的變數。GNU make 通常稱之為變數,而其他 UNIX 的 make
工具稱之為宏,實際是同一個東西。在 makefile 中引用變數的值時,只需變數名之前添加 $ 符號,如
上面的 $(CC) 和 $(CCFLAGS)。
1.9.4 GNU make 的主要預定義變數
GNU make 有許多預定義的變數,這些變數具有特殊的含義,可在規則中使用。表 1-5 給出了一些主要的
預定義變數,除這些變數外,GNU make 還將所有的環境變數作為自己的預定義變數。
表 1-5 GNU make 的主要預定義變數
預定義變數 含義
$* 不包含副檔名的目標檔案名稱。
$+ 所有的依賴檔案,以空格分開,並以出現的先後為序,可能包含重複的依賴檔案。
$< 第一個依賴檔案的名稱。
$? 所有的依賴檔案,以空格分開,這些依賴檔案的修改日期比目標的建立日期晚。
$@ 目標的完整名稱。
$^ 所有的依賴檔案,以空格分開,不包含重複的依賴檔案。
$% 如果目標是歸檔成員,則該變數表示目標的歸檔成員名稱。例如,如果目標名稱
為 mytarget.so(image.o),則 $@ 為 mytarget.so,而 $% 為 image.o。
AR 歸檔維護程式的名稱,預設值為 ar。
ARFLAGS 歸檔維護程式的選項。
AS 組譯工具的名稱,預設值為 as。
ASFLAGS 組譯工具的選項。
CC C 編譯器的名稱,預設值為 cc。
CCFLAGS C 編譯器的選項。
CPP C 先行編譯器的名稱,預設值為 $(CC) -E。
CPPFLAGS C 先行編譯的選項。
CXX C++ 編譯器的名稱,預設值為 g++。
CXXFLAGS C++ 編譯器的選項。
FC FORTRAN 編譯器的名稱,預設值為 f77。
FFLAGS FORTRAN 編譯器的選項。
1.9.5 隱含規則
GNU make 包含有一些內建的或隱含的規則,這些規則定義了如何從不同的依賴檔案建立特定類型的目標。
GNU make 支援兩種類型的隱含規則:
* 尾碼規則(Suffix Rule)。尾碼規則是定義隱含規則的老風格方法。尾碼規則定義了將一個具有某個
尾碼的檔案(例如,.c 檔案)轉換為具有另外一種尾碼的檔案(例如,.o 檔案)的方法。每個尾碼規
則以兩個成對出現的尾碼名定義,例如,將 .c 檔案轉換為 .o 檔案的尾碼規則可定義為:
.c.o:
$(CC) $(CCFLAGS) $(CPPFLAGS) -c -o $@ $<
* 模式規則(pattern rules)。這種規則更加通用,因為可以利用模式規則定義更加複雜的依賴性規則。
模式規則看起來非常類似於正則規則,但在目標名稱的前面多了一個 % 號,同時可用來定義目標和依賴
檔案之間的關係,例如下面的模式規則定義了如何將任意一個 X.c 檔案轉換為 X.o 檔案:
%.c:%.o
$(CC) $(CCFLAGS) $(CPPFLAGS) -c -o $@ $<
1.9.7 運行 make
我們知道,直接在 make 命令的後面鍵入目標名可建立指定的目標,如果直接運行 make,則建立第一個
目標。我們還知道可以用 make -f mymakefile 這樣的命令指定 make 使用特定的 makefile,而不是
預設的 GNUmakefile、makefile 或 Makefile。但 GNU make 命令還有一些其他選項,表 1-6 給出了
這些選項。
表 1-6 GNU make 命令的常用命令列選項
命令列選項 含義
-C DIR 在讀取 makefile 之前改變到指定的目錄 DIR。
-f FILE 以指定的 FILE 檔案作為 makefile。
-h 顯示所有的 make 選項。
-i 忽略所有的命令執行錯誤。
-I DIR 當包含其他 makefile 檔案時,可利用該選項指定搜尋目錄。
-n 只列印要執行的命令,但不執行這些命令。
-p 顯示 make 變數資料庫和隱含規則。
-s 在執行命令時不顯示命令。
-w 在處理 makefile 之前和之後,顯示工作目錄。
-W FILE 假定檔案 FILE 已經被修改。