GNU Make User Manual

GNU Make 使用手冊
Version 3.79
繁體版更新日期 2006/08/30
校稿 ChanningLan
目錄
1 make概述
1.1 怎樣閱讀本手冊
1.2 問題和BUG
2.1 規則的格式
2.2一個簡單的Makefile檔案
2.3mke處理Makefile檔案的過程
2.4使用變數簡化Makefile檔案
2.5讓make推斷命令
2.6另一種風格的Makefile檔案
2.7在目錄中刪除檔案的規則
3编寫Makefile文件
3.1Makefile檔案的內容
3.2Makefile檔案的命名
3.3引入(include)其它的Makefile檔案
3.4變數MAKEFILES
3.5Makefile檔案重新生成的過程
3.6重載其它Makefile檔案
3.7make讀取Makefile檔案的過程
4 編寫規則
4.1規則的語法
4.2在檔案名中使用萬用字元
4.2.1萬用字元例子
4.2.2使用萬用字元的常見錯誤
4.2.3函數wildcard
4.3在目錄中搜尋先決條件
4.3.1VPATH:所有先決條件的搜尋路俓(stem)
4.3.2vpath指令
4.3.3目錄搜尋過程
4.3.4編寫搜尋目錄的shell命令
4.3.5目錄搜尋和隱含規則
4.3.6連接庫(Link Libraries)的搜尋目錄
4.4假想(phony)目標
4.5沒有命令或先決條件的規則
4.6使用空目錄檔案記錄事件
4.7內建的特殊目標名
4.8具有多個目標的規則
4.9具有多條規則的目標
4.10靜態樣式規則
4.10.1靜態樣式規則的語法
4.10.2靜態樣式規則和隱含規則
4.11雙冒號規則(::)
4.12自動生成先決條件
5 在規則中使用命令
5.1命令回顯
5.2執行命令
5.3並行執行
5.4命令錯誤
5.5中斷或關閉make
5.6遞迴make
5.6.1變數MAKE的工作模式
5.6.2與子make通訊的變數
5.6.3與子make通訊的選項
5.6.4`--print-directory'選項
5.7定義固定次序命令
5.8使用空命令
6
使用變數
6.1變數引用基礎
6.2變數的兩個特色
6.3變數進階引用技術
6.3.1替換引用
6.3.2巢狀變數引用
6.4變數取值
6.5設定變數
6.6為變數值附加文字(text)
6.7撤銷(override)指令
6.8定義多行變數
6.9環境變數
6.10特定目標變數的值
6.11特定樣式變數的值
7 Makefile檔案的條件語句
7.1條件語句的例子
7.2條件語句的語法
7.3測試標誌的條件語句
8 文字(text)轉換函數
8.1函數呼叫語法
8.2字元串替換和分析函數
8.3檔案名函數
8.4函數foreach
8.5函數if
8.6函數call
8.7函數origin
8.8函數shell
8.9控制Make的函數
9
執行
make
9.1指定Makefile檔案的參數
9.2指定最終目標的參數
9.3代替執行命令
9.4避免重新編譯檔案
9.5變數重載
9.6測試編譯程式
9.7選項概要
10 使用隱含規則
10.1使用隱含規則
10.2隱含規則目錄
10.3隱含規則使用的變數
10.4隱含規則鏈
10.5定義與重新定義樣式規則
10.5.1樣式規則簡介
10.5.2樣式規則的例子
10.5.3自動變數
10.5.4樣式匹配
10.5.5萬用規則
10.5.6刪除隱含規則
10.6定義最新類型的預設規則
10.7舊式的後置規則(suffix rule)
10.8隱含規則搜尋算法
11 使用make更新資料庫檔案
11.1資料庫成目標
11.2資料庫成目標的隱含規則
11.2.1更新資料庫成
11.3使用檔案的危險
11.4資料庫檔案的後置規則(suffix rule)
12 GNU make的特
13 不相失去的特
14 Makefile檔案
14.1makefile檔案的通用
14.2makefile檔案的工具
14.3指定命令的變數
14.4安裝路俓(stem)變數
14.5用目標
14.6安裝命令分類
15快速
16make生的錯誤
17複雜的Makefile檔案例子 附錄 名詞翻對照表
1 Make 概述
Make 自動決定一個程式中哪些檔案要重新編譯發布重新編譯它的命令。本版本GNU Make使用手冊 Richard M. Stallman and Roland McGrath編著,是從Paul D. Smith寫的V3.76版本發展 GNU Make符合IEEE Standard 1003.2-1992 (POSIX.2) 6.2章節的規定
為C語程式更具有代表性,以我們的例子基C語程式,但Make並不是僅僅能夠處理C語程式可以處理 那些編譯器能夠在Shell命令執行的的種語的程式實上,GNU Make不僅僅限於程式可以適於任何如果 檔案變化導致檔案必須更新的任務。 如果要使用Make,必須先寫一個為Makefile的檔案,該檔案述程式中個檔案之間相互係,且提供每一個
檔案的更新命令在一個程式中,可執行程式檔案的更新依靠OBJ檔案,而OBJ檔案是由源檔案編譯得來旦合適的Makefile檔案,每次更些源檔案在shell命令簡單的 make
就能執行所有的要的重新編譯任務。Make程式根據Makefile檔案中的數個檔案更時間戳決定哪些檔案
要更新。對於這些需要更新的檔案Make基Makefile檔案發布命令進行更新進行更新的模式由提供的命令行參數
控制具體請看執行Make章節。
1.1怎樣閱讀本手冊
如果您現下對Make一者您僅需了解對make 的介紹,請查前幾章內容,略過後章節。前幾 章節是普通介紹內容章節是具體的專業、技術內容。 如果您對其它Make程式熟悉,請參閱GNU Make的特不相失去的特點部GNU Make的特點這章列 出了GNU Makemake程式的展開,不相容和失去的特章解釋了其它Make程式有的特徵而GNU Make缺乏原因。 對於快速瀏覽者,請參閱選項概要、快速和內建的特殊目標名
1.2問題和BUG
如果您有關GNU Make的問題或者您認您發現了一個BUG,請向開發者報告;我們不能許諾我們能幹什麼,但 我們會盡力修正報告BUG之前,請確您是否真正發現了BUG,仔細研究文檔後確認是否真按您的指令執
。如果文檔不能清楚告訴您么做,也報告,這是文檔的一個BUG您報告己親修正BUG之前,請把它分離出來,即在使問題暴露前提下儘可能縮小Makefile檔案。然 個Makefile檔案和Make給出精確結果發給我們。同時請說明您希望得到什麼,這可以幫助我們確定問題是否出在文 檔上。
旦您找到一個精確的問題,請給我們發E-mail,我們的E-mail位址是︰ bug-make@gnu.org
件中引入(include)使用的GNU Make的版本號。您可以利用命令‘make—version’得到版本號。同時希望您提 供您機器型號和作業系統類型,如可能話,希望同時提供config.h檔案(該檔案有配置過程)。
2 Makefile檔案介紹
Make程式要一個所的Makefile檔案來告訴干什麼。在多數情況下,Makefile檔案告訴Make怎樣編譯和連接成 一個程式
章我們將討論一個簡單的Makefile檔案,該檔案述怎樣8個C程式檔案和3個檔案編譯和連接成為一個文 字(text)編輯器。Makefile檔案可以同時告訴Make怎樣執行所要的雜亂無章的命令如,清刪除特定的檔案
)。如果詳細、複雜的Makefile檔案例子,請參閱複雜的Makefile檔案例子一章。
make重新編譯個編輯器時,所有動的C語言源檔案必須重新編譯。如果一個檔案,每一個引入(include) 該頭檔案的C語言源檔案必須重新編譯,這才能保證生成的編輯器是所有檔案更新後的編輯器。每一個C語言源
案編譯後生一個對應OBJ檔案,如果一個檔案重新編譯所有的OBJ檔案無論是剛剛編譯得到的或原來編譯得到必須從新連接,形成一個新的執行檔案
2.1 規則的格式
一個簡單的Makefile檔案引入(include)一系列規則”,其樣式如下︰
目標(target): 先決條件(prerequiries)
<tab>命令(command)
目標(target)通常生的檔案的名稱,如;目標可以是執行檔案或OBJ檔案目標也可是一個執行的動作名稱, 諸如‘clean’(詳細內容參閱假想(phony)目標一節)。
先決條件來輸從而產生目標的檔案一個目標常有個先決條件 命令Make執行的動作一個規則可以含有個命令,每個命令一行注意︰每個命令行前面必須是一個Tab
符,即命令行一個字符是Tab這是不小心容易出錯的地方。
通常,如果一個先決條件生變化要規則呼叫命令對相應先決條件和服務進行處理從而更新或建目標。但是 指定命令更新目標的規則並不都需要先決條件如,引入(include)和目標clern’相聯繫的刪除命令的規則沒有 先決條件
規則一般是於解釋怎樣和何時重建特定檔案的,這些特定檔案是這詳盡規則的目標Make需首先呼叫命令先決 條件進行處理而才能或更新目標。當然,一個規則也可以是於解釋怎樣和何時執行一個動作,詳見編寫規 則一章。
一個Makefile檔案可以引入(include)規則以外的其它文字(text),但一個簡單的Makefile檔案僅僅需要引入(include)規則 。雖然真正的規則比這裡展示的例子複雜,但格式卻是完全一樣
2.2一個簡單的Makefile檔案
一個簡單的Makefile檔案,該檔案一個為文字(text)編輯器(edit執行檔案生成,該檔案依靠8個 OBJ檔案.o檔案),依靠8個C程式檔案和3個檔案個例子中所有的C語言源檔案引入(include)defs.h 檔案,但僅僅定義編命令的檔案引入 (include)command.h’頭檔案,僅僅改變編輯器緩沖區低層檔案引入(include)buffer.h’頭檔案
edit : main.o kbd.o command.o display.o \ insert.o search.o files.o utils.o cc -o edit main.o kbd.o command.o display.o \ insert.o search.o files.o utils.o
main.o : main.c defs.h cc -c main.c kbd.o : kbd.c defs.h command.h cc -c kbd.c command.o : command.c defs.h command.h cc -c command.c display.o : display.c defs.h buffer.h cc -c display.c insert.o : insert.c defs.h buffer.h cc -c insert.c search.o : search.c defs.h buffer.h cc -c search.c files.o : files.c defs.h buffer.h command.h cc -c files.c utils.o : utils.c defs.h cc -c utils.c clean : rm edit main.o kbd.o command.o display.o \ insert.o search.o files.o utils.o
我們把每一個行使用反斜線(\)分為兩行或多行,實們相當於一行,這僅僅是閱讀
便
使用Makefile檔案建立可執行的edit的檔案,鍵make 使用Makefile檔案目錄中刪除執行檔案和目標,鍵make clean 在個Makefile檔案例子中目標包括執行檔案editOBJ檔案main.okdb.o’。先決條件C語言源檔案和 C語言頭檔案如‘main.cdef.h實上,每一個OBJ檔案即是目標也是先決條件命令行包括cc -c main.ccc -c kbd.c’。
目標一個檔案時,如果它的一個先決條件生變化目標必須重新編譯和連接。任何命令行的一個 字符必須是‘Tab符,這可以把Makefile檔案中的命令行與其它行分開來。(一定要Make並不知命令 是如何工作的僅僅能向您提供保證目標的合適更新的命令Make的全部工作是當目標要更新時,按照您定的 具體規則執行命令。)
目標clean’不是一個檔案,僅僅是一個動作的名稱。正情況下,在規則中clean’這個動作並執行 目標clean’也不需任何先決條件般情況下,意告訴make執行clean命令,否clean命令永遠
執行。注意這樣的規則不需任何先決條件們存在的目的僅僅是執行一特殊的命令像這些不需要先決條件 僅表動作的目標為假想(phony)目標。詳細內容參見假想(phony)目標參閱命令錯誤可以了解rm或其它命令怎樣 導致make錯誤的
2. make處理makefile檔案的過程
預設情況下,make於第一個目標假想(phony)目標的名稱前.’)。這個目標稱為預設最終目標(即 make最終更新的目標具體內容請看指定最終目標的參數一節)。上節的簡單例子中預設最終目標更新執行檔案edit’,以我們將該規則設為一規則。這旦您給出 命令 make make就會當前目錄的makefile檔案處理一條規則。在本例中,第一條規則連接生成edit’,但在make 全部完成本規則工作之前,必須先處理edit依靠OBJ檔案。這些OBJ檔案按照各自的規則處理更新,每OBJ 檔案的更新規則編譯其檔案重新編譯根據依靠檔案或檔案是否比現存OBJ檔案更’,者OBJ檔 案是否存
其它規則的處理根據的目標是否和預設最終目標的先決條件聯來。如果規則和預設最終目 標無任何這些規則不會執行告訴Make強製執行(如輸入執行make clean命令)。
OBJ檔案重新編譯之前,Make它的先決條件C語言源檔案和C語言頭檔案是否需要更新。如果這些 C語言源檔案和C語言頭檔案不是任何規則的目標make將不會對們做任何情。Make也可以自動生C語言源程式 ,這需要特定的規則,如可以根據Bison或Yacc生C語言源程式
OBJ檔案重新編譯(如果需要的話)之make決定是否重新連接生成edit執行檔案。如果edit可執行檔案
不存在或任何一個OBJ檔案比存在的edit執行檔案’,則make重新連接生成edit執行檔案
,如果我們修改了‘insert.c檔案,然後執行makemake將會編譯insert.c檔案更新insert.o檔案 ,然後重新連接生成edit執行檔案。如果我們修改了‘command.h檔案,然後執行makemake將會重新編譯kbd.ocommand.o檔案,然後重新連接生成edit執行檔案
2.4使用變數簡化makefile檔案
我們的例子中,我們edit的生成規則中所有的OBJ檔案兩次,這裡
edit : main.o kbd.o command.o display.o \ insert.o search.o files.o utils.o cc -o edit main.o kbd.o command.o display.o \ insert.o search.o files.o utils.o
樣的兩次錯的可能,系統中加入一個新的OBJ檔案,我們可能在一個地方加入了, 而在另一個地方卻了。我們使用變數可以簡化makefile檔案並錯的可能。變數是定義一個字元串一次 ,而能在多處替代字元串使用具體內容閱讀使用變數一節)。
在makefile檔案中使用名為objects, OBJECTS, objs, OBJS, obj, 或 OBJ的變數代所有OBJ檔案已約定成俗個 makefile檔案我們定義名為objects的變數其定義格式如下︰
objects = main.o kbd.o command.o display.o \ insert.o search.o files.o utils.o
一個OBJ檔案的地方,我們使用寫為`$(objects)'式的變數代替具體內容閱讀使用變數一節)。 下面是使用變數後的的makefile檔案
objects = main.o kbd.o command.o display.o \ insert.o search.o files.o utils.o
edit : $(objects) cc -o edit $(objects) main.o : main.c defs.h cc -c main.c kbd.o : kbd.c defs.h command.h cc -c kbd.c command.o : command.c defs.h command.h cc -c command.c display.o : display.c defs.h buffer.h cc -c display.c insert.o : insert.c defs.h buffer.h cc -c insert.c search.o : search.c defs.h buffer.h cc -c search.c files.o : files.c defs.h buffer.h command.h cc -c files.c utils.o : utils.c defs.h cc -c utils.c clean :
rm edit $(objects)
2.5 讓make推斷命令
編譯單的C語言源程式並不需要寫命令,因為make可以把它推斷出來︰make有一個使用CC c命令的C語 程式編譯更新為相同檔案名的OBJ檔案的隱含規則make可以自動使用cc -c main.c -o main.o命令把‘main.c 編譯 main.o’。因,我們可以略OBJ檔案的更新規則。詳細內容請看使用隱含規則一節。
如果C語言源程式能夠這樣自動編譯則它能夠自動加入先決條件中以我們可在先決條件中C語言源程 式而可以命令。下面是使用隱含規則和變數objects的makefile檔案的例子 objects = main.o kbd.o command.o display.o \ insert.o search.o files.o utils.o
edit : $(objects) cc -o edit $(objects)
main.o : defs.h kbd.o : defs.h command.h command.o : defs.h command.h display.o : defs.h buffer.h insert.o : defs.h buffer.h search.o : defs.h buffer.h files.o : defs.h buffer.h command.h utils.o : defs.h
.PHONY : clean clean :
-rm edit $(objects) 這是我們實際編寫makefile檔案的例子。(和目標clean’聯繫複雜情況具體參見假想(phony)目標命令 錯誤兩內容。)因為隱含規則便常重要在makefile檔案中常使用它們。
2.6 另一種風格的makefile檔案
當時在makefile檔案中使用隱含規則建立OBJ檔案時,用另一種風格的makefile檔案也是可行的種風格的 makefile檔案中,可以依據先決條件分代替依據目標分。下面是種風格的makefile檔案
objects = main.o kbd.o command.o display.o \
insert.o search.o files.o utils.o edit : $(objects) cc -o edit $(objects) $(objects) : defs.h kbd.o command.o files.o : command.h display.o insert.o search.o files.o : buffer.h 這裡的defs.h所有OBJ檔案的的一個先決條件command.h和bufffer.h具體列出OBJ檔案的先決條件 雖然種風格編寫makefile檔案更具風makefile檔案更加小,但把每一個目標的訊息放而不喜歡這種風格
2.7 在目錄中刪除檔案的規則
編譯程式並不是編寫make規則的一事情。Makefile檔案可以告訴make去完成編譯程式以外的其它任務,如,怎樣刪 除OBJ檔案和執行檔案以保目錄的乾淨。下面是刪除用make規則編輯器的例子 clean: rm edit $(objects) 在用中,應該編寫複雜的規則不能預料的情況發更接用的規則樣式如下︰
.PHONY : clean clean :
-rm edit $(objects) 可以防止make在名為clean的檔案而發亂,且導致它在執行rm命令時發生錯誤具體參見假想 (phony)目標命令錯誤兩內容)。 諸如這樣的規則不能放在makefile檔案的,因我們不希望它變為預設最終目標。應該我們的makefile檔案例子一 樣,把edit的規則前面,從而把編譯更新edit執行程式定為預設最終目標
3 編寫makefile檔案
make編譯系統依據的訊來源於稱為makefile檔案的資料庫
3.1 makefile檔案的內容
makefile檔案含5種內容具體規則隱含規則定義變數指令和釋。規則變數和指令在後章節介紹 具體規則用什么時間或怎樣重新生成為規則目標的一個或多個文件的目標所依靠
檔案,這些檔案目標的先決條件。具體規則可能同時提供了或更新目標的命令。詳細內容參閱編 寫規則一章。
隱含規則用於述什么時間或怎樣重新生成一文件名的一系列文件的它描述的目標是根據和它名字
相同的檔案進行建或更新的,同時提供了或更新目標的命令。詳細內容參閱使用隱含規則一節。
定義變數是為一個變數一個固定的字符串值,從而後的文件中能夠使用變數代替個字
注意在makefile檔案中定義變數的makefile檔案例子中我們定義所有OBJ檔案的變 數objects(詳細內容參閱使用變數簡化makefile檔案一節)。
指令make根據makefile文件執行一定任務的命令這些包括如下幾方面: 讀取其它makefile文件(詳細內容參見
引入(include)其它的makefile文件
)。
(根據變數的值)是否使用或略makefile文件的分內容(詳細內容參閱
makefile文件的條件
語句
節)。
定義多行變數,即定義變數值可以引入(include)多行字的變數(詳細內容參見
定義多行變數
)。
以‘#’開的行是注釋行在處理時將make略,如果一個行在行是‘\表示下一行繼續,這釋可以持續多行除在define指令內部外,註釋可以出現下makefile檔案的任何地方,甚至在命令內部(
這裡shell決定什麼是內容)。
3.2 makfile檔案的命名
預 設 情 況 下 , 當 make 尋 makefile 檔 案 時 , 它 試 搜 尋 具 有 如 下 的 名 字 的 檔 案 , 按 GNUmakefile’ 、‘makefileMakefile’。
通常情況下您應該把您的makefile檔案命名為makefileMakefile’。(我們使用Makefile’,因為它基本出現 目錄單的前面,其它重要的檔案如‘README)。雖然首先搜尋GNUmakefile’,但我們 使用的makefile檔案特為GNU make編寫的在其它make版本上不能執行,您才應該使用GNUmakefile作 為的makefile的檔案名
如果make不能發現具有上面所述名字的檔案將不使用任何makefile檔案。這您必須使用命令參數定目標make 試用內建的隱含規則如何重建目標。詳細內容參見使用隱含規則一節。 如果您使用名字makefile檔案,您可以使用-f--file參數指定的makefile檔案參數-f name-­file=name’能夠告訴make讀名字為name的檔案作為makefile檔案。如果您使用 -f--file參數多一個,意
著您指定多個makefile檔案所有的makefile檔案具體的序發生作用旦您使用了‘-f--file參數,將自動查是否存在名為GNUmakefile’、‘makefileMakefile的makefile檔案
3.3 引入(include)其它的makefile檔案
include指令告訴make暫停讀取當前的makefile檔案先讀include指令指定的makefile檔案後再繼續指令在makefile檔案 一行其格式如下︰
include filenames...
filenames可以含shell檔案名的格式
在include指令行處的多的空格,但make處理略這些空格,注意該行不能以Tab字符開(因為 ,以Tab字符開始的行make命令行)。include和檔案名之間以空格開,兩個檔案名之間也以空格開, 的空格make處理略,行的部可以上以‘#起始釋。檔案名可以引入(include)變數函數呼叫 在處理時由make進行展開(具體內容參閱使用變數一節)。
如,.mk檔案︰‘a.mk’、‘b.mkc.mk’,變數$(bar)展開為bish bash下面是︰
include foo *.mk $(bar) 和include foo a.mk b.mk c.mk bish bash’相同。
make見include指令時, make暫停讀取當前的makefile檔案,依次讀取的makefile檔案完之make 繼續讀取當前makefile檔案中include指令後的內容 使用include指令的一種情況是幾個程式分有單的makefile檔案,但們需要一系列的變數定義(詳細內容參閱 設定變數),系列的樣式規則(詳細內容參閱定義與重新定義樣式規則)。
另一種使用include指令情況是需要自動從源檔案為目標生先決條件的情況,時,先決條件在makefile檔案引入 (include)的檔案中。這種模式比其它版本的make把先決條件附加在makefile檔案後部的統模式更顯得簡。具體內容 參閱自動生先決條件 如果makefile檔案名不以‘/’開頭,當前目錄下也不能找到,搜尋另的目錄。首搜尋以‘-|-­include-dir參數指定的目錄 ,然次 搜尋下 面 的 目錄 (如果們存在的 話)︰‘ prefix/include' ( 通常為
/usr/local/include') /usr/gnu/include', /usr/local/include', /usr/include'
如果指定引入(include)的makefile檔案在述所有的目錄都不能找到,make將產生一個,注意這不是致命的錯 處理完include指令引入(include)的makefile檔案繼續處理當前的makefile檔案一旦完成makefile檔案的讀取make或更新舊式的或不存在的makefile檔案。詳細內容參閱makefile檔案重新生成的過程有在所有make 求丟失的makefile檔案的努力失make才能斷定丟失的makefile檔案一個命的錯誤。 如果您希望對不存且不能重新建的makefile檔案進行略,且不產生錯誤訊則使用-include指令代替include指
格式如下︰
-include filenames...
種指令的作用就是對於任何不存在的makefile檔案都不會產生錯誤(即使也不會產)。如果希望保持和其 它版本的make使用sinclude指令代替-include指令
3.4 變數MAKEFILES
make 讀取數個 makefile 時(包括根據環境變數 MAKEFILES 讀取的 makefile命令指定的預設的、使用 include 指 定的),這些makefile的名字自動的加進變數 MAKEFILE_LIST 。這些檔案名稱會在開始被 make 解析之前就 加進變數 MAKEFILE_LIST 也就是說,如果在一個 makefile 中一件事就是查這個變數的最後一個字,這個字就該是前這個 makefile 的 檔名的 makefile 使用指令 include ,這個變數的最後一個字就會變成 include 進的 makefile 的檔名 一個名為 Makefile 的 makefile 含有以下內容
name1 := $(word $(words $(MAKEFILE_LIST)),$(MAKEFILE_LIST)) include inc.mk name2 := $(word $(words $(MAKEFILE_LIST)),$(MAKEFILE_LIST))
all:
@echo name1 = $(name1) @echo name2 = $(name2)
那麼,可以預料到會看到以下輸出
name1 = Makefile name2 = inc.mk
其它的特殊環境變數 GNU make 支援一個特殊變數,任何給該變數的值都會被忽略;回它的特殊值
一個特殊變數 .VARIABLES 。當展開此變數時,會引入(include)一在所有的 makefile 中所定義的 變數名表。這裡頭引入(include)了值為空的變數(如內建變數,參考 示性規則所使用的變數 ),但不包括只在 個指定標的的內容中定義的變數
3.5 makefile檔案重新生成的過程
makefile檔案可以由其它檔案重新生成,如從RCS或SCCS檔案生成。如果一個makefile檔案可以從其它檔案重 新生成一定注意讓make更新makefile檔案讀取makefile檔案
成讀取所有的makefile檔案make查每一個目標並試更新它。如果對於一個makefile檔案有說明它怎樣 更新的規則(無論當前的makefile檔案中或其它makefile檔案中),者存在一條隱含規則說明它怎樣更新具體內 容參見使用隱含規則),則在要的makefile檔案將會自動更新。在所有的makefile檔案查之,如果發現任何 一個makefile檔案生變化make就會清空所有記錄並重新讀入所有makefile檔案。(然後次試更新這些makefile檔,正情況下,因這些makefile檔案已被更新make將不會們。)
如果您知的一個或多個makefile檔案不能重新建立,也許由於執行效率緣故,您不希望make按照隱含規則搜尋 或重建它們,您應使用常的阻止按照隱含規則們。如,您可以寫一個具體的規則,把這些makefile檔案 作目標,但不提供任何命令(詳細內容參閱使用空命令)。
如果在makefile檔案中指定依據雙冒號規則(::)使用命令重建一個檔案,但沒有提供先決條件則一make執行 重建檔案(詳細內容參見雙冒號規則(::))。同,如果在makefile檔案中指定依據雙冒號規則(::)使用命令重建的一 個makefile檔案且不提供先決條件則一make執行就會重建makefile檔案,然後重新讀入所有makefile檔案,然重建makefile檔案重新讀入所有makefile檔案,如此往無限,致使make不能任務。 如果要避免情況一定注意不依據雙冒號規則(::)使用命令並且不提供先決條件重建任何makefile檔案
如果您沒有使用-f--file指定makefile檔案make將會使用預設的makefile檔案名(詳細內容參見3.2內容 )。不像使用-f--file選項指定具體的makefile檔案,這時make不能確定makefile檔案是否存。如果預設的 makefile檔案不存,但可以由執行的make依據規則建立,您需要執行這些規則要使用的makefile檔案
如果預設的makefile檔案不存make將會按照搜尋的次序立,到將makefile檔案成或 make所有的檔案名試過來。注意make不能找到或建立makefile檔案不是錯誤,makefile檔案並不是執行make必須的。
使使用-t指定,‘-t--touch選項更新makefile檔案不產任何影響 makefile檔案 更新以當您使用-t--touch選項時,您不要使用舊式的makefile檔案決定touch’哪個目標具體含 義參閱代替執行命令)。同,因-q' (或 --question') 和 -n' (或 --just-print')也能不阻止更新makefile檔案 舊式的makefile檔案其它的目標將產生錯誤的輸出結果。如,‘make -f mfile -n foo命令將這樣執行更新
mfile’,然後讀入輸出更新foo的命令和先決條件,但執行更新foo’,注意,所有回顯的更新foo的命令在更新後的mfile中指定的
使用過程中,您一定確實希望阻止更新makefile檔案的情況。如果這樣,您可以在makefile檔案命令行將需要更新的makefile檔案指定為目標,如阻止更新makefile檔案。一makefile檔案名明確指定為一個目標 選項-t將會對生作用。如這樣設定,‘make -f mfile -n foo命令將這樣執行讀入mfile’,輸出更新 foo的命令和先決條件,但執行更新foo’。回顯的更新foo的命令引入(include)在現存mfile
3.6 重載其它makefile檔案
一個makefile檔案和另一個makefile檔案也是有用的。您可以使用include指令更多的makefile檔案引入 (include)進來,如加入更多的目標和定義的變數。然而如果兩個makefile檔案對相同的目標給出了不同的命令,make 就會產生錯誤makefile檔案要引入(include)其它makefile檔案的,您可以使用萬用字元樣式規則說明有在依靠當前 makefile檔案中的訊不能重新建目標時,make搜尋其它的makefile檔案,詳細內容參見定義與重新定義樣式規則如︰如果您有一個說明怎樣建目標foo’(和其它目標的makefile檔案Makefile’,您可以編寫另一個 GNUmakefile的makefile檔案引入(include)以下語句
foo:
frobnicate > foo %: force @$(MAKE) -f Makefile $@ force: ;
如果鍵make foo’,make就會找到‘GNUmakefile’,讀入,然後執行frobnicate > foo’。如果鍵make bar’,make發現無根據‘GNUmakefile立‘bar’,使用樣式規則提供的命令︰‘make f Makefile bar’。如 Makefile提供了‘bar更新的規則make就會使用規則。對其它GNUmakefile’不提供怎樣更新的目標 make也會同樣處理。這種工作的模式是使用了樣式規則中的樣式匹配符‘%’,它可以和任何目標匹配。該規則指定了 一個先決條件force’,來保證命令一定要執行,無論目標檔案是否存。我們給出的目標‘force’時使用了空命令 ,這防止make按照隱含規則搜尋和建,否make將把同樣的匹配規則目標force,從而陷入先決條件的環中
3.7 make讀取makefile檔案的過程
GNU make它的工作顯的分為兩個階。在一階make讀取makefile檔案包括makefile檔案本、內置變數、隱含規則和具體規則構造所有目標的依靠表和它們的先決條件。在make使用這些內置的組織決定
要重新構造的目標使用要的規則進行工作。 了解make兩階的工作模式分重要,因為它影響變數函數展開模式;而這也是編寫makefile檔案時導致 誤的來源之。下面我們將對makefile檔案中不同架構展開模式進行結。我們稱在make工作一階生的展開 是立即展開︰情況下,makemakefile檔案進行語法分析時把變數和函數展開架構單元的一。我們把 不能立即執行的展開稱(deferred)展開。延時(deferred)展開架構直到已出現下上下架構中或make進入到了第 工作階時才執行展開。 您可能對這分內容不熟悉。您可以看完面幾章對這些知熟悉內容
變數
變數的定義語法如下︰
immediate = deferred immediate ?
= deferred
immediate := immediate immediate += deferred or immediate
define immediate deferred endef 對於附加符‘+=’,右邊變數如果前面使用:=定義為簡單展開變數則是立即變數其它(deferred) 變數
條件語句
,條件語句都按語法立即分析常用的有ifdefifeq、ifndef和inneq。
定義規則
規則不論如何,都按相同的模式展開。
immediate : immediate ; deferred
deferred 目標和先決條件都立即展開,構造目標的命令通常都是(deferred)展開。這個通用的規對具體規則、樣式 規則後置規則(suffix rule)靜態樣式規則和簡單先決條件定義都適
4編寫規則
makefile檔案中的規則來說明何時以怎樣重建特定檔案的,這些特定的檔案規則的目標通常情況下
,每個規則有一個目標)。在規則中列的其它檔案稱為目標的先決條件,同時規則還給出了目標建立、更新的命令般情況下規則的次序,但決定預設最終目標時卻是外。預設最終目標是您沒有另指定最終目標時,
make定的最終目標。預設最終目標makefile檔案中的一條規則的目標。如果第一條規則有多個目標,只有第一個目預設最終目標有兩種例情況︰以點(‘.’)開的目標不是預設最終目標(如果該目標引入 (include)一個或多個斜線(/) ‘/’,目標也可能是預設最終目標);另一種情況是樣式規則定義的目標不是預設最 終目標參閱定義與重新定義樣式規則)。
以,我們編寫makefile檔案時,通常將第一個規則的目標定為編譯全部程式或是由makefile檔案述的所有程式(經 常設定一個all的目標)。參閱指定最終目標的參數。
4.1規則的語法
通常一條規則如下︰
targets : prerequisites
command ...
targets : prerequisites ; command
command ...
目標target)是檔案的名稱,間由空格開。萬用字元可以在檔案名中使用參閱在檔案名中使用萬用字元),
am)’形式的檔案名表示m在檔案a中參閱資料庫成目標)。般情況下,一條規則只有一個目標,但偶 爾由於其它原因一條規則有多個目標參閱具有多個目標的規則)。
命令行Tab字符開,第一個命令可以和先決條件在一行命令和先決條件之間用分號開,也可以在先決條件 一行,以Tab字為行的。這兩種方法的果一樣,參閱在規則中使用命令。
用為變數引用的符,如果您真希望在規則中使用,您必須連寫兩次,‘$$參閱使 用變數)。您可以把一行在中間插入\’使其分為兩行,也就是說,一行的部是’\’的話,表示下一行是本行的
繼續。但這不是必須make沒有makefile檔案中行的長度進行一條規則可以告訴make兩件事情︰何時目標時,以怎樣在更新它們。
斷目標舊式的則和先決條件關密切先決條件也由檔案名檔案名之間由空格開,萬用字元和
資料庫成員也在先決條件中出現。一個目標如果不存在或它其中一個先決條件的修改時間目標已經 時。該來源於目標是根據先決條件的訊息計得來,因旦任何一個先決條件生變化目標檔案也就不
目標的更新模式命令決定命令shell解釋執行,但也有一的特點。參閱在規則中使用命令
4.2 在檔案名中使用萬用字元
一個簡單的檔案名可以過使用萬用字元代表許多檔案Make中的萬用字元和Bourne shell中的萬用字元一樣
是‘*’、‘[]’。例如︰‘*.C指在當前目錄中所有以‘.C’結尾的檔案
符‘~在檔案名的前面也有特殊的含義如果字符‘~’單或後面跟一個斜線(/) ‘/’,則代表您的home目錄。如
~/bin’展開/home/bin’。如果符‘~一個字展開為home目錄下以該字為名字的目錄,如 ‘~John/bin’表示‘home/John/bin’。在一業系統(如ms-dosms-windows不存在home目錄,可以過設定環
境變數home比。
在目標、先決條件和命令中的萬用字元自動展開。在其它上下文中萬用字元有在您明確表明呼叫萬用字元函數時才
展開。
萬用字元另一個特點是如果萬用字元前面是反斜線(\)\’,萬用字元失去通配能力。如‘foo\*bar’表示一個特定 的檔案其名字由‘foo’、‘*bar
4.2.1萬用字元例子
萬用字元可以用在規則的命令中萬用字元shell展開。如,下面的規則刪除所有OBJ檔案
clean
rm -f *.o 萬用字元在規則的先決條件中有用下面的makefile規則中,‘make print’將列所有從上您列動的.c檔案
print: *.c lpr -p $? touch print
本規則使用ptint作為一個空目標檔案使用空目標檔案記錄事件);自動變數$?來列那些經修改 的檔案自動變數 當您定義一個變數萬用字元不會展開,如果您這樣寫 objects = *.o 變數objects的值就是字元串*.o’。然而,如果您在一個目標先決條件和命令中使用變數objects的值萬用字元 那時展開。使用下面的語句使萬用字元展開︰
objects=$(wildcard *.o) 詳細內容參閱函數wildcard
4.2.2使用萬用字元的常見錯誤
下面有一個幼稚使用萬用字元展開的例子,但實上該例子不能完希望完成的任務。假設執行檔案foo’由當前目錄的所有OBJ檔案建立,其規則如下︰
objects = *.o
foo : $(objects) cc -o foo $(CFLAGS) $(objects)
由於變數objects的值為字元串*.o’,萬用字元在目標foo的規則下展開,以每一個OBJ檔案都會變為目標foo的先決條件並在重新編譯自己。 但如果您刪除所有的OBJ檔案,情況怎樣呢?沒有和萬用字元匹配的檔案目標foo’就依靠了一個 奇怪名字的檔案*.o’。因為目錄中不存檔案make將發出不能立‘*.o的錯誤訊。這可不是所要執行的 任務。
上,使用萬用字元得正確結果是可能,但您必須使用稍微複雜的技術,該技術包括使用函數wildcard和
替代字元串。詳細內容節論 微軟的作業系統(MS-DOSMS-WINDOWS使用反斜線(\)分目錄路俓(stem),如︰ C:\foo\bar\bar.c
和Unix風格c:/foo/bar/bar.c’相同(‘c:’是驅動)。當make在這些系統上執行時,不但支援在路俓(stem)中反斜線(\)支援Unix風格的斜線(/)。但是這種對反斜線(\)的支援包括萬用字元展開,因為萬用字元展開時,反斜 (\)用作引用字符。以,這些合您必須使用Unix風格的斜線(/)
4.2.3函數wildcard(萬用字元)
萬用字元在規則中可以自動展開,但設定在變數中或在函數的參數中萬用字元一般不能正展開。如果您需 要在這些合展開萬用字元,您應該使用函數wildcard格式如下︰
$(wildcard pattern...)
可以在makefile檔案的任何地方使用字元串,應時該字元串在指定目錄下存在的並檔案名和給出的檔案名
的格式相符合的檔案所代替檔案名中間由空格開。如果沒有和指定格式一的檔案則函數wildcard的輸出將會 略。注意這和在規則中萬用字元展開的模式不同,在規則中使用展開模式,而不是模式參閱上節)。 使用函數wildcard得到指定目錄所有的C語言源程式檔案名的命令格式為
$(wildcard *.c)
我們可以把所獲的C語言源程式檔案名的字元串透將‘.c後置變為.o轉換為OBJ檔案名的字元串其格式為
$(patsubst %.c,%.o,$(wildcard *.c))
這裡我們使用一個函數patsubst,詳細內容參閱字元串替換和分析函數。 這一個編譯特定目錄所有C語言源程式並連接在一的makefile檔案可以寫成如下格式
objects := $(patsubst %.c,%.o,$(wildcard *.c))
foo : $(objects) cc -o foo $(objects)
這裡使用了編譯C語言源程式的隱含規則,因此沒有必要為每個檔案寫具體編譯規則。 ‘:=’是‘=’的變,對‘:= ’的解釋,參閱兩種風格的變數。
4.3在目錄中搜尋先決條件
對於大系統,把源檔案放在一個單的目錄中,而把二進制檔案在另一個目錄中是十分常見的Make 的目錄搜尋特使自動在個目錄搜尋先決條件分容易。當您個目錄中重新的檔案,您不必改動單的 規則,僅僅改動一搜尋路俓(stem)即可。
4.3.1 VPATH所有先決條件的搜尋路俓(stem)
make變數VPATH的值指定make搜尋的目錄。經常用是那些引入(include)先決條件的目錄不是當前 的目錄;但VPATH指定make所有檔案都適用的目錄搜尋序列,包括規則的目標所要的檔案 如果一個作為目標或先決條件的檔案在當前目錄中不存make就會在VPATH指定的目錄中搜尋檔案。如果這些 目錄中找到要尋的檔案這些檔案在當前目錄下存在一樣規則把這些檔案指定為先決條件參閱編寫搜尋 目錄的shell命令
在VPATH變數定義中目錄的名字冒號或空格分開。目錄列舉的次序也是make 搜尋的次序。在MS-DOS、MS-
WINDOWS系統VPATH變數定義中的目錄的名字分號分開,因為在這些系統冒號用為路俓(stem)名的一通常在面)。如︰
VPATH = src:../headers
指定兩個目錄,‘src‘…/headers’,make也按照這個次序進行搜尋使用VPATH的值,下面的規則
foo.o : foo.c
在執行時就如下寫法一樣中斷 foo.o : src/foo.c 後在src目錄搜尋foo.c
4.3.2 vpath指令
vpath指令(注意是小和VPATH變數類,但卻更具靈活性。vpath指令許對符合一定格式類型的檔案名指定 一個搜尋路俓(stem)。這樣您就可以對一種格式類型的檔案名指定一個搜尋路俓(stem),對另外格式類型的檔案名指定另 一個搜尋路俓(stem)總共三種式的vpath指令
vpath pattern directories
一定格式類型的檔案名指定一個搜尋路俓(stem)搜尋的路俓(stem)要搜尋的目錄目錄冒號在MS- DOSMS-WINDOWS系統中用分號或空格開,和VPATH變數定義要搜尋的路俓(stem)格式一樣
vpath pattern
除和一定類型格式相聯繫的搜尋路俓(stem)
vpath
除所有前面由vapth指令指定的搜尋路俓(stem)
一個vpath的格式pattern一個含一個%的字元串。該字元串必須搜尋的一個先決條件的檔案名匹配%
任何字元串匹配樣式規則參閱定義與重新定義樣式規則)。例如,%.h和任何檔案名以.h結的檔案匹配。 如果不使用%’,格式必須與先決條件精確匹配,這情況很少使用
在vpath指令格式中的字符‘%’可以透前面的反斜線(\)被引用引用其它字符‘%’的反斜線(\)也可以被更多的反斜 線(\)引用。引用字符‘%’和其它反斜線(\)的反斜線(\)在和檔案名比較之前和格式。如果反斜線(\)所引用的字符
%沒有錯誤反斜線(\)不會執行來任何危。 如果vpath指令格式和一個先決條件的檔案名匹配當前目錄中先決條件不存則vpath指令中指定的目錄和
VPATH變數中的目錄一樣可以搜尋如︰
vpath %.h ../headers
將告訴make如果當前目錄中以‘.h’結檔案不存則在../headers目錄搜尋任何以‘.h’結先決條件
如果個vpath指令格式和一個先決條件的檔案名匹配則make一個接一個的處理它們,搜尋所有在指令中指定的目 Make在makefile檔案中出現的次序控制多個vpath指令多個指令雖然相同的格式,但們是相互。 以下
vpath %.c foo vpath % blish vpath %.c bar
表示搜尋`.c'檔案先搜尋目錄`foo'、然後`blish'最後`bar';如果是如下
vpath %.c foo:bar vpath % blish
表示搜尋`.c'檔案先搜尋目錄foo'、然bar'最後blish'
4.3.3目錄搜尋過程
透過目錄搜尋找到一個檔案,該檔案有可能不是您在先決條件單中所列出的先決條件透過目錄搜尋找到的 路俓(stem)也可能被廢棄Make決定過目錄搜尋找到的路俓(stem)廢棄依據的算法如下︰
1如果一個目標檔案在makefile檔案所在的目錄下不存將會執行目錄搜尋 2如果目錄搜尋成則路俓(stem)和所得到的檔案作為目標檔案存。
3所有目標的先決條件用相同 4、把先決條件處理成後,該目標可能需要或不需要重新建立︰
1如果該目標不需要重建目錄搜尋得到的檔案的路俓(stem)用作目標所有先決條件的路俓(stem),同時
目標檔案而言之,如果make不必重建目標使用過目錄搜尋得到的路俓(stem) 2、如果該目標要重建目錄搜尋得到的檔案的路俓(stem)廢棄目標檔案在makefile檔案所在的目錄重 建而言之,如果make要重建目標,是在makefile檔案所在的目錄重建目標,而不是在目錄搜尋得到的檔 案的路俓(stem)
算法似乎複雜,但卻可十精確解釋實所要的東西 其它版本的make使用一種簡單的算法︰如果目標檔案在當前目錄下不存,而過目錄搜尋得到,不論該目標
是否需要重建終使用過目錄搜尋得到的路俓(stem)。 實上,如果在GNU make中使的一全部目錄具種行為,您可以使用GPATH變數指定這些目錄GPATH變數和VPATH變數具有相同的語法和格式。如果過目錄搜尋得到一個舊式的目標,而目標在的目錄又出現GPATH變數路俓(stem)將不廢棄目標路俓(stem)重建
4.3.4編寫目錄搜尋的shell命令
使過目錄搜尋在其它目錄下找到一個先決條件,不能改變規則的命令,這些命令按照原來編寫的模式執行。 因,您應該小心的編寫這些命令,以便們可以在make能夠發現先決條件的目錄中處理先決條件
助諸如‘$^’的自動變數的使用shell命令參閱自動變數)。例如,‘$^’的值代所有的先決條件
引入(include)尋先決條件的目錄;‘$@’的值目標
foo.o : foo.c
cc -c $(CFLAGS) $^ -o $@
變數CFLAGS可以方便您利用隱含規則指定編譯C語言源程式的。我們這裡使用它是為了保持編譯C語言源程式致性。參閱隱含規則使用的變數 先決條件通常情況下也引入(include)檔案,因自動變數$<’的值是第一個先決條件,因這些頭檔案您可以不必在 命令中
如︰
VPATH = src:../headers foo.o : foo.c defs.h hack.h cc -c $(CFLAGS) $< -o $@
4.3.5 目錄搜尋和隱含規則
搜尋的目錄是由變數VPATH或隱含規則引入的vpath指令指定的(詳細參閱使用隱含規則)。如,如果檔案foo.o 沒有具體的規則make則使用隱含規則︰如檔案foo.cmake使用內置的規則編譯它;如果檔案foo.c當前目錄 下,就搜尋適當的目錄,如的目錄下找到foo.cmake樣使用內置的規則編譯它 隱含規則的命令使用自動變數是必需隱含規則可以然地使用目錄搜尋得到的檔案
4.3.6 連接庫(Link Libraries)的搜尋目錄
對於連接庫(Link Libraries)檔案目錄搜尋用一種特的模式。這種特的模式於︰您寫一個先決條件它的名 字是‘-|name。(您可以這裡寫一特的字符,因為先決條件檔案名庫檔案名通常
‘libname.a’ 的形式,而不是‘-|name’ 的形式。) 當一個先決條件的名字是‘-|name’的形式時,make特地在當前目錄下、與vpath匹配的目錄下、VPATH指定的目錄下 以‘/lib’, ‘/usr/lib', 和 ‘prefix/lib'(正常情況為`/usr/local/lib',但是MS-DOS、MS-Windows版本的make的行為好像是 prefix定義為DJGPP安裝的根目錄的情況)目錄下搜尋名字為‘libname.so'的檔案然後處理它。如果沒有搜尋到 ‘libname.so'檔案,然後在前述的目錄下搜尋‘libname.a'檔案。
如,如果系統中有/usr/lib/libcurses.a'的庫檔案
foo : foo.c -lcurses cc $^ -o $@
如果‘foo’比‘foo.c更舊,將導致命令cc foo.c /usr/lib/libcurses.a -o foo'執行
預設情況下是搜尋libname.so' 和libname.a'檔案具體搜尋的檔案及其類型使用.LIBPATTERNS變數指定,這個變 數值中的一個字都是一個字元串格式。當尋找名為‘-|name’的先決條件時,make首先用name替代清單中第一個字中 的格式成要搜尋的庫檔案名,然後使用庫檔案名在述的目錄中搜尋。如果沒有發現庫檔案則使用單中 的一個字其餘此類推 .LIBPATTERNS變數預設的值是"‘lib%.so lib%.a'",該對前面描述的預設行為提供支援。您可以透將該值設為空值 從而徹底關閉連接庫(Link Libraries)的展開。
4.4假想(phony)目標
假想(phony)目標並不是一個真正的檔案名僅僅是您定的一個具體規則所執行的一命令的名稱。使用假想 (phony)目標有兩個原因︰避免和具有相同的檔案衝突性能。
如果您寫一個其命令目標檔案的規則旦由於重建而提目標規則的命令就會執行
這裡有一個例子
clean: rm *.o temp
為rm命令名為clean的檔案以不應有名為clean的檔案。因不論何時您發布`make clean'指令 rm命令就會執行
假想(phony)目標能夠任何在目錄名為clean的檔案工作。但如在目錄下存在檔案clean,因為該目標clean沒 有先決條件檔案clean會認經該更新,因它的命令不會執行避免情況,您應該使用 如下的.PHONY目標樣式將該目標具體的為一個假想(phony)目標
.PHONY : clean
旦這明,‘make clean命令無論目錄下是否存在名為clean的檔案,該目標的命令都會執行 為make道假想(phony)目標不是一個根據別的檔案重新建際檔案跳過隱含規則搜尋假想 (phony)目標的步驟(詳細內容參閱使用隱含規則)。這是把一個目標為假想(phony)目標可以提執行效率原因 ,因此使用假想(phony)目標您不在目錄下是否際檔案。這,對前面的例子可以用假想(phony)目標的 寫出,其格式如下︰
.PHONY: clean clean: rm *.o temp
一個使用假想(phony)目標的例子使用make的遞迴進行連接的情況︰時,makefile檔案常常引入(include)系列需要建的子目錄的變數。不用假想(phony)目標任務使用一條規則其命令一個在個子目 錄環的shell命令
如下面的例子
subdirs: for dir in $(SUBDIRS); do \ $(MAKE) -C $$dir; \ done
使用述問題︰首,這個規則在建子目錄時產生的任何錯誤都不時發現,因,當一個子目錄 建立失時,該規則然會繼續剩餘的子目錄。雖然該問題可以添加監視錯誤產生並退出的shell命令來解決,但是如果make使用了‘-k選項,這個問題然會產。第,也許更重要的是您使用了該方法就失去使用make 並行處理的特點能力。
使用假想(phony)目標(如果子目錄經存,您必須這做,否,不存在的子目錄將不會立)可以避免 述問題
SUBDIRS = foo bar baz
.PHONY: subdirs $(SUBDIRS)
subdirs: $(SUBDIRS)
$(SUBDIRS): $(MAKE) -C $
foo: baz
時,如果子目錄baz’沒有建立完子目錄foo’將不會立;當使用並行建立時這種關其重 要
一個假想(phony)目標不應該是一個目標檔案的先決條件,如果這make次執行規則的命令目標檔案要 更新要假想(phony)目標不是一個真實目標的先決條件假想(phony)目標的命令有在假想(phony)目標作為特目 標時才會執行參閱指定最終目標的參數)。 假想(phony)目標也可以有先決條件。當一個目錄引入(include)多個程式時,使用假想(phony)目標可以方便的在一個 makefile檔案中述多個程式的更新。重建的最終目標預設情況下是makefile檔案的一個規則的目標,但將多個程式作 為假想(phony)目標的先決條件則可以輕鬆成在一個makefile檔案中述多個程式的更新。如下
all : prog1 prog2 prog3 .PHONY : all
prog1 : prog1.o utils.o cc -o prog1 prog1.o utils.o
prog2 : prog2.o cc -o prog2 prog2.o
prog3 : prog3.o sort.o utils.o cc -o prog3 prog3.o sort.o utils.o
,您可以重建所有程式,也可以參數的式重建其中的一個或多個(如‘make prog1 prog3')。 當一個假想(phony)目標另一個假想(phony)目標的先決條件假想(phony)目標作為一個假想(phony)目標的子例
如,這裡‘make cleanall'用刪除OBJ檔案diff檔案和程式檔案
.PHONY: cleanall cleanobj cleandiff
cleanall : cleanobj cleandiff rm program
cleanobj : rm *.o
cleandiff : rm *.diff
4.5 沒有命令或先決條件的規則
如果一個規則沒有先決條件、也沒有命令,而且這個規則的目標也不是一個在的檔案則make規則執行 ,該目標已被更新。這意著,所有以這種規則的目標為先決條件的目標的命令總被執行。這裡一個例子
clean: FORCE rm $(objects) FORCE:
這裡的目標FORCR’滿足上面的特殊條件以以其為先決條件的目標clean’將總強製它的命令執行於 ‘FORCR’的名字沒有特的要,但‘FORCR’是使用的名字
也許您經明使用FORCR’法和使用假想(phony)目標.PHONY: clean結果一樣,但使用假想(phony)目
標更具體更靈活,由於的版本的make支援假想(phony)目標以‘FORCR’出現下許多makefile檔案中 參閱假想(phony)目標
4.6使用空目標檔案記錄事件
空目標一個假想(phony)目標變數它用控制一命令的執行,這些命令來完成一些經要的具體任務。但 真正的假想(phony)目標它的目標檔案可以實存在,但檔案的內容與無關通常情況下,這些檔案沒有內
空目標檔案的用記錄規則的命令最後一次執行的時間,也是空目標檔案最後更時間。以能夠這樣 執行是因為規則的命令中有一條用更新目標檔案的touch命令外,空目標檔案有一先決條件(否則空目 標檔案沒有在的)。如果空目標比它的先決條件舊,當您命令重建空目標檔案時,有關的命令才會執行。下面有 一個例子
print: foo.c bar.c lpr -p $? touch print
按照這個規則,如果任何一個檔案從上次執行make print'以來發生變化,鍵make print'則執行lpr命令自動變數$?來列那些發生變化的檔案參閱自動變數)。
4.7 內建的特殊目標名
名字作為目標使用則含有特殊的 .PHONY 特殊目標.PHONY的先決條件假想(phony)目標假想(phony)目標是這樣一目標make條件的執行它命令
目錄下是否存檔案它最後一次更新的時間沒有關係。詳細內容參閱假想(phony)目標
.SUFFIXES 特殊目標.SUFFIXES的先決條件後置規則(suffix rule)的後置。詳細內容參閱舊式的後置規則(suffix
rule)
.DEFAULT .DEFAULT指定一命令,這些命令用於那些沒有找到規則具體規則或隱含規則更新的目標。詳細內容參閱定
義最新類型的-預設規則。如果.DEFAULT指定命令則所有的檔案作為先決條件,而不能作為規則的目標;這些指定的命令按照的模式執行。詳細內容參閱隱含規則搜尋算法
.PRECIOUS 特殊目標.PRECIOUS的先決條件將按照下面給定的特殊模式進行處理︰如果在執行這些目標的命令的過程中
make關閉或中斷,這些目標不能刪除,詳細內容參閱關閉和中斷make;如果目標檔案,即使它沒 有任何也不能刪除具體情況目標成一樣參閱隱含規則鏈;該目標的其它和特殊目標 .SECONDARY。如果規則的目標樣式與先決條件的檔案名匹配,您可以使用隱含規則的格式(如‘ %.O’)列目標作為特殊目標.PRECIOUS的先決條件檔案存由這些規則建的中檔案
.INTERMEDIATE 特殊目標.INTERMEDIATE的先決條件處理為中檔案。詳細內容參見隱含規則鏈.INTERMEDIATE如果沒有先
決條件檔案將不會發生作用
.SECONDARY 特殊目標.SECONDARY的先決條件處理為中檔案,但永遠不能自動刪除。詳細內容參見隱含規則鏈
.SECONDARY如果沒有先決條件檔案則所有的makefile檔案中的目標都將處理為中檔案
.DELETE_ON_ERROR 如果在makefile檔案的處.DELETE_ON_ERROR作為一個目標如果該規則生變化或它的命令沒有
確完退出,make將會刪除規則的目標具體行為和它到了刪除號一樣。詳細內容參閱命令錯誤
.IGNORE 如果您為目標.IGNORE指先決條件則MAKE將會處理這些先決條件檔案執行命令生的錯誤。如果
.IGNORE作為一個沒有先決條件的目標提出來,MAKE將忽處理所有檔案時產生的錯誤.IGNORE命令並沒有特的含義.IGNORE的用僅是期版本的。因為.IGNORE影響所有的命令它的用途不大;我們 使用其它來忽特定命令生的錯誤。詳細內容參閱命令錯誤
.SILENT 如果您為.SILENT指先決條件則在執行之前MAKE將不會回顯重新構造檔案的命令。如果.SILENT作為一個
沒有先決條件的目標提出來,任何命令在執行之前都不會列.SILENT並沒有特的含義其用僅是 期版本的。我們推您使用其它方法來處理那些不列印的命令。詳細內容參閱命令回顯。如果您希望所有的命都不列,請使用-s-silent選項(詳細參閱選項概要)
.EXPORT_ALL_VARIABLES 如該特殊目標簡單的作為一個目標MAKE預設地把所有變數子進程中參閱使與子MAKE通
的變數
.NOTPARALLEL
如果.NOTPARALLEL作為一個目標,即使給出‘-j選項make也不使用並行執行。但遞迴的make命令並行執 在呼叫的makefile檔案中引入(include).NOTPARALLEL的目標的例外)。.NOTPARALLEL的任何先決條件都將略。
任何定義的隱含規則後置如果作為目標出現都會為一個特殊規則,即使兩個後置串來也是如如‘.c.o’。 這些目標為後置規則(suffix rule),這種定義舊式的定義隱含規則的廣泛使用的)。原上 ,如果您它分為兩個並後置單中,任何目標名都可法指定。實上,後置一般以‘.’開
,因,這些特的目標以‘.’開。具體參閱舊式的後置規則(suffix rule)
4.8 具有多個目標的規則
具有多個目標的規則同於寫多條規則,這些規則除目標不同之外,完全相同。相同的命令所有目 標,但命令執行的結果可能有所差異,因您可以在命令中使用$@’發不同目標名稱。這條規則
所有的目標有相同的先決條件
以下兩種情況下具有多個目標的規則相當有用
您僅僅需要,但不需要任何命令如︰ kbd.o command.o files.o: command.h
為三提及的目標檔案給出附加的先決條件
所有的目標使用相同的命令命令的執行結果未必完全相同,因為自動變數‘$@’可以在重建指定目標
閱自動變數)。如︰
bigoutput littleoutput : text.g generate text.g -$(subst output,,$@) > $@
同於︰
bigoutput : text.g generate text.g -big > bigoutput littleoutput : text.g generate text.g -little > littleoutput
這裡我們假設程式可以產生兩種輸出檔案類型一種給出‘-big’,另一種給出‘-little’。參閱字元串代替和分析函數 ,對函數subst的解釋。 如果您喜歡根據目標變換先決條件使用變數$@’變換命令一樣。您不必使用具有多個目標的規則,您可以使用
靜態樣式規則。詳細內容見
4.9 具有多條規則的目標
一個目標檔案可以有多個規則。在所有規則中的先決條件都將在一個目標的先決條件單中。如果該目標比
任何一個先決條件’,所有的命令執行重建目標。 但如果一條以上的規則對同一檔案給出多條命令make使用最後給出的規則,同時列錯誤訊。(作為特例,如 果檔案名以點‘.’開,不列錯訊。這古怪的行為僅僅是和其它版本的make)。您沒有樣編寫的makefile檔案,這正是make給您發出錯誤訊原因。
一條特的先決條件規則可以來立即給多條目標檔案提供的先決條件例如,使用名為objects的變數變數系統產生的所有輸出檔案。如果‘congfig.h’發生變化所有的輸出檔案必須重新編譯,可以下列
單的法編寫
objects = foo.o bar.o foo.o : defs.h bar.o : defs.h test.h $(objects) : config.h
這些可以入或取出而不影響指定的目標檔案生成規則,如果您希望斷斷續續的為目標加先決條件,這是便
一個加先決條件的定義一個變數將該變數作為make命令的參數使用。詳細內容參閱變數重載
如︰
extradeps= $(objects) : $(extradeps)
命令`make extradeps=foo.h'含義是將‘foo.h作為所有OBJ檔案的先決條件,如果僅僅輸make命令則不是這 如果沒有具體的規則為目標的生成指定命令,那麼make搜尋合適的隱含規則進而確定一命令來完成生成或重建目 標。詳細內容參閱使用隱含規則
4.10 靜態樣式規則Static Pattern Rules
靜態樣式規則指定多個目標並能夠根據每個目標名構造對應的先決條件名的規則靜態樣式規則在用多個目標
常的規則更常用,因為目標可以不必完全相同的先決條件;也就是說,這些目標的先決條件必須,但不必 完全相同。
4.10.1 靜態樣式規則的語法
這裡是靜態樣式規則的語法格式
targets ...
: target-pattern: dep-patterns ... commands ...
目標單指明該規則用的目標目標可以含有萬用字元具體使用和常的目標規則基本一樣參閱在檔案名中使 用萬用字元)。 目標的格式和先決條件的格式是說明如何個目標先決條件的。從匹配目標樣式的目標名中依據格式 分字元串,這部分字元串為俓(stem)。將俓(stem)分發到每一個先決條件格式中生先決條件名
一個格式通常含字符‘%’。目標樣式匹配目標時,‘%’可以匹配目標名中的任何字元串;這部分匹配的字元串為俓(stem)必須完全相同。如目標foo.o匹配樣式%.o’,字元串foo’稱為俓(stem)。而目標foo.cfoo.out’不匹配樣式
個目標的先決條件名使用俓(stem)代替個先決條件中的%’產。如,如果一個先決條件格式為%.c’,把
(stem)foo代替先決條件格式中的%生成先決條件的檔案名foo.c’。在先決條件格式中%’也是合法 的時對所有目標來說,先決條件是相同
在樣式規則中字符‘%’可以前面反斜線(\)\’方法引用引用%反斜線(\)也可以由更多的反斜線(\)引用 引用%’、‘\’的反斜線(\)在和檔案名俓(stem)代替它之前從格式中移走反斜線(\)不會因為引用‘%’而
亂。如,格式`the\%weird\\%pattern\\'`the%weird\' 加符‘%',和字元串 pattern\\'連接最後的兩個反斜線(\) 由於不能影響任何統符‘%以保
這裡有一個例子將對應.c檔案編譯成foo.obar.o’。
objects = foo.o bar.o all: $(objects) $(objects): %.o: %.c $(CC) -c $(CFLAGS) $< -o $@
這裡‘
$<’是自動變數控制先決條件的名稱,‘$@’也是自動變數掌握目標的名稱
。詳細內容參閱自動變數
一個指定目標必須和目標樣式匹配,如果不符告。如果您有一檔案,僅有其中的一分和樣式匹配,您 可以使用filter函數把不符合的檔案移走參閱字元串替代和分析函數)︰
files = foo.elc bar.o lose.o
$(filter %.o,$(files)): %.o: %.c $(CC) -c $(CFLAGS) $< -o $@ $(filter %.elc,$(files)): %.elc: %.el
emacs -f batch-byte-compile $<
個例子中,‘$(filter %.o,$(files))'的結果是‘bar.o lose.o',第一個靜態樣式規則是將相應的C語言源檔案編譯更新為 OBJ檔案,‘$(filter %.elc,$(files))' 的結果是‘foo.elc'由‘foo.el構造 另一個例子怎樣在靜態樣式規則中使用$*’︰
bigoutput littleoutput : %output : text.g generate text.g -$* > $@
命令generate執行時,$*展開為俓(stem),即‘biglittle者之
4.10.2靜態樣式規則和隱含規則
靜態樣式規則和定義為樣式規則的隱含規則有相同地方(詳細參閱定義與重新定義樣式規則)。方都目 標的格式和構造先決條件名的格式差異make使用它時機不同。
隱含規則可以應於任何於它匹配的目標,但僅僅是在目標沒有具體規則指定命令先決條件可以搜尋
況下應。如果有多條隱含規則適合,僅有執行其中一條規則依據隱含規則的定義次序。 相靜態樣式規則用在規則中指的目標不能應其它任何目標它的使用模式對於各個目標固定變的。如果使用兩個有命令的規則衝突錯誤
靜態樣式規則如下原因可能比隱含規則更 文件名不能按句法分類的但可以給出列表的文件使用靜態樣式規則可以重載隱含規則鏈
如果不能精確確定使用的路俓(stem),您不能確定一些無關要的文件是否導致make使用錯誤的隱含規則(因為
隱含規則的選根據其定義次序使用靜態樣式規則則沒有這些不確︰每一條規則都精確的用指定的 目標上。
4.11雙冒號規則(::)
雙冒號規則(::)在目標名後使用‘︰︰’代替‘︰’的規則。當同一個目標在一條以上的規則中出現時,雙冒號規則(:
:)和常的規則處理有所差異
一目標在多條規則中出現時,所有的規則必須是同一類型么都是雙冒號規則(::)么都是普通規則。如果們 都是雙冒號規則(::)則它們之間都是相互。如果目標一個雙冒號規則(::)的先決條件’,雙冒號規則(:
:)的命令執行。這可導致具有一目標雙冒號規則(::)全部或部分執行。
雙冒號規則(::)就是將具有相同目標的多條規則相互分離,每一條雙冒號規則(::)立的執行,就這些規則的目不同一樣
對於一個目標的雙冒號規則(::)按照在makefile檔案中出現序執行。然而雙冒號規則(::)真正義的合是雙冒 號規則(::)和執行關的合。
雙冒號規則(::)有糊難解,僅僅提供了一種在特定情況下根據更新的先決條件檔案不同,而不同模 式更新目標的。實用雙冒號規則(::)的情況 一個雙冒號規則(::)都應該指定命令,如果沒有指定命令使用隱含規則。詳細內容參閱使用隱含規則
4.12 自動生成先決條件
在為一個程式編寫的makefile檔案中常常要寫僅僅是說明些OBJ檔案依靠頭檔案的規則如,如果 main.c透過一條#include語句使用defs.h’,您需要寫入的規則
main.o: defs.h
您需條規則讓make如果‘defs.h旦改必須重新構造main.o’。由您可以明對於一個的程式您需 要在makefile檔案中寫樣的規則。而且加或一條#include語句您必須十小心地makefile檔案 為避免煩惱,現代C編譯器根據原程式中的#include語句可以編寫這些規則。如果需要使用這種能,通常可在 編譯程式加入-M’開
如,下面的命令
cc -M main.c
如下輸出︰
main.o : main.c defs.h
您就不必自寫這些規則編譯器可以您完這些工作。 注意,由於在makefile檔案中及構造main.o’,因main.o’將永遠不會隱含規則檔案進行搜尋 ,這同時意make不會在使用它後自動刪除它參閱隱含規則鏈
對於舊版的make程式過一個命令,如‘make depend’,利用編譯的特生成先決條件慣。這些 命令將產生一個depend檔案,該檔案引入(include)所有自動生成的先決條件;然後makefile檔案可以使用include命令讀入參閱引入(include)其它makefile檔案)。
在GNU make中重新構造makefile檔案的特使例成為舊式的東西──永遠不必具體告訴make重新生成先 決條件,因為GNU make重新構造任何舊式的makefile檔案參閱Makefile檔案的重新生成的過程
我們使用自動生成先決條件的慣是把makefile檔案和程式檔案一一對應來。如,對每一個程式檔案name.c有一名為name.d的makefile檔案和它對應,該makefile檔案中列出了名為name.oOBJ檔案所先決條件
的檔案。這種模式的優點是僅程式檔案變的情況下才要重新掃描生成新的先決條件
這裡有一個根據C語言源程式name.c生成名為name.d先決條件檔案的樣式規則
%.d: %.c set -e; $(CC) -M $(CPPFLAGS) $< \ | sed 's/\($*\)\.o[ :]*/\1.o $@ : /g' > $@; \ [ -s $@ ] || rm -f $@
定義樣式規則的訊參閱定義與重新定義樣式規則。‘-e’開關是告訴shell如果$(CC)命令執行零狀態退
)立即退出。正情況下,shell退出時有最後一個命令在管中的狀態sed,make不能注意到編譯器產生的狀態
對於GNU C編譯器您可以使用-MM’開關代替-M’,這是略了有關係統頭檔案的先決條件。詳細內容參閱《GNU CC使用手冊中控制預處理選項 命令Sed的作用是翻
如)︰
main.o : main.c defs.h
到︰
main.o main.d : main.c defs.h
使一個.d檔案和與之對應.o檔案依靠相同程式檔案和檔案,據Make可以知如果任一個 程式檔案和檔案生變化必須重新構造先決條件檔案旦您定義重新構造.d檔案的規則,您可以使用使用include命令讀入,(參閱引入(include)其它 makefile檔案),
如︰
sources = foo.c bar.c include $(sources:.c=.d)
(這個例子中使用一個代替變數參照從源程式檔案foo.c bar.c'先決條件檔案foo.d bar.d'。詳細內容參 閱替換引用。)以,‘.d的makefile檔案和其它makefile檔案一樣,即使沒用任何進一的指令make要的候重新建它們。參閱Makefile檔案的重新生成過程
5在規則中使用命令
規則中的命令系列shell命令行一條一條的序執行一條命令行可以分號為 在目標-先決條件行後面外,所有的命令行必須以TAB。空行與在命令行中間出現,處理被忽略。 (但是必須注意,以TAB始的’不是空命令參閱使用空命令。)使用多種不同的shell程式,如果在makefile檔案中沒有指其它的shell則使用預設的/bin/sh’解釋makefile檔案 中的命令參閱命令執行 使用的shell種類決定了是否能夠在命令行釋以編寫使用的語法。當使用‘/bin/sh’作為shell,以‘#’開直延到該。‘#’不必在行首,而且‘#’不是的一
5.1 命令回顯
情況下make在執行命令之前首命令行,我們因這可將您編寫的命令輸出為回顯。 以‘@’起始的行不能回顯,‘@’輸給shell被丟棄型的情況,您可以在makefile檔案中使用一個僅僅用於列 印某內容的命令,如echo命令makefile檔案執行的進程
@echo About to make distribution files
使用make時給出‘-n‘--just-print’標誌僅僅回顯命令而不執行命令參閱選項概要。在這種情況下也有在情況下,所有的命令行回顯,即使以‘@’開的命令行回顯。這個標誌對於使用命令的情況下發現make哪些是必要的命令常有用。 ‘-s--silent標誌可以使make阻止所有命令回顯好像所有的行都以‘@’開一樣在makefile檔案中使用不
先決條件的特目標.SILENT的規則可以達到相同果(參閱內建的特殊目標名)。因‘@’使用更加靈活於現下基本使用特目標.SILENT
5.2執行命令
要執行命令更新目標時,每一命令行都會使用一個獨的子shell環境,保證該命令行得到執行。(實上,make可能影響結果俓(stem)。)
請注意︰這意設定變數的shell命令cd將不影響緊跟的命令行;如果您需要使用cd命令影響到下一個命 令,請把這兩個命令一行用分號開,這樣make將認為它們是一個單一的命令行,把起傳shell,然序執行它們。如︰
foo : bar/lose cd bar; gobble lose > ../foo
如果您喜歡一個單一的命令分成多個文字(text)行,您必須反斜線(\)作為一行的最後一行除外。這 多個文字(text)行過刪除反斜線(\)成一新行,然shell。如,下面的例子和前面的例子是同的
foo : bar/lose cd bar; \ gobble lose > ../foo
用作shell的程式是由變數SHELL指定預設情況下,使用程式/bin/sh作為shell 在MS_DOS執行,如果變數SHELL沒有指定變數COMSPEC的值用代替指定shell 在MS_DOS執行和在其它系統上執行,對於makefile檔案中設定變數SHELL的行的處理也不一樣。因為MS_DOS的 shell,‘command.com’,能十分有限,以許多make用向於安裝一個代替的shell。因在MS_DOS執行 make測變數SHELL的值根據它指定的Unix風格或DOS風格的shell變化它的行為。即使使用變數SHELL指
command.com’ ,make依然測變數SHELL的值。 如果變數SHELL指定Unix風格的shell在MS_DOS執行的make附加指定的shell是否能真正找到;如果不能找到 ,指定的shell在MS_DOS上,GNU make按照下步驟搜尋shell: 1在變數SHELL指定的目錄中如,如果makefile指`SHELL = /bin/sh'make當前路俓(stem)子目錄/bin’。
2當前路俓(stem)下。 3、按序搜尋變數PATH指定的目錄
在所有搜尋的目錄中make先尋指定的檔案(如例子中的sh’)。如果該檔案沒有存在,make將在上述目錄中搜
尋帶有定的執行檔案展開的檔案如︰‘.exe', .com', .bat', .btm', .sh'檔案和其它檔案等
如果上述過程中能夠搜尋一個shell則變數SHELL的值設定為所發現shell的路俓(stem)檔案名。然而如果上 力全部失變數SHELL的值將不改設定shell的行的有性將被忽略。這是在make執行的系統如果確實安裝了 Unix風格的shellmake支援的Unix風格shell特原因。 注意這shell的展開搜尋僅僅限制在makefile檔案中設定變數SHELL的情況。如果在環境或命令行中設定,希望您 定shell的路俓(stem)檔案名,而且全路俓(stem)檔案名在Unix系統中執行的一樣準確無
述的DOS特色的處理,而且您把 ‘sh.exe’安裝在變數PATH指定的目錄中或在makefile檔案內設定 `SHELL = /bin/sh' 和多數Unix的makefile檔案一樣),則在MS_DOS的執行效果和在Unix執行完全一樣。 不其它多數變數變數SHELL從不根據環境設定。這是因為環境變數SHELL指定使用的shell 程式。如果變數SHELL在環境中設定影響makefile檔案的功能,這是算的參閱環境變數。然而在MS- DOS和MS-WINDOWS中在環境中設定變數SHELL的值要使用的,因為在這些系統多數用設定變數
的值make可能變數指定要使用的值。在MS-DOS上,如果變數SHELL的設定對於make不合適,您可以 設定變數MAKESHELL用指定make使用的shell;這種設定使變數SHELL的值
5.3 並行執行
GNU make可以同時執行條命令。正常情況下,make一次執行一個命令,待它完成後在執行下一條命令。然而,使用 -j--jobs選項將告訴make同時執行多條命令在MS-DOS上,‘-j選項沒有作用,因該系統不支援多進程 處理
如果‘-j’選項後面跟一個整數,該整數表示一次執行的命令的條數;這稱為job slots數。如果‘-j’選項後面沒有數 ,也就是沒有對job slots的數目限制。預設的job slots數是一,這意著按序執行(一次執行一條命令)。同時執行多條 命令的一個不理想的結果是每條命令產生的輸出與每條命令發的時間對應,即命令產生的回顯可能混亂
另一個問題兩個進程不能使用一設以必須確定一次有一條命令make能保證正在執 行的命令的標準輸其它的標準輸將失。這意著如果同時從準輸入設入的話,對於 多數子進程將產命的錯誤(即產生一個Broken pipe信號)。
命令一個有的標準輸入或為make的標準輸入設是不可預測的。第一條執 行的命令是第一個得到準輸成一條命令後一條動的另一條命令將得到下一個標準輸等等
如果我們找到一個更替換,我們將改變make的種工作模式間,如果您使用並行處理的特點,您不應 該使用任何需要標準輸入的命令。如果您不使用點,任何需要標準輸入的命令將都能正常工作最後make的遞迴也導致出現問題詳細的內容參閱與子make通訊的選項。 如果一個命令一個號中退出),且該條命令生的錯誤不能略(參閱命令錯誤),剩餘 一目標的命令行將會停止工作。如果一條命令,而且‘-k--keep-going選項沒有給出(參閱選項概要 ),make放棄繼續執行。如果make由於原因(包括信要中子進程在執行到這些子進 再實際退出。 當系統正滿負荷執行時,您許希望負荷再添任務。這時,您可以使用‘-|選項告訴make根據平均負荷
執行的任務。‘-|--max-load選項一一個如︰
-| 2.5 將不make在平均負荷高2.5啟動一項任務。‘-|選項如果沒有據,則取前面‘-|’給定的負荷精確地,當make動一項任務時,而至少一項任務正在執行則它查當前平均負荷;如果不 於‘-|’選項定的負荷時,make平均負荷於限制或所有其它任務完成後啟動其它任務。 預設情況下沒有負荷
5.4命令錯誤
一個shell命令回後make查該命令退的狀態。如果該命令成地完成,下一個命令行就會在新的子shell環境 中執行,當最後一個命令行成後,這條規則告完。如果出現錯誤退狀態), make放棄當前的規則 ,也許是所有的規則一個特定的命令不是出現了問題如︰您可能使用mkdir命令建一個目錄,如果該目錄經存 mkdir將報告錯誤,但您時也許要make繼續執行
一個命令執行生的錯誤,請使用字符‘-’(化TAB的後面)作為命令行的。字符‘-在命令shell執行丟棄如︰
clean:
-rm -f *.o
條命令使在不能刪除一個檔案時也強製rm繼續執行 在執行make使用-i--ignore-errors選項,將會所有規則的命令執行生的錯誤在makefile檔案中使用 沒有先決條件的特殊目標.IGNORE規則,也具有樣的果。但因為使用字符‘-靈活以該條規則很少 使用
使用--i選項執行命令時產生的錯誤被忽略,make處理成執行的命令一樣處理具有回錯誤 的命令不同地方是列一條,告訴您命令退出時的編狀態說明該錯誤被忽略。如果發生錯誤
make並不說明被忽略,示當前的目標不能重新構造和它關或關的目標不能重建 。因一個過程沒有以不會進一執行的命令
情況下,make一般立即放棄任務,回一個的狀態。然而,如果指定-k--keep-goning選項make 則繼續個目標的其它先決條件,如果要在make放棄狀態之前重建它們。例如,在編譯一個OBJ檔案 生錯誤後,即使make經知所有OBJ檔案連接在一是不可能,‘make -k'選項繼續編譯其它OBJ檔案。詳細 內容參閱選項概要通常情況下,make的行為基假設的目的更新指定的目標make得知這是不可能
將立即報告失。‘-k選項是告訴make真正的目的測試程式中所有變化的性,許是找幾的問題便 您可以次編譯之前們。這是Emacs編譯命令預設情況下-k選項的原因。
通常情況下,當一個命令執行失敗時,如果經改目標檔案檔案可能發亂而不能使用或檔案至 少沒有完全得到更新。但是,檔案的時間戳卻表明該檔案更新最新,因在make次執行時,將不更新
檔案。這種狀和命令發出行關閉一樣參閱中斷或關閉make。因,如果變目標檔案後命令般應該刪除目標檔案。如果.DELETE_ON_ERROR作為目標在makefile檔案中出現,make自動做這些情。這是您 應該明確make執行的動作,不是以前問題時,您應明確提出這樣的要
5.5中斷或關閉make
如果make在一條命令執行時得到一個命的 則make將根據第一次時間戳和最後更時間戳是否發生變 化決定它是否刪除命令要更新的目標檔案 刪除目標檔案的目的是當make次執行時確保目標檔案從原檔案得到更新什麼假設在編譯檔案時您鍵入Ctrl­c,而且這時經開OBJ檔案foo.o’,Ctrl-c關閉了該編譯器,結果得到不完OBJ檔案foo.o時間戳比源 程式foo.c時間戳,如果makeCtrl-c的沒有刪除OBJ檔案foo.o’,下make更新OBJ檔案 foo.o’時,make將認檔案更新最新沒有要更新,結果在linker將OBJ檔案連接為執行檔案時產奇怪 的錯誤訊
您可以將目標檔案作為特殊目標.PRECIOUS的先決條件從而阻止make樣刪除目標檔案在重建一個目標之前,make查該目標檔案是否出現下特殊目標.PRECIOUS的先決條件單中,從而決定在時是否刪除目標檔案。 您不刪除種目標檔案的原因可能是︰目標更新一種子風格或目標檔案僅僅記錄更改時間(其內容
),或目標檔案必須防止其它類型的錯誤
5.6遞迴make
遞迴著可以在makefile檔案中make作為一個命令使用。這種技術在引入(include)系統makefile分樣的子系統時非常有用如,假設有一個子目錄subdir’,該目錄中有它自的makefile檔案,您希望子目 錄中執行make使用makefile檔案您可以按下述模式編寫
subsystem:
cd subdir && $(MAKE)
或, 同於這樣寫 (參閱選項概要):
subsystem: $(MAKE) -C subdir
您可以僅僅拷貝述例子實現make的遞迴,但您應該了解們是如何工作的什麼這樣工作,以子make和make的相互係。
使用便GNU make變數CURDIR的值設定為當前工作的路俓(stem)。如果‘-C選項有引入(include)的新路俓(stem),而不是原來的路俓(stem)。該值和它在makefile中設定的值有相同預設情況下,環境變數
CURDIR不能重載)。注意,操作make設定
5.6.1 變數MAKE的工作模式
遞迴make的命令使用變數MAKE,而不是明確的命令名make’,如下示︰
subsystem:
cd subdir && $(MAKE)
變數的值呼叫make的檔案名。如果這個檔案名是‘/bin/make’,則執行的命令`cd subdir && /bin/make'。如果您makefile檔案用特定版本的make則執行遞迴時也使用相同的版本
在命令行中使用變數MAKE可以改-t' (--touch'), -n' (--just-print'), 或 -q' (--question')選項的效果。如果在使用 變數MAKE的命令行使用字符‘+’也會起到相同的作用參閱代替執行命令 設想一述例子中命令make -t的執行過程。(‘-t選項標誌目標已更新,但卻不執行任何命令參閱代替 執行命令。)按照通常的定義,命令‘make t’在上例中僅僅建立名為‘subsystem’的檔案而不進行別的工作。您實際 要求執行cd subdir && make t’干什麼?是執行命令或是按照‘-t的要求執行命令? Make的個特點是這樣的︰只要命令行中引入(include)變數MAKE標誌`-t', `-n' 和 `-q'將不對本行起作用。雖然存在標誌
讓命令執行,但引入(include)變數MAKE的命令行卻正常執行make上是過變數MAKEFLAGS標誌值給 了子make參閱與子make通訊的選項)。以您驗証檔案、列命令的求等都能系統。
5.6.2與子make通訊的變數
過明確,上make變數的值可以環境遞給子make,這些變數在子make中預設定義您不使用-e關的情況下,遞的變數的值不能代替子make使用的makefile檔案中指定的值參閱命令概要)。 向下或輸出一個變數時,make將該變數以它的值加到執行每一條命令的環境中。子make,作為附應,使用該
環境化它的變數值表。參閱環境變數
了明確指定外,make僅向下輸出在環境中定義並化的或在命令行中設定的變數,而且這些變數的變數名必須僅 數字和線組。一些shell不能處理名字中含有字、數字和以外的環境變數。特殊變數SHELL 和MAKEFLAGS一向下輸出(您不輸出們)。即使您把變數MAKEFILE設為其它的值也向下輸出。 Make自動遞在命令行中定義的變數的值是將入MAKEFLAGS變數中。詳細內容參閱下節。Make預設
的變數的值不能向下遞,子make可以定義它們。如果您指定變數輸出給子make,請用export指令格式 下︰
export variable ...
阻止一變數輸出給子make,請用unexport指令格式如下︰ unexport variable ...
便起,您可以同時定義並輸出一個變數 export variable = value
下面的格式具有相同:
variable = value
export variable export variable := value 具有相同果︰
variable := value
export variable
同樣, export variable += value 同樣:
variable += value
export variable 參閱為變數值附加文字(text)
您可能注意到export和unexport指令在make與shell中的工作模式相同,如sh。 如果您所有的變數都輸出,您可以使用export
export 這告訴make export和unexport沒有及的變數統統輸出,但任何在unexport及的變數然不能輸出。如果您使用 export作為預設的輸出變數模式名字中含有字數字和以外的變數將不能輸出,這些變數除您明確使 用export指令才能輸出。
使用export的行為是頭本GNU make預設定義的行為。如果您的makefile依靠這些行為,而且您希望本GNU make,您可以為特殊目標.EXPORT_ALL_VARIABLES 編寫一條規則代替export指令本GNU make
,但如果同時使用export指令則
,您可以使用unexport告訴make預設輸出變數,因這是預設的行為前面使用export(也許
在一個包括的makefile中)您才做。您不能同時使用export和unexport指令實現對命令輸出對其它的 命令不輸出。最後的一條指令export或unexport)將決定make的全部執行結果。
作為一個特點,變數MAKELEVEL的值在一個向下層傳時發生變化。該變數的值是字符型,它用十進數表示
。‘0make,‘1子make,‘2子-子-make,以類推Make為一個命令建立一次環境加1
變數的要作用在一個條件指令中測試參閱makefile檔案的條件語句);,您可以編寫一個 makefile,如果遞迴用一種執行模式,由您控制接執行用另一種執行模式。 您可以使用變數MAKEFILES使所有的子make使用附加的makefile檔案變數MAKEFILES的值makefile檔案名的檔案名之間用空格隔開。makefile中定義變數,該變數的值過環境向下;因可以作為子make的的makefile檔案在子make讀常的或指定的makefile檔案前,將讀入參閱變數MAKEFILES
5.6.3與子make通訊的選項
諸如‘-s-k標誌過變數MAKEFLAGS自動子make。該變數make自動建立,並引入(include)make的 標誌字以,如果您是make ks變數MAKEFLAGS就得到ks’。 作為結果,任一個子make在它的執行環境中為變數MAKEFLAGS作為附應,make使用值作為標誌並進行處 理,就作為參數給出一樣參閱選項概要
在命令行中定義的變數也將變數 MAKEFLAGS傳子make變數MAKEFLAGS值中的字可以引入 (include)‘=’,make們按變數定義處理其過程和在命令行中定義的變數一樣參閱變數重載 選項`-C', `-f', `-o', 和 -W’不能放入變數MAKEFLAGS中;這些選項不能向下傳
-j選項一個特殊的例子參閱並行執行)。如果您將它設定為一數值N’,而且您的作業系統支援它(大多 數Unix系統支援其它作業系統不支援),make和所有子make通訊保證在它間同時僅N任務執行。注意 ,任何引入(include)遞迴的任務(參閱代替執行命令)不能計算在任務數內(否,我們僅能得到‘N個子make執 行,而沒有多時間執行在的工作)。
如果您的作業系統不支援述通訊,那麼‘-j 1’將變數MAKEFLAGS中代替指定的值。這是因如果‘-j 選項子make,您可能得到比您多的並行執行的任務。如果您給出‘-j’選項而沒有數字參數,意
儘可能並行處理多個任務,這向下,因數的無限多為1。 如果您不希望其它的標誌向下,您必須改變變數MAKEFLAGS的值變模式如下︰
subsystem: cd subdir && $(MAKE) MAKEFLAGS=
命令行中定義變數的上出現下變數MAKEOVERRIDES中,而且變數MAKEFLAGS引入(include)了該變數的引用值 。如果您向下遞標誌,而不向下遞命令行中定義的變數,這時,您可以將變數MAKEOVERRIDES的值設為空
格式如下︰
MAKEOVERRIDES =
不十分有用。但是,些系統對環境的大小有固定,而且該小,將這么多的訊息放變數MAKEFLAGS的 值中可能該限。如果您看到‘Arg list too long'的錯誤訊可能就是由於該問題成的。(按照嚴格的POSIX.2 的規定,如果在makefile檔案定義特殊目標.POSIX’,改變變數MAKEOVERRIDES的值並影響變數MAKEFLAGS 也許您心這些。)
期版本具有相同的變數MFLAGS也是存在的不能引入(include)命令行定義變數外,它和變 數MAKEFLAGS有相同的值,而且空值它的值是以短線MAKEFLAGS有在和多字選項一使 用時才以短線,如--warn-undefined-variables連用)。變數MFLAGS的使用在明確的遞迴make的命令中如︰
subsystem: cd subdir && $(MAKE) $(MFLAGS)
但現下,變數MAKEFLAGS使種用法變。如果您的makefile檔案和版本的make程式,請使用種模 式;這種模式在代版本make中也能很好的工作
如果您要使用次執行make要設定的特定選項如‘-k選項參閱選項概要),變數MAKEFLAGS分有用。您 可以簡單的在環境中將給變數MAKEFLAGS或在makefile檔案中設定變數MAKEFLAGS指定的附加標誌可以對
個makefile檔案作用。(注意︰您不能以這種模式使用變數MFLAGS變數MFLAGS為和期版本 用其它模式設定變數make將不解釋。)
make解釋變數MAKEFLAGS值的(不管在環境中定義或在makefile檔案中定義),如果該不以短線則 make先為值假設一個短線著將該值分成字字與字用空格開,然將這些字進行語法分析好像
在命令行中給出的選項一樣。(‘-C', -f',-h',-o',‘-W'選項以及的長名字版本都將忽略,對於無效的選項不 產生錯誤訊息。) 如果您在環境中定義變數MAKEFLAGS,您不要使用重影響make執行破壞makefile檔案的意圖以及make自的選項如‘-t', -n', 和‘-q'選項,如果將中的一個放變數MAKEFLAGS的值中,可能產災難的後果,或至少
生讓結果。
5.6.4 --print-directory選項
如果您使用make遞迴使用-w--print-directory選項過顯示每個make處理處理成的目錄使 您得到比輸出。如,如果使用make w命令在目錄/u/gnu/make中執行make則make將下面格式 輸出
make: Entering directory `/u/gnu/make'.
說明進入目錄中還沒有進行任何任務。下面的訊
make: Leaving directory `/u/gnu/make'.
說明任務經完 通常情況下,您不必具體指明這個選項,因為make您做了︰當您使用-C選項時,‘-w選項自動 在子make中也是如。如果您使用-s選項,‘-w選項不會自動開,因-s選項是不列印訊,同樣使用`
--no-print-directory'選項-w選項也不會自動開。
5.7定義固定次序命令
在建立各種目標時,相同次序的命令分有用時,您可以使用define指令定義固定次序的命令根據這些目標的規則 引用固定次序固定次序一個變數,因它的名字不能和其它的變數名衝突 下面是定義固定次序命令的例子
define run-yacc yacc $(firstword $^) mv y.tab.c $@ endef
run-yacc定義的變數的名字endef標誌定義的行命令。define指令在固定次序中不對變數引用和函數呼叫 展開;符‘$’、括號、變數名等等變成定義的變數的值的一
定義多行變數一節對指令define有詳細解釋。
例子中,對於任何使用固定次序的規則,第一個命令是對一個先決條件執行Yacc命令Yacc命令執行生 的輸出檔案一命名為y.tab.c’;第條命令,是將該輸出檔案的內容入規則的目標檔案中 在使用固定次序時,規則中命令使用的變數定的值替代,您可以替代其它變數一樣替代這些變數(詳細內容 參閱變數引用基礎)。因define指令定義的變數展開的變數在使用所有變數引用才展開。如︰
foo.c : foo.y
$(run-yacc)
固定次序run-yacc執行時,‘foo.y’將代替變數$^’,‘foo.c’將代替變數$@’。
這是一個現實的例子,但不是必要的,因為make有一條隱含規則可以根據的檔案名的類型定所用的命令
閱使用隱含規則 在命令執行時,固定次序中的一行被處理為和直接出現下規則中的命令行一樣,前面一個Tabmake特別為 一行求一個的子shell。您也可以在固定次序的一行使用影響命令行的綴字(`@', `-',和 `+')參閱在規則 中使用命令使用述的固定次序
@echo "frobnicating target $@" frob-step-1 $< -o $@-step-1 frob-step-2 $@-step-1 -o $@ endef
make將不回顯一行,但要回顯後的兩個命令行
另一方面,如果前在引用固定次序的命令行中使用該前符將應固定次序的每以行中如這個規 則
frob.out: frob.in @$(frobnicate)
將不回顯固定次序的任何命令具體內容參閱命令回顯
5.8 使用空命令
定義什麼也不干的命令有有用定義空命令可以簡單的給出一個僅僅含有空格而不含其它任何東西的命令即可。如︰
target: ; 為字元串target定義一個空命令。您也可以使用以Tab字符開始的命令行定義一個空命令,但這由於看來空
亂。
也許您奇怪什麼我們定義一個空命令?唯一的原因是阻止目標更新使用隱含規則提供的命令。 (參閱使用隱含規則定義最新類型的預設規則)也許您不存在的目標檔案定義空命令,因樣它的
先決條件可以重建。然而這不是一個,因如果目標檔案則先決條件有可能不重建使用假 想(phony)目標較好的選參閱假想(phony)目標
6 使用變數
變數在makefile中定義的名字其用代替一個文字(text)字元串,該文字(text)字元串變數的值在具體要
,這些可以代替目標先決條件命令makefile檔案中其它。(在其它版本的make中變數巨集macros)。) 在makefile檔案讀入時,除規則中的shell命令使用=定義的=右邊的變數、以使用define指令定義的變數體 時不展開外,makefile檔案其它分的變數和函數都將展開。 變數可以代替檔案遞給編譯的選項要執行的程式、查找源檔案的目錄、輸出寫入的目錄您可以文字(text)
變數名是不包括‘:',‘#',='、前導或結尾空格的任何字元串。然而變數名含字、數字以以外的其它字符的 情況應盡量避免,因為它們可能在將來被賦予特別的含義,而且對於一些shell它們也不能透過環境傳遞給子make(參
閱與子make通訊的變數)。變數名是大小敏感變數名foo', FOO', 和 Foo'代表不同的變數
使用寫字作為變數名是以前慣,但我們在makefile內使用寫字作為變數名寫字作為控制 隱含規則參數或用重載命令選項參數的變數名。參閱變數重載。
分的變數使用一個標點符號或個字作為變數名,這些變數自動變數特定的用。參閱自動變數
6.1 變數引用基礎
寫一個號後號或變數名則引用變數的值︰‘$(foo)' 和 ${foo}'都是對變數foo的有 引用。‘$種特殊作用是您在命令或檔案名中必須$$’才有單個$原因。 變數的引用可以用在上下文的任何地方︰目標、先決條件、命令大多數指令以及新變數的值等等。這裡有一個常見的 例子在程式中變數存著所有OBJ檔案的檔案名
objects = program.o foo.o utils.o program : $(objects) cc -o program $(objects)
$(objects) : defs.h
變數的引用按照格的文字(text)替換進行,這規則
foo = c prog.o : prog.$(foo) $(foo)$(foo) -$(foo) prog.$(foo)
可以編譯C語言源程式prog.c’。因為在變數分發時,變數值前面的空格被忽略,變數foo的值是‘C’。(不 要在的makefile檔案樣寫
元符號後一個字符但不是元符號、大號,符將處理為單字符的變數名。因可以使用
$x引用變數x。然而,這在使用自動變數的情況下,在其它工作中應該完全避免參閱自動變數
6.2 變數的兩個特色
在GNU make中可以使用兩種模式為變數,我們將這兩種模式為變數的兩個特色two flavors)。兩個特色的區別的定義模式和展開時的模式不同。 變數的一個特色遞迴展開型變數。這種類型的變數定義模式︰在命令行中使用=定義(參閱設定變數)或使用
define指令定義參閱定義多行變數)。變數替換對於您所指定的值字進行替換的;如果其它變數的引用
,這些引用在變數替換時(或在展開為其它字元串的過程中)才展開。這展開模式為遞迴型展開。如︰
foo = $(bar) bar = $(ugh) ugh = Huh?
all:;echo $(foo)
回顯Huh?'︰‘$(foo)’展開$(bar)’,進一展開$(ugh)’,最終展開Huh?’。 這種特色的變數其它版本make支援的變數類型缺點也點。大多數為的類型的變數的點是︰
CFLAGS = $(include_dirs) -O include_dirs = -Ifoo -Ibar
即能夠完希望成的任務︰當‘CFLAGS在命令中展開時,最終展開-Ifoo -Ibar’。其最缺點是不能 在變數後加內容,如
CFLAGS = $(CFLAGS) -O
在變數展開過程中可能導致無(實make到無就會產生錯誤訊)。 它的另一個缺點是在定義中引用的任何函數時(參閱文字(text)轉換函數變數一旦展開函數就會立即執行。這可導致 make執行變,性能且導致萬用字元與shell函數(因不能控制何時呼叫或呼叫多)產不可預測的結果。 為避免問題和遞迴展開型變數的不方便性,出現了另一個特色變數簡單展開型變數 簡單展開型變數在命令行中用‘:=定義參閱設定變數)。簡單展開型變數的值一次永遠使用,對於引用的其 它變數和函數在定義的經展開。簡單展開型變數的值就是您寫的文字(text)展開結果。因此它包含任何 其它變數的引用變數定義時就包含的值以︰
x := foo y := $(x) bar x := later
同於︰
y := foo bar x := later
引用一個簡單展開型變數時,它的值也是字替換的。這裡有一個複雜的例子,說明了‘:=’和shell函數連接用法( 參閱函數shell)。該例子也表明了變數MAKELEVEL的用法,該變數在之間生變化。(參閱與子make 通訊的變數,可變數MAKELEVEL關的訊。)
ifeq (0,${MAKELEVEL}) cur-dir := $(shell pwd) whoami := $(shell whoami) host-type := $(shell arch) MAKE := ${MAKE} host-type=${host-type} whoami=${whoami} endif
按照這法使用:=點是看述的型的‘下目錄的命令
${subdirs}:
${MAKE} cur-dir=${cur-dir}/$@ -C $@ all
簡單展開型變數為在多數程式設可以變數一樣工作,因能夠使複雜的makefile程式更具有預測 許您使用它自的值重新定義或它的值可以被一個展開函數模式處理),還允許您使用更有展開函數參閱文字(text)轉換函數)。 您可以使用簡單展開型變數控制的前導空格引入變數的值中。前導空格字在變數引用和函數呼叫被丟棄 簡單展開型變數的個特點意著您可以在一個變數的值中前導空格並在變數引用時保們。
nullstring := space := $(nullstring) # end of the line
這裡變數space的值就是一個空格釋‘# end of the line包括在這裡解。因的空格不能從變數 值中分離出去,僅一個空格樣的果(但是時相當),如果您在變數值後一個空格樣 在行的釋清楚表明您錯的意。相,如果您在變數值後要空格,您萬記要在行的 後下幾個空格釋。如︰
dir := /foo/bar # directory to put the frobs in
這裡變數dir的值是‘/foo/bar ’(四個空格),這不是預期的結果。(假設/foo/bar’是預期的值)。 另一個變數值的符是?=’,它稱為條件變數,因為它僅僅在變數沒有定義的情況下。這
明︰
FOO ?= bar
下面的語句同(參閱函數origin
ifeq ($(origin FOO), undefined) FOO = bar
endif
注意,一個變數即使是空值,它仍然已被定義,所以使用‘?=’定義無
6.3變數引用進階技術
內容介紹變數引用的進階技術
6.3.1替換引用
換引用指定的變數替換一個變數的值它的$(var:a=b)’(${var:a=b}它的含義是把變數 var的值中的一個字的a用b替換
我們說‘在一個字的’,我們a一定在一個字的出現,且a的後么是空格要么是該變數值的 ,這時的a替換值中其它地方的a替換如︰
foo := a.o b.o c.o bar := $(foo:.o=.c)
變數bar的值設為a.c b.c c.c’。參閱變數設定
替換引用使用展開函數patsubst的簡寫參閱字元串替換和分析函數)。我們提供替換引用也是使展開函數 patsubst與make的其它實現段兼容的措施 另一種替換引用使用展開函數patsubst。它的式和述的$(var:a=b)一樣,不同必須含單個%符,實這同於‘$(patsubst a,b,$(var))’。有關函數patsubst展開述參閱字元串替換和分析函數。例如︰
foo := a.o b.o c.o bar := $(foo:%.o=%.c)
值變數bar'的值為a.c b.c c.c'
6.3.2巢狀變數引用算的變數名
巢狀變數引用算的變數名)是一個複雜的概,僅僅複雜的makefile程式中使用多數情況您不必考們,僅僅知名字中含有元標誌的變數可能特的結果就夠了。然而,如果您是您實們如何工作有興趣,請認真閱讀以下內容 變數可以在它的名字中引用其它變數,這稱為巢狀變數引用算的變數名)。如︰
x = y y = z a := $($(x)) 定義a為z’︰‘$(x)$($(x))展開y’,因$($(x))’展開$(y)’,最終展開z’。這裡對引 用的變數名的明確;根據‘$(x)展開進行引用$(x)’是巢狀在變數引用中的 一個例子表明了巢狀,但是任何層次數目的巢狀都是如,這裡有一個三層巢狀的例子
x = y y = z z = u a := $($($(x))) 這裡裡面$(x) 展開y’,因$($(x))’展開$(y)’,‘$(y) 展開z’,最終展開u’。 在一個變數名中引用遞迴展開型變數通常的風格展開。如︰
x = $(y) y = z z = Hello a := $($(x)) 定義的a是‘Hello’︰‘$($(x))’展開$($(y))’,‘$($(y))變為$(z)’, $(z)最終展開Hello’。 巢狀變數引用和其它引用一樣也可以修改引用和函數呼叫參閱文字(text)轉換函數)。如,使用函數subst參 閱字元串替換和分析函數)︰ x = variable1 variable2 := Hello
y = $(subst 1,2,$(x)) z = y a := $($($(z))) 定義的a是‘Hello’。任何人也不會寫像這樣令人解的巢狀引用程式,但它確實可以工作︰‘$($($(z)))’ 展開為‘$($ (y))’,‘$($(y))變為‘$(subst 1,2,$(x))’。變數x’得到variable1’,變換替換為variable2’,以整個字 元串變為‘$( variable2)’,一個簡單的變數引用它的值為Hello’。 巢狀變數引用不都是簡單的變數引用可以包含好個變數引用,同也可包含一固定文字(text)如,
a_dirs := dira dirb 1_dirs := dir1 dir2
a_files := filea fileb 1_files := file1 file2
ifeq "$(use_a)" "yes" a1 := a else a1 := 1 endif
ifeq "$(use_dirs)" "yes" df := dirs else df := files endif
dirs := $($(a1)_$(df)) 根據設定的use_a和use_dirs的可以將dirs相同的值分別賦a_dirs, 1_dirs, a_files 或 1_files
巢狀變數引用也可以替換引用 a_objects := a.o b.o c.o 1_objects := 1.o 2.o 3.o
sources := $($(a1)_objects:.o=.c) 根據a1的值定義的sources可以是`a.c b.c c.c' 或 `1.c 2.c 3.c' 使用巢狀變數引用一的們不能分指定要呼叫的函數名,這是因為用識別函數名的測試在巢狀變數引 用展開之前完如︰ ifdef do_sort func := sort else func := strip endif
bar := a d b g q c
foo := $($(func) $(bar)) 則變數foo的值sort a d b g q c' 或 strip a d b g q c',而不是將‘a d b g q c作為函數sort或strip的參數。如果將來去一個錯的意。
您也可以變數值的使用巢狀變數引用或在define指令中。如︰ dir = foo $(dir)_sources := $(wildcard $(dir)/*.c) define $(dir)_print
lpr $($(dir)_sources) endef
例子定義變數dir',foo_sources', 和foo_print'。 注意︰雖然巢狀變數引用和遞迴展開型變數都是用在複雜的makefile檔案中,但二者不同(參閱變數的兩個特色)。
6.4變數取值
變數有以下幾種模式取的值 您可以在執行make為變數指定一個重載值參閱變數重載
您可以在makefile文件中指定值,即變數參閱
設置變數
或使用字定義變數參閱
定義多行變數
)。
把環境變數變為make的變數參閱環境變數。 自動變數可根據規則提供們都有簡單的慣用法,參閱
自動變數
變數可以用常量初參閱隱含規則使用的變數
6.5設定變數
在makefile檔案中設定變數編寫變數名=:=的一行即可。任何=:=的內容 變為變數的值如︰
objects = main.o foo.o bar.o utils.o
定義一個名為objects的變數變數名後的空格和緊跟=的空格被忽略。 使用=定義的變數遞迴展開型變數;以‘:=定義的變數簡單展開型變數簡單展開型變數定義可以含變數 引用,而且變數引用在定義的同時就立即展開。參閱變數的兩種特色 變數名中也可以含變數引用和函數呼叫行讀入時展開,這可以出能夠實使用的變數名 變數值的長度沒有,但限於中的換空間。當定義一個變數時,在合適的地方插入反斜線(\),把變 數值分為多個文字(text)行是不錯的選。這不影響make的能,但可使makefile檔案更加
多數變數如果您不為它設定值空字元串自動作為它的。雖然變數有內建的空的初化值,但您可
時按照通常的模式為它參閱隱含規則使用的變數。)變數可根據規則自動設定新值
自動變數參閱自動變數
如果您喜歡僅對沒有定義過的變數,您可以使用符‘?=代替=’。下面兩種設定變數的模式完全同(
參閱函數origin)︰
FOO ?= bar
ifeq ($(origin FOO), undefined) FOO = bar endif
6.6 為變數值附加文字(text)
過的變數的值加更多的文字(text)一般比有用。您可以行中使用+=’來實現上述設想。如︰
objects += another.o
為變數objects的值文字(text)another.o’(前面有一個前導空格)。這
objects = main.o foo.o bar.o utils.o objects += another.o
變數objects 設定為main.o foo.o bar.o utils.o another.o' 使用 `+=' 相同於:
objects = main.o foo.o bar.o utils.o objects := $(objects) another.o
對於使用複雜的變數值,不同方法的差別非常重要。如變數在以前沒有定義過+=的作用和=’相同︰它定義 一個遞迴型變數。然而如果以前有定義,‘+=的作用先決條件於您原定義的變數的特色,詳細內容參閱變數的 兩種特色 當您使用+=為變數值附加文字(text)時,make的作用好像定義變數時就引入(include)了您加的文字 (text)。如果開使用:=定義一個簡單展開型變數+=’對該簡單展開型變數值附加文字(text)變數 新的文字(text)值展開,好像在始定義時就將附加文字(text)定義一樣,詳細內容參閱設定變數。實上,
variable := value variable += more
同於︰
variable := value variable := $(variable) more
另一方面,當您把‘+=次使用無符=定義的遞迴型變數一使用時,make的執行模式有所差異。在 用遞迴型變數時,make並不立即在變數引用和函數呼叫時展開您設定的值;而是將來,將變數引用和函 數呼叫來,以展開。當您對於一個遞迴型變數使用+=’時,相當於對一個不展開的文字(text)加新 文字(text)
variable = value variable += more
同於︰
temp = value variable = $(temp) more
當然,您從沒有定義過叫temp的變數,如您定義變數時,變數值中引入(include)變數引用時可以更為深使用不同模式定義的的重要性。下面常見的例子
CFLAGS = $(includes) -O ...
CFLAGS += -pg # enable profiling
一行定義變數CFLAGS,而且變數CFLAGS引用其它變數includes。(變數CFLAGS用C編譯的規則參閱隱 含規則目錄。)由於定義使用=’,變數CFLAGS遞迴型變數,意著‘$(includes) -O’在make處理變數 CFLAGS定義時是不展開
也就是變數includes在生之前不必定義僅需要在任何引用變數CFLAGS之前定義
。如果我們使用+=為變數CFLAGS附加文字(text),我們可能按下述模式
CFLAGS := $(CFLAGS) -pg # enable profiling
似乎很好,但結果不是我們希望使用:=重新定義變數CFLAGS為簡單展開型變數,意make在設定變 數CFLAGS之前展開了‘$(CFLAGS) -pg’。
如果變數includes沒有定義,我們將得到‘-0 -pg
’,且以變數 includes的定義也不會效。相使用+= 設定變數CFLAGS我們得到沒有展開$(CFLAGS) 0 -pg’,這 了對變數includes的引用在後一個地方如果變數includes得到定義,‘$(CFLAGS)然可以使用它的值
6.7 撤銷(override)指令
如果一個變數設定使用命令參數參閱變數重載),那麼在makefile檔案中通常的對該變數不會時對 該變數進行設定,您需要使用撤銷(override)指令其格式如下︰
override variable = value
override variable := value
變數加更多的文字(text)使用
override variable += more text
參閱為變數值附加文字(text) 撤銷(override)指令不是makefile和命令參數衝突,而是希望用它您可以改變和哪些設定使用命令參數 的變數的值
如,假設在執行C編譯器時使用-g’開,但您像往常一樣使用命令參數指定其它,您就可以 使用撤銷(override)指令:
override CFLAGS += -g
您也可以在define指令中使用撤銷(override)指令,下面的例子也許就是您想要得︰
override define foo bar endef
define指令的訊參閱下節。
6.8定義多行變數
設定變數值的另一種使用define指令。這個指令有一個特殊的用法,可以定義含多行字符的變數。這使得定義 命令的固定次序便參閱定義固定次序命令)。 在define指令一行的後般是變數名,當然,也可以什麼也沒有變數的值由下面給出,值的由僅僅 含 endef 的一行標示出。了上述在語法不同之外,define指令=一樣工作它建立了一個遞迴型變數參閱 變數的兩個特色)。變數的名字可以包括函數呼叫和變數引用在指令讀入時展開,以便能夠出實的變數 名
define two-lines echo foo echo $(bar) endef
變數的值在通常的值語句中在一行中,但在define指令中在define指令行後endef行之前所有的行都是 變數值的一最後一行除外,因為標endef一行不能認變數值的一)。前面的例次能上同於︰
two-lines = echo foo; echo $(bar)
為兩命令之間用分號開,其行為兩個分的shell命令。然而,注意使用兩個分的行,意make shell兩次,每一行的子shell中執行參閱執行命令
如果您希望使用define指令的變數定義使用命令行定義的變數,您可以把define指令和撤銷(override)指令一使
override define two-lines foo $(bar) endef
參閱撤銷(override)指令
6.9 環境變數
make使用的變數可以來自make的執行環境。任何make能夠看見的環境變數在make執行時都轉變為值的 make變數。但是,在makefile檔案中變數的具體或使用有參數的命令,都可以對環境變數進行重載(如果明
使用-e標誌環境變數的值可以對makefile檔案中的值進行重載參閱選項概要,但是這使用 。)
過在環境中設定變數CFLAGS,您可以實現下多數makefile檔案中的所有C程式的編譯使用。因您知沒有makefile將該變數用其它任務,以這種使用標含義的變數是安全(但這也是不可靠makefile檔案可能設定變數CFLAGS,從而使環境中變數CFLAGS的值)。當使用遞迴的make時,make 環境中定義的變數,可以的make參閱遞迴make)。預設模式下,有環境變數或在命令行中定義的變數 才能make。您可以使用export指令遞其它變數參閱與子make通訊的變數
環境變數的其它使用模式都不使用。將makefile的執行完全依靠環境變數的設定、出makefile檔案的控制範圍,這是不明,因不同的用執行一個makefile檔案有可能得出不同結果。這和大部分makefile檔案的意
違背
變數SHELL在環境中指定用戶對的shell的選,因使用變數SHELL也存字類的問題。這種根據選定影響make執行的模式受歡以,make環境中變數SHELL的值在MS-DOS 和 MS-Windows中執行 例外,但變數SHELL通常設定值參閱執行命令)。
6.10 特定目標變數的值
make中變數的值一般是全,無論任何地方使用的值一樣的(當然,您重新設定除外);自 動變數一個例外(參閱自動變數)。 另一個例外是特定目標變數的值,這個特許您可以根據make建目標的變化變變數的定義自動變數一樣
這些在一個目標的命令本的上下作用。 可以樣設定特定目標變數的值
target ...
: variable-assignment
target ...
: override variable-assignment
target ...含有多個目標,如則設定的特定目標變數的值在目標單中的一個目標中使用。‘variable­assignment使用任何值模式都是遞迴(‘=’)、靜態(‘:=’)、追加(‘+=’)或條件(‘?=’)。所有 出現下‘variable-assignment中的變數能夠在特定目標target ...的上下文中使用︰也就是任何以前為特定目標target ...定 義的特定目標變數的值在這些特定目標中都是。注意這種變數值和變數值相比是的值︰這兩種類型的 變數不必相同的類型遞迴vs.靜態)。 特定目標變數的值和其它makefile變數具有相同在命令行中定義的變數強製使用-e’情況下的環 境變數的值先的地位,而使用撤銷(override)指令定義的特定目標變數的值則地位。 特定目標變數的值有另一個特點︰當您定義一個特定目標變數時,該變數的值特定目標target ...的所有先決條件有 ,除這些先決條件用它的特定目標變數的值將該變數重載如︰
prog : CFLAGS = -g prog : prog.o foo.o bar.o
在目標prog的命令本中設定變數CFLAGS的值為-g’,同時在建`prog.o', `foo.o', 和 `bar.o'的命令本中變數 CFLAGS的值也是‘-g’,以及prog.o',foo.o', 和bar.o'的先決條件的建命令本中變數CFLAGS的值也是‘-g’。
6.11 特定樣式變數的值
特定目標變數的值參閱上小節)外,GNU make支援特定樣式變數的值使用特定樣式變數的值,可以為匹配 指定格式的目標定義變數在為目標定義特定目標變數後搜尋特定樣式定義的變數在為目標的目標定義的 特定目標變數前也要搜尋特定樣式定義的變數
設定特定樣式變數格式如下︰
pattern ...
: variable-assignment
pattern ...
: override variable-assignment
這裡‘pattern’是%-格式像特定目標變數的值一樣pattern ...含有多個格式,如則設定的特定樣式變 數的值在匹配單中的一個格式中的目標中使用。‘variable-assignment’使用任何賦值模式都是有的,在命令行 中定義的變數的值先的地位,而使用撤銷(override)指令定義的特定樣式變數的值則地位。如︰
%.o : CFLAGS = -O
搜尋所有匹配樣式%.o的目標它的變數CFLAGS的值設定為-0’。
7 makefile檔案的條件語句
一個條件語句可以導致根據變數的值執行或makefile檔案中一條件語句可以將一個變數與其它變數的值
相比一個變數與一字元串常相比條件語句用控制make見的makefile檔案,不能在執行控制shell命令
7.1條件語句的例子
述的條件語句的例子告訴make如果變數CC的值是‘gcc’時使用一個資料庫,如不是則使用其它資料庫過控制兩命令行一作為規則的命令工作。‘CC=gcc作為make變的參數的結果不僅決定使用一個編譯 ,而且決定連接一個資料庫
libs_for_gcc = -lgnu normal_libs =
foo: $(objects) ifeq ($(CC),gcc) $(CC) -o foo $(objects) $(libs_for_gcc) else $(CC) -o foo $(objects) $(normal_libs) endif
條件語句使用個指令ifeq、else和endif
Ifeq指令條件語句的並指條件含兩個參數號分開,號內。執行時首兩個 參數變數替換,然後進行。在makefile中在ifeq後面的行是符合條件時執行的命令;否則,它們將被忽略。
如果前面的條件else指令將導致跟在其後的命令執行述例子中,意著當第一個選項執行時, 個選項連在一的命令執行在條件語句中else指令是可使用的 Endif指令條件語句。任何條件語句必須以endif指令makefile檔案中的常內容 表明條件語句工作在準︰條件語句的行根據條件要被處理成makefile檔案的一分或要被忽略。這是 makefile檔案重的語法單位(規則)可以跨越條件語句的原因。 變數CC的值gcc,上例的
foo: $(objects) $(CC) -o foo $(objects) $(libs_for_gcc)
變數CC的值不是gcc而是其它值的,上例的
foo: $(objects) $(CC) -o foo $(objects) $(normal_libs)
相同結果也能使用另一種得︰變數的值條件化,然使用變數
libs_for_gcc = -lgnu normal_libs =
ifeq ($(CC),gcc) libs=$(libs_for_gcc) else libs=$(normal_libs) endif
foo: $(objects) $(CC) -o foo $(objects) $(libs)
7.2條件語句的語法
對於沒有else指令的條件語句的語法為
conditional-directive text-if-true
endif
text-if-true’可以是任何文字(text)行在條件為‘真’時它被makefile檔案的一;如果條件為’,將被 忽略。完的條件語句的語法為
conditional-directive
text-if-true
else
text-if-false
endif
如果條件為‘真’,使用text-if-true’;如果條件為’,使用text-if-false’。‘text-if-false’可以是任意多行的文 字(text)
於‘conditional-directive的語法對於簡單條件語句和複雜條件語句完全一樣。有不同的指令用測試不同的條件 。下面是指令表︰
ifeq (arg1, arg2) ifeq 'arg1' 'arg2' ifeq "arg1" "arg2" ifeq "arg1" 'arg2' ifeq 'arg1' "arg2"
展開參數arg1arg2中的所有變數引用,並且比它們。如果們完全致,則使用text-if-true’,否則使用text-if-false’(如果存在的話)。您經常要測試一個變數是否空值,當經複雜的變數和函數展開得到一個值, 對於您認空值,實可能由於含空格不是空值,由可能亂。對於,您可以使用strip函數
從而避免空格作為空值的如︰
ifeq ($(strip $(foo)),)
text-if-empty
endif
使$(foo)中含有空格,也使用text-if-empty’。
ifneq (arg1, arg2) ifneq 'arg1' 'arg2' ifneq "arg1" "arg2" ifneq "arg1" 'arg2' ifneq 'arg1' "arg2"
展開參數arg1arg2中的所有變數引用且比較它們。如果們不同,則使用text-if-true’,否則使用text-if­false’(如果存在的話)。
ifdef variable-name
如果變數variable-name’是非空值,‘text-if-true,否,‘text-if-false(如果存在的話)。變數沒有 定義過則變數空值注意ifdef僅僅測試變數是否有值。它不能展開到看變數是否空值。因而,使用ifdef測試所有定
義過的變數‘真’,但那些foo=’情況外。測試空值使用ifeq($(foo),)。例如︰
bar = foo = $(bar) ifdef foo frobozz = yes else frobozz = no endif
設定frobozz'的值為yes', 而︰:
foo = ifdef foo frobozz = yes else frobozz = no endif
設定frobozz' 為no'
ifndef variable-name
如果變數variable-name’是空值,‘text-if-true,否,‘text-if-false(如果存在的話)。
在指令行前面有多的空格在處理被忽略,但是不有Tab(如果一行Tab,那麼該
規則的命令行)。此之外,空格和Tab可以入到行的任何地方,當然指令名和參數中間除外。以‘#’開 可以在行的
在條件語句中另兩個有影響的指令else和endif。這兩個指令以一個單字的形式出現,沒有任何參數。在指令行前面 有多的空格空格和Tab可以行的中間,以‘#’開釋可以在行的 條件語句影響make使用的makefile檔案。如果條件為‘真’,make讀入text-if-true含的行;如果條件為
make讀入text-if-false含的行(如果存在的話);makefile檔案的語法單位,規則,可以跨越條件語句的
讀入makefile檔案時,Make算條件的值。因而您不能在測試條件使用自動變數,因們是命令執行時才定義參閱自動變數)。
避免不可忍受亂,在一個makefile檔案中開始一個條件語句,而在另一個makefile檔案中情況是不。然而如果您引入引入(include)的makefile檔案中斷條件語句,您可以在條件語句中編寫include指令
7.3測試標誌的條件語句
您可以使用變數MAKEFLAGSfindstring函數編寫一個條件語句用它測試例如‘-t等的make命令標誌參閱字元 串替換和分析的函數)。這適於僅使用touch標誌不能完全檔案的時間戳合。
findstring函數一個字元串是否為另一個字元串的子字元串。如果您要測試‘-t’標誌,使用‘-t’作為第一個字元串
,將變數MAKEFLAGS的值作為另一個字元串如下面的例子是安排使用ranlib t’完成一個資料庫檔案的更新
archive.a: ... ifneq (,$(findstring t,$(MAKEFLAGS))) +touch archive.a +ranlib -t archive.a else ranlib archive.a endif
+’表示這些命令行遞迴行,即使-t標誌它一樣要執行參閱遞迴make
8 文字(text)轉換函數
函數許您在makefile檔案中處理文字(text)計算檔案、操作使用命令。在函數呼叫時您必須指定函數名函數 使用的參數函數處理的結果將makefile檔案中的呼叫點,其模式和變數替換一樣
8.1函數呼叫語法
函數呼叫和變數引用類它的格式如下︰
$(function arguments)
${function arguments}
這裡‘function’是函數名,是make內建函數單中的一個。當然您也可以使用建函數call建的函數
arguments’是該函數的參數參數和函數名之間是用空格或Tab隔開如果有多個參數,它們之間用隔開。這些
格和不是參數值的一。包函數呼叫的定符,無論圓括號或大括,可以在參數中成對出現,在一個函數 呼叫中只有一種定符。如果在參數中包含變數引用或其它的函數呼叫最好使用一種定符,如寫為‘$(subst a,b,$(x))', 而不是 `$(subst a,b,${x})'。這是因種模式不但比較清楚,而且也有在一個函數呼叫中只有一種定的 規定一個參數寫的文字(text)過變數替換或函數呼叫處理最終得到參數的值,這些函數執行必須依靠的文字 (text)外,變數替換是按照變數在參數中出現的次序進行處理的
號和不對出現號、大不能作為文字(text)出現下參數中,前導空格也不能出現下第一個參數中。這些 不能變數替換處理為參數的值。如果需要使用這些符,首先定義變數comma和space的值號和空格
符,然後在要的地方因用它們,如下
comma:= , empty:= space:= $(empty) $(empty) foo:= a b c bar:= $(subst $(space),$(comma),$(foo)) # bar is now `a,b,c'.
這裡函數subst的能是將變數foo中的空格用號替換,然結果。
8.2字元串替換和分析函數
這裡有一於操作字元串的函數
$(subst from,to,text)
在文字(text)text中使用to替換一處from。例如︰
$(subst ee,EE,feet on the street)
結果fEEt on the street’。
$(patsubst pattern,replacement,text)
找‘text符合格式pattern的字replacement替換它。這裡‘pattern’中含萬用字元‘%’,它和一
個字中任意個數的字符相匹配。如果‘replacement’中也含有萬用字元‘%’,則這個‘%被和‘pattern’中萬用字元 ‘%’匹配的文字(text)代替。在函數patsubst中的‘%’可以用反斜線(\)(‘\’)引用。引用字符‘%’的反斜線(\)可以更 多反斜線(\)引用。引用字符‘%’和其它反斜線(\)的反斜線(\)在比檔案名或有一個俓(stem)代替它之前從格式中移出。 使用反斜線(\)引用字符‘%’不會來其它麻煩。例如,格式‘the\%weird\\%pattern\\'是‘the%weird\' 加上萬用字元‘%' 然後和字元串‘pattern\\'連接。最後的兩個反斜線(\)由於不能影響任何統配符‘%’所以保不變。在字之間的空格間
為單個空格,前導以空格被丟棄如︰
$(patsubst %.c,%.o,x.c.c bar.c)
結果︰‘x.c.o bar.o'替換引用是實現函數patsubst一個簡單
$(var:pattern=replacement)
同於 ︰
$(patsubst pattern,replacement,$(var))
另一個通常使用的函數patsubst的簡單是︰替換檔案名的後置
$(var:suffix=replacement)
同於︰
$(patsubst %suffix,%replacement,$(var))
如您可能有一個OBJ檔案的
objects = foo.o bar.o baz.o
得到這些檔案的檔案,您可以簡單的寫為
$(objects:.o=.c)
代替規的格式
$(patsubst %.o,%.c,$(objects))
$(strip string)
前導尾空格的多個空格為單個空格這樣,‘$(strip a b c )'結果a b c’。函數strip和條件語
句連用常有用。當使用ifeq或ifneq把值和空字元串‘’比時,您通常要些僅由空格成的字元串空 字元串參閱makefile中的條件語句)。如下面的例子在實現預期結果時可能失
.PHONY: all ifneq "$(needs_made)" "" all: $(needs_made) else all:;@echo 'Nothing to make!' endif
在條件指令ifneq中用函數呼叫$(strip $(needs_made))'代替變數引用$(needs_made)'將不出現問題
$(findstring find,in)
在字元串in中搜尋find’,如果找到,回值是‘find’,否回值為空。您可以在一個條件中使用該函數測
定的字元串中是否含有特定的子字元串。這,下面兩個例子
$(findstring a,a b c) $(findstring a,b c)
分別生值a‘’。對於函數findstring的特定用法參閱測試標誌的條件語句
$(filter pattern...,
text)
回在text空格開且匹配樣式pattern...的字,對於不符合格式pattern...的字。格式用%
前面論述過的函數patsubst的格式相同。函數filter可以變數分類型不同的字元串如︰
sources := foo.c bar.c baz.s ugh.h foo: $(sources) cc $(filter %.c %.s,$(sources)) -o foo
表明‘foo' 依靠‘foo.c',bar.c',baz.s' 和ugh.h';但僅foo.c',bar.c' 和 baz.s' 指用命令編譯
$(filter-out pattern...,
text)
回在text空格開且不匹配樣式pattern...的字,對於符合樣式pattern...的字出。函數filter的 函數。例如︰
objects=main1.o foo.o main2.o bar.o mains=main1.o main2.o
下面產引入(include)在變數mains中的OBJ檔案的檔案
$(filter-out $(mains),$(objects))
$(sort list)
將‘list中的字字母順並取的字。輸出是由單個空格隔的字的
$(sort foo bar lose)
回值是‘bar foo lose’。順便,由於函數sort可以重複的字,您就是不也可以使用它的個特點。 這裡有一個使用函數subst和patsubst的例子假設一個makefile檔案使用變數VPATH指定make搜尋先決條件檔案的一 系列路俓(stem)參閱VPATH:先決條件搜尋路俓(stem))。這個例子表明怎樣告訴C編譯相同路俓(stem)單中搜尋檔案
變數VPATH的值用冒號的路俓(stem)名,如‘src:../headers'。首函數subst冒號變為空格
$(subst :, ,$(VPATH))
這產生值src ../headers'。然函數patsubst為一個路俓(stem)名加入-|標誌,這這些路俓(stem)可以變數 CFLAGS中,就可以自動C編譯器︰ override CFLAGS += $(patsubst %,-I%,$(subst :, ,$(VPATH))) 結果是以前給定的變數CFLAGS的值後附加文字(text)-Isrc -I../headers’。撤銷(override)指令的作用是即使以前使用命 令參數指定變數CFLAGS的值新值也能作用參閱撤銷(override)指令
8.3檔案名函數
其中個內建的展開函數和分檔案名檔案名聯。下面列舉的函數都能執行對檔案名的特定轉換。函數的 參數系列的檔案名檔案名之間用空格開(前導空格被忽略)。清單中的一個檔案名相同的模 式轉換,而且結果用單個空格串在一
$(dir names...)
names一個檔案名的路俓(stem)檔案名的路俓(stem)包括檔案名的最後一個斜線(/) 斜線(/) )之前的一符。如果檔案名中沒有斜線(/) 路俓(stem)是‘./’。如︰
$(dir src/foo.c hacks)
生的結果src/ ./’。
$(notdir names...)
names一個檔案名中除路俓(stem)符(真正的檔案名)。如果檔案名中沒有斜線(/)
案名,否,將路俓(stem)移走。一個檔案名如果僅引入(include)路俓(stem)(以斜線(/) 的檔案名 )將變為空字元串。這是,因這意結果如果種檔案名兩檔案名之間的空格將不是由 相同多的空格開。但現下我們不能看到其它任何的代替如︰
$(notdir src/foo.c hacks)
生的結果foo.c hacks’。
$(suffix names...)
names一個檔案名的後置。如果檔案名中或含有斜線(/) ,且在最後一個斜線(/) 後含有句點,則後置
最後個句點以後的所有字符,否後置空字元串。如果結果為空著‘names沒有後置檔案名,如果檔案 中含有多個檔案名結果列出的後置數可能比原檔案名數目如︰
$(suffix src/foo.c src-1.0/bar.c hacks)
生的結果是‘.c .c’。
$(basename names...)
names一個檔案名中除後置。如果檔案名中或含有斜線(/) ,且在最後一個斜線(/) 後含有句
點,則基本名字是從開最後一個句點(不引入(include))間的所有字符。如果沒有句點,基本名字個檔案名 如︰
$(basename src/foo.c src-1.0/bar hacks)
生的結果src/foo src-1.0/bar hacks’。
$(addsuffix suffix,names...)
參數names作為一系列的檔案名檔案名之間用空格;suffix作為一個單位。將Suffix(後置)的值附加在每一
檔案名的後面,完成後檔案名串來,們之間用單個空格開。如︰
$(addsuffix .c,foo bar)
結果foo.c bar.c’。
$(addprefix prefix,names...)
參數names作為一系列的檔案名檔案名之間用空格;prefix作為一個單位。將preffix(前)的值附加在每一
檔案名的前面,完成後檔案名串來,們之間用單個空格開。如︰
$(addprefix src/,foo bar)
結果src/foo src/bar’。
$(join list1,list2)
兩個參數串兩個參數的一個字串來形結果一個字兩個參數的個字串來形結果
個字,以類推。如果一個參數另一個參數的字多則多的字動的拷貝到結果上。例如,‘$(join a b,.c .o)'a.c b.o'字之間的空格們由單個空格代替。該函數可將函數dirnotdir的結果合,產定的檔案
$(word n,text)
text中的n個字N的法值1開始。如果n比‘text中的字的數目大,回空值如︰
$(word 2, foo bar baz)
bar’。
$(wordlist s,e,text)
text中的從第s個字到第e個字的一。S、e的法值1。如果s比‘text中的字的數目大,
回空值;如果e比‘text中的字的數目大,從第s個字到‘text’結的所有字;如果se大,不任何如︰
$(wordlist 2, 3, foo bar baz)
回`bar baz'
$(words text)
text中字的數目。這text中的最後一個字是‘$(word $(words text),text)’。
$(firstword names...)
參數names作為一系列的檔案名檔案名之間用空格開;一個檔案名如︰
$(firstword foo bar)
結果‘foo’。 雖然 $(firstword text) 和 $(word 1,text)的作用相同,但第一個函數為簡單而保下來。
$(wildcard pattern)
參數pattern’是一個檔案名樣式型的引入(include)萬用字元和shel中的檔案名一樣。函數wildcard的結果是
和樣式匹配的檔案在的檔案名檔案名之間用一個空格開,參閱在檔案名中使用萬用字元
8.4函數foreach
函數foreach和其它函數不同,導致一個文字(text)使用,而且每次使用文字(text)進行不同的替換它 和shell sh中的命令forC-shell csh中的命令foreach類 函數foreach語法如下︰
$(foreach var,list,text)
兩個參數,‘varlist’,將首展開,注意最後一個參數text時不展開;著,對每一個list’展開產 生的字,將var’展開後命名的變數;然text引用變數展開;因展開都不相同。
結果是由空格textlist中多次展開的字成的新的list’。‘text多次展開的字串來,字與字之 間由空格開,如就產函數foreach的回值。 這是一個簡單的例子,將變數files的值設定為 dirs中的所有目錄的所有檔案的
dirs := a b c d files := $(foreach dir,$(dirs),$(wildcard $(dir)/*))
這裡‘text’是‘$(wildcard $(dir)/*)’。第一個為變數dir發現的值是‘a’,所以產生函數foreach結果的第一個字為 ‘$(wildcard a/*)’;第二個重複的值是‘b’,所以產生函數foreach結果的第二個字為$(wildcard b/*)’;第三個重
的值是‘c’,以產生函數foreach結果個字為$(wildcard c/*)’;等等。該例子和例有結果︰ files := $(wildcard a/* b/* c/* d/*) 如果‘text’比複雜,您可以使用附加變數為它命名,這可以提升程式的性︰ find_files = $(wildcard $(dir)/*) dirs := a b c d files := $(foreach dir,$(dirs),$(find_files))
這裡我們使用變數find_file。我們定義變數find_file時,使用了‘=’,因變數為遞迴型變數,這樣變數find_file所引 入(include)的函數呼叫在函數foreach控制展開;對於簡單展開型變數將不是這在變數find_file定義時就呼叫 函數wildcard 函數foreach變數var沒有影響它的值和變數特色在函數foreach呼叫前面一樣其它從‘list 得到的值在函數foreach執行起作用們是變數var在函數foreach執行期間是簡單展開型變數,如果 執行函數foreach之前變數var沒有定義則函數foreach呼叫後沒有定義參閱變數的兩個特色 使用複雜變數達式生變數名時應小心,因奇怪的字作為變數名,但可能不是您要 的如︰
files := $(foreach Esta escrito en espanol!,b c ch,$(find_files))
如果變數find_file展開引用名為Esta escrito en espanol!變數,上,但錯誤
8.5函數if
函數if在函數上下文中展開條件提供了支援(相對於GNU make makefile檔案中的條件語句ifeq指令參閱條件 語句的語法)。 一個函數if的呼叫,可以引入(include)兩個或個參數
$(if condition,then-part[,else-part])
一個參數condition’,首把前導、結尾空格,然展開。如果展開為非空字元串則條件condition‘真 ’;如果展開為空字元串則條件condition’。 如果條件condition‘真’,那麼計第二個參數then-part的值將該值作為整個函數if的值。 如果條件condition’,第三個參數如果存則計算第三個參數else-part的值將該值作為整個函數if 的值;如果第三個參數不存函數if將什麼也不計回空值。 注意僅能計then-partelse-part’二者之,不能同時計。這樣有可能產作用函數shell的呼叫)。
8.6函數call
函數call一的建新的有參數函數的函數。您可以寫一個複雜的表是作為一個變數的值,然後使用函數call用不 的參數呼叫它 函數call的語法為
$(call variable,param,param,...)
make展開該函數時,每一個參數param賦值變數$(1)$(2)變數$(0)的值變數variable。對於參param的數沒有最數目,也沒有最數目,但是如果使用函數call沒有任何參數不大。 變數variable這些變數的上下文中展開為一個make變數,這在變數variable變數$(1)的引 用決定呼叫函數call時對第一個參數param的使用
注意變數‘variable’是一個變數的名稱,不是對該變數的引用,所以,您不能用‘$’和號的格式寫該變數 ,當然,如果您需要使用的檔案名,您可以在檔案名中使用變數引用。 如果變數名內建函數名內建函數呼叫(即使使用的make變數經存)。函數call在變數 以前首展開參數,這意著,變數variable’對內建函數的呼叫用特殊的規則進行展開,函數foreach或if展開結果預期的結果可能不同。下面的一例子能夠清楚點。 該例子使用巨集參數的
reverse = $(2) $(1)
foo = $(call reverse,a,b)
這裡變數foo的值是‘b a’。 下面是一個的例子它定義一個巨集使用巨集可以搜尋變數PATH引入(include)的所有目錄中的一個
指定類型的程式
pathsearch = $(firstword $(wildcard $(addsufix /$(1),$(subst :, ,$(PATH)))))
LS := $(call pathsearch,ls)
現下變數LS的值是‘/bin/ls或其它的類的值 在函數call中可以使用巢狀。每一次遞迴都可以為它自己的部變數‘$(1)等賦值,從而代替上一函數call的值。例 如︰這實現了像函數能。
map = $(foreach a,$(2),$(call $(1),$(a)))
現下您可以map)僅有一個參數的函數,如函數origin得到多個值
o = $(call map,origin,o map MAKE)
最後變數o引入(include)諸如‘file file default’這樣的值
告︰在函數call的參數中使用空格一定要小心。因為在其它函數中,第個或接下來的參數中的空格是不刪除的 ,這可能導致奇怪結果。當您使用函數call時,去參數中任何的空格才是安全
8.7函數origin
函數origin函數不對任何變數的值僅僅告訴您一個變數的訊它特告訴您變數的
來源。 函數origin的語法
$(origin variable)
注意變數variable’是一個詢變數的名稱,不是對該變數的引用所以,您不能採用$號的格式變 數,當然,如果您需要使用的檔案名,您可以在檔案名中使用變數引用。
函數origin的結果是一個字元串,該字元串變數怎樣定義的
undefined' 如果變數variable’從沒有定義。 ‘default'
變數variable’是預設定義通常和命令CC使用參閱隱含規則使用的變數。注意如果您對一個預設變數重新 進行定義函數origin回後的定義 environment' 變數variable作為環境變數定義選項-e沒有開(參閱選項概要)。 environment override' 變數variable作為環境變數定義選項-e開(參閱選項概要)。 file'
變數variable在makefile中定義
command line' 變數variable在命令行中定義 override' 變數variable在makefile中用撤銷(override)指令定義參閱撤銷(override)指令)。 automatic' 變數variable’是自動變數定義它執行個規則中的命令參閱自動變數)。
種訊息的基本用其它用途滿足的好奇心)是使了解變數值的依據。如,假設有一個名為foo的 makefile檔案它引入(include)另一個名為bar的makefile檔案,如果在環境變數中已定義變數bletch’,您希 執行命令make f bar在makefile檔案bar中重新定義變數bletch’。但是makefile檔案foo在包括makefile檔bar’之前已經定義變數bletch’,而且您也不想使用撤銷(override)指令定義,那麼您可以在makefile檔案 foo中使用撤銷(override)指令,因為撤銷(override)指令將會重載任何命令行中的定義其定義的權超越 後在makefile檔案bar中的定義。因此makefile檔案bar’可以引入(include) ifdef bletch ifeq "$(origin bletch)" "environment" bletch = barf, gag, etc. endif endif
如果變數bletch在環境中定義,這裡將重新定義它。 即使在使用選項-e情況下,您也對來自環境的變數bletch重載定義您可以使用如下內容
ifneq "$(findstring environment,$(origin bletch))" "" bletch = barf, gag, etc. endif
如果‘$(origin bletch)返回environmentenvironment override’,這裡將對變數bletch重新定義參閱字元串 替換和分析函數
8.8 函數shell
函數wildcard之外,函數shell和其它函數不同,make與外部環境的通訊工具。函數shell和在多數shell中後引號
(’)執行的一樣它用命令的展開。這意呼叫shell命令和回命令輸出結果的參數的作用Make僅
處理結果,結果替換呼叫點之前,make將每一個換行回/換行處理為單個空格;如果 結果最後換行符(符),make將把們去。由函數shell呼叫的命令函數呼叫展開,就立即執行在大
多數情況下,當makefile檔案讀入函數shell呼叫的命令執行外情況是在規則命令行中函數的呼叫,因情況下有在命令執行函數才能展開,其它呼叫函數shell的情況
這裡有一使用函數shell的例子
contents := $(shell cat foo)
含有檔案foo的目錄設定為變數contents的值,是用空格(而不是換行符)離每一行
files := $(shell echo *.c)
將‘*.c展開設定為變數files的值make使用怪異的shell,否條語句和wildcard *.c結果相同。
8.9 控制make的函數
這些函數控制make的執行模式通常情況下,來向戶提供makefile檔案的訊或在類型的環境錯誤中斷make執行
$(error text...)
通常text’是致命的錯誤訊。注意錯誤函數時產生的,因如果您將該函數在命令的本中或遞迴型 變數值的右邊過期也不能。‘text’將在錯誤之前展開,如︰
ifdef ERROR1 $(error error is $(ERROR1)) endif
如果變數ERROR01定義makefile檔案讀入時產命的錯誤
ERR = $(error found an error!)
.PHONY: err err: ; $(ERR)
如果err目標被呼叫在make執行時產命錯誤
$(warning text...)
函數和函數error工作的模式類,但make退出,即雖然‘text’展開並顯示結果,但make繼續執行。 展開該函數的結果是空字元串
9 執行make
述編譯程式的makefile檔案,可以由多種模式實現。最簡單的模式編譯所有過期的檔案,對於通常所寫的makefile檔,如果不使用任何參數執行make,那麼將這樣執行
但是您也許僅僅更新一分檔案;您也許需要使用不同的編譯不同的編譯選項;您也許僅僅希望找出舊式的檔案 而不更新它們。這些過在執行make時給出參數才能實現。退make狀態有情況︰
0
表示make成退出。
2
退出狀態為2表示make執行中到錯誤將列描述錯誤
1
退出狀態為1表示您執行make使用了‘-q’標誌make決定一檔案沒有更新參閱代替執行命令
9.1 指定makefile檔案的參數
指定makefile檔案名的使用-f--file選項(‘--makefile’也能工作)。如,‘-f altmake’說明名為
altmake的檔案作為makefile檔案。 如果您連續使用-f標誌,而且每一個-f面都帶有參數則所有指定的檔案連在一起作為makefile檔案。 如果您不使用-f--file選項預設的是按次序尋找‘GNUmakefile', makefile', 和 Makefile'使用這三個中
一個能夠找到在檔案或能夠的檔案參閱編寫makefile檔案
9.2指定最終目標的參數
最終目標gaol)是make最終更新的目標。其它更新的目標是因為它作為最終目標的先決條件或先決條件的先 決條件等等類推
預設情況下,makefile檔案中的一個目標最終目標(不計算那些以句點開始的目標)。因,makefile檔案的第一個
編譯目標是對個程式或程式。如果第一個規則同時個目標規則的一個目標預設的最終目 標 您可以使用make的參數指定最終目標。方使用目標的名字作為參數。如果您指定個最終目標make按您命名
序一個接一個的處理它們。 任何在makefile檔案中出現的目標都能作為最終目標了以‘-’開或含有=的目標一種析為
一種變數定義)。即使在makefile檔案中沒有出現的目標,按照隱含規則可以說明怎樣生成,也能指定為最終目標 Make在命令行中使用特殊變數MAKECMGOALS設定指定的最終目標。如果沒有在命令行指定最終目標,該變數的 值為空值。注意該變數值在特殊合下使用 一個合適的例子除規則中避免刪除包括.d的檔案參閱自動生先決條件),因這樣make不會一建 ,就立即又刪除它們︰
sources = foo.c bar.c
ifneq ($(MAKECMDGOALS),clean) include $(sources:.c=.d) endif
指定最終目標的一個用是僅僅編譯程式的一分或程式中的個程式。如是這,您可以將您希望的檔案指 定為最終目標如,在一個路俓(stem)引入(include)個程式一個makefile檔案以下面的格式
.PHONY: all all: size nm ld ar as
如果您僅對程式size編譯您可以使用make size命令,這只有指定的程式重新編譯 指定最終目標的另一個用編譯哪些沒有常生成的檔案如,一個檔案調或一個版本的程式 要編譯進行測試,然而該檔案不是makefile檔案規則中預設最終目標的先決條件時,可以使用最終目標參數指定它
們。 指定最終目標的另一個用途是執行和一個假想(phony)目標參閱假想(phony)目標或空目標使用空目標記錄事件) 相聯繫的命令。許多makefile檔案引入(include)一個假想(phony)目標clean刪除除了原檔案以外的所有檔案。正情況 下,具體指使用make clean命令make才能執行任務。下面列出型的假想(phony)目標和空目標的名 稱。對GNU make件使用的所有標目標名參閱用目標
all'
makefile檔案的所有目標
`clean'
刪除所有make常建的檔案
`mostlyclean'
目標clean’,但避免刪除們正情況下不重新建的一分檔案如,GCC的目標mostlyclean刪除libgcc.a’,因為重建它的情況十,而且時間。
`distclean' `realclean' `clobber'
這些目標可能定義為目標clean 刪除更多的檔案如,刪除配置檔案或為編譯常建備檔案甚至 makefile檔案自不能的檔案
install
命令搜尋目錄拷貝執行檔案;向可執行檔案尋目錄拷貝執行檔案使用的檔案
print
生變化的檔案
tar
立源檔案的壓縮‘tar檔案
shar
檔案建一個shell的資料庫檔案
dist
檔案建一個發布檔案。這可能是‘tar檔案, ‘shar檔案或多個述的壓縮版本檔案
TAGS
更新程式的tags
`check' `test'
對該makefile檔案建的程式執行自測試
9.3 代替執行命令
makefile檔案告訴make怎樣識別一個目標是否需要更新怎樣更新一個目標。但是更新目標並不是您要的特定的選項可以指定make的其它 `-n' `--just-print' `--dry-run' `--recon' No-op’。make的是列印用目標所使用的命令,但執行它們。 `-t' `--touch' touch’。這是做更新標誌,實卻不們。換句話說,make假編譯目標,但實沒有一 `-q' `--question' ‘question’。這暗中目標是否更新;但是任何情況下也不執行命令換句話說,即不編譯也不輸出。 `-W file' `--what-if=file' `--assume-new=file' `--new-file=file'
What if’。每一個-W標誌後跟一個檔案名所有檔案名的更改時間被make記錄為當前時間,但實際改時間保。如果您要更新檔案,您可以使用‘-W標誌和-n標誌連用看看將發什麼。
使用標誌-n’,make那些正常執行的命令,但卻不執行它們。 使用標誌-t’,make規則中的命令,對那些需要更新的目標使用touch命令。如果不使用-s或 .SILENT,‘touch命令了提執行效率make並不實呼叫程式touch,而是使touch接執行 使用標誌-q’,make不列輸出也不執行命令,如果所有目標更新最新make的退狀態0;如果要更新退狀態1;如果make錯誤退狀態2,因您可以根據沒有更新的目標尋錯誤
在執行make時對以上個標誌如果同時兩個或將產生錯誤。標誌-n’、‘-t-s’對那些以符‘+’開 命令行和引入(include)字元串$(MAKE)' 或${MAKE}'命令行作用。注意僅有這些以字符‘+’開始的命令行和引 入(include)字元串$(MAKE)' 或${MAKE}'命令行執行時不注意這些選項參閱變數MAKE的工作模式
‘-W’標誌有一下兩個特點︰ 如果同時使用標‘-n’或‘-q’,如果您更改一部分文件,看看make將會做什么。 沒有使用標-n-q’,如果make執行用標-W’,則make假裝所有文件經更新,但實
上不改任何文件
注意選項-p-v許您得到更多的make訊在使用的makefile檔案的訊參閱選項概要)。
9.4避免重新編譯檔案
時您可能改一個檔案,但您不希望編譯所有依靠它的檔案如,假設在一個多檔案都依靠檔案 種一個巨集或一個明,按照保的規則make任何對於該頭檔案的,需要編譯所有依靠它的檔案
但是您知那是不必要的且您沒有們完全編譯的時間。 如果您提前了解改檔案以前的問題,您可以使用-t選項。該標誌告訴make執行規則中的命令,但卻將所有目
標的時間戳改到最新。您可按下步驟實現上 1用make命令重新編譯那些需要編譯的檔案 2改頭檔案 3、使用make t命令變所有目標檔案的時間戳,這次執行make時就不會因檔案的編譯任何一個檔 如果在重新編譯那些需要編譯的檔案經改了頭檔案按上步驟已顯太晚了;作為補救措施,您可以 使用-o file標誌能將指定的檔案的時間戳裝改以前時間戳(參閱選項概要)。這意著該檔案沒有更 ,因您可按下步驟進行 1、使用make -o file命令重新編譯那些不是因檔案而需要更新的檔案。如果幾個頭檔案,您可以對每個 檔案使用-o標誌進行指定 2使用make t命令變所有目標檔案的時間戳。
9.5變數重載
使用=定義的變數︰‘v=x’將變數v的值設為x。如果您該方法定義一個變數在makefile檔案後面任何對該變 數的都將make略,要使它在命令行重載
最為常見的使用遞附加標誌編譯靈活性。如,在一個makefile檔案中變數CFLAGS引入(include) 執行C編譯一個命令,因,如果僅僅鍵入命令make時,檔案foo.c’將按下面的模式編譯
cc -c $(CFLAGS) foo.c
在makefile檔案中變數CFALAGS設定的任何影響編譯執行的選項都能,但是每次執行make時您都可以 將該變數重載如︰如果您說‘make CFLAGS='-g -O'’,任何C編譯器都將使用cc -c -g -O’編譯程式。這說明了
在重載變數時,怎樣使用shell命令中的引用包括空格和其它特殊字在內的變數的值 變數CFALAGS僅僅是您可以使用種模式重載的多標變數中的一個,這些變數的單見隱含規則使用的 變數
您也可以編寫makefile看您的附加變數,從而使用戶可過更改這些變數控制make執行的其它。 當您使用命令參數重載變數時,您可以定義遞迴展開型變數或簡單展開型變數。上例中定義的遞迴展開型變數,如 果定義簡單展開型變數,請使用‘:=代替=’。注意在變數值中使用變數引用或函數呼叫,這兩種變數沒有 任何差異。 利種模式也可以改在makfile檔案中重載的變數在makfile檔案中重載的變數使用撤銷(override)指令,是override variable = value’相的命令行。詳細內容參閱撤銷(override)指令
9.6 測試編譯程式
情況下,在執行shell命令有錯誤make立即退狀態;不會任何目標繼續執行命令錯誤表make不能正確的建最終目標make一發現錯誤就立即報告。 當您編譯您修改過的程式時,這不是您所要的結果。您希望make能夠經可能的試編譯一個程式儘可能的顯示 每一個錯誤。 這情況下,您可以使用-k--keep-going選項。這種選項告訴make錯誤狀態之前,繼續找該
標的先決條件,如果要則重新建如,在編譯一個目標檔案時發現錯誤,即使make經知連接它
是不可能的, make k’也將繼續編譯其它目標檔案除在shell命令失繼續執行外,即使發在make不知如何建立
的目標和先決條件檔案,‘make k’也將儘可能繼續執行在沒有-k選項時,這些錯誤將是致命的參閱 選項概要)。 通常情況下,make的行為假設的目標使最終目標更新發現這是不可能的它就立即報告錯誤選項 -k’說真正的目標是儘可能測試程式的影響,發現存在的問題,以便在次執行之前您可以們。這是 Emacs M-x compile命令預設-k選項的原因。
9.7 選項概要
下面是所有make的選項
`-b' `-m' 和其它版本make時,這些選項被忽略。
`-C dir' `--directory=dir' 在makefile讀入之前,把路俓(stem)到‘dir’下。如果指定多個‘-C’選項,每一個都是相對於前一個的解釋︰‘
-C/-C etc同於‘-C/etc’。該選項型用在遞迴make過程中參閱遞迴make
-d常處理後調試訊調試訊說明哪些檔案用更新,哪個檔案作為時間戳的標準以結果,哪
檔案上需要更新,需使用哪些隱含規則等等----一和make決定最終干什麼有關的事情。‘-d選項 於‘--debug=a選項參見下面內容)。
`--debug[=options]' 在常處理後調試訊。可以選各種和類型的輸出。如果沒有參數,列‘基本’別的調試訊。以下是 可能的參數,僅僅考一個字,各個值之間使用號或空格開︰
a (all)
所有調試訊,該選項同於‘-d選項
b (basic)
基本調試訊一個舊式的目標,以重建是否
v (verbose)
比‘基本級高一個的調試訊包括makefile檔案的語法分析結果,沒有要更新的先決條件。該選項同時 入(include)基本調試訊
i (implicit)
隱含規則搜尋目標的訊。該選項同時引入(include)基本調試訊
j (jobs)
種子命令呼叫的詳細
m (makefile)
以上選項引入(include)重新建makefile檔案的訊。該選項引入(include)了這方面的訊。注意,選項all’也不引入 (include)這方面。該選項同時引入(include)基本調試訊
`-e' `--environment-overrides' 設定環境中的變數的權高makefile檔案中的變數的參閱環境變數
`-f file' `--file=file' `--makefile=file'
名為file的檔案設定為makefile檔案參閱編寫makefile檔案
`-h' `--help' 向您提醒make 能夠的選項,然退出。
`-i' `--ignore-errors' 略重建檔案執行命令時產生的所有錯誤
`-I dir' `--include-dir=dir' 指定搜尋引入(include)makefile檔案的路俓(stem)dir’。參閱引入(include)其它makefile檔案。如果同時使用-I選 項用指定路俓(stem)按照指定的次序搜尋這些路俓(stem)
`-j [jobs]' `--jobs[=jobs]' 指定同時執行的命令數目。如果沒有參數make將同時執行儘可能多的任務;如果有多個‘-j’選項,則僅最後一個選項。詳細內容參閱並行執行。注意在MS-DOS下,該選項被忽略。
`-k' `--keep-going' 在出現錯誤後,儘可能繼續執行。當一個目標建立失則所有依靠它的目標檔案將不能重建,而這些目標的其它 先決條件則繼續處理參閱測試編譯程式
`-l [load]' `--load-average[=load]' `--max-load[=load]' 指定如果有其它任務正在執行平均load’(一個),時不動新任務。如果沒有 參數則取以前載的參閱並行執行
`-n' `--just-print' `--dry-run' `--recon' 印要執行的命令,但卻不執行它們。參閱代替執行命令
`-o file' `--old-file=file' `--assume-old=file' 使檔案file它的先決條件’,也不重建檔案。不為檔案file的重建任何其它檔案。該選項本上是裝將該檔案的時間戳改為舊的時間戳,以於依靠它的規則被忽略。參閱避免重新編譯檔案
`-p' `--print-data-base' 印資料庫規則和變數的值),這些據來自讀入makefile檔案的結果;然通常樣執行或按照別的指定選項執。如果同時給出‘-v’開版本訊參閱下面內容)。使用make qp資料庫後重建任何 檔案。使用make p f/dev/null預定義的規則和變數的資料庫。資料庫輸出中引入(include)檔案名,以命令和 變數定義的行號訊複雜環境中很好調試工具
`-q' `--question' 問題模式’。不列輸出也不執行命令,如果所有目標更新最新make的退狀態0;如果要更
退狀態1;如果make錯誤退狀態2參閱代替執行命令
`-r' `--no-builtin-rules'
除使用內建的隱含規則(參閱使用隱含規則)。您然可以定義的樣式規則參閱定義和重新定義樣式規則 )。選項‘-r’同時也清除了預設的後置清單和後置規則(suffix rule)(參閱舊式的後置規則(suffix rule))。但是您可以使
用.SUFFIXES規則定義的後置。注意,使用選項-r’僅僅影響規則預設變數參閱隱含規則使用的 變數);參閱述的選項-R’。 `-R' `--no-builtin-variables'
除使用內建的規則變數(參閱隱含規則使用的變數)。當然,您然可以定義自的變數選項-R’自動使選項-r;因為它隱含規則所使用的變數的定義隱含規則也就失去了存在的
`-s' `--silent' `--quiet' 沈默選項。不回顯那些執行的命令參閱命令回顯
`-S' `--no-keep-going' `--stop' 使選項-k’失在遞迴make時,過變數MAKEFLAGS從上make選項-k’,在環境中設定選項 -k’,否則沒有要使用選項
`-t' `--touch' 標誌檔案更新最新,但實沒有更新它們。這是假裝那些命令經執行,用於愚弄將來的make呼叫。參閱代替執 行命令
`-v' `--version' 印make程式的版本訊者清單和沒有注意,然退出。
`-w' `--print-directory'
執行makefile檔案涉及的所有工作目錄。這對於make遞迴時複雜巢狀生的錯誤非常有用參閱遞迴make。實上,您很少要指定選項,因為make您完指定參閱--print-directory選項
`--no-print-directory' 在指定選項-w情況下,工作路俓(stem)。這個選項在選項-w自動開而且您不時比 有用參閱--print-directory選項
`-W file' `--what-if=file' `--new-file=file' `--assume-new=file' 假目標檔案更新在使用標誌n’時,將向您表明改該檔案會發什麼。如果沒有標誌n它和在執行 make之前對給定的檔案使用touch命令的結果幾一樣,但使用選項make在的想中更改該檔案的時間戳。參閱 代替執行命令
`--warn-undefined-variables'
make看到引用沒有定義的變數時,發布一條。如果您按照複雜模式使用變數,當您調的makefile檔案時 ,該選項常有用
10 使用隱含規則
重新建目標檔案的一準方是經常使用的。例如,一個的建立OBJ檔案的使用C編譯器,如cc編譯C言源程式
隱含規則能夠告訴make怎樣使用的技術任務,這,當您使用它們時,您就不必詳細指定它們。如,有一 條編譯C語言源程式的隱含規則檔案名決定執行哪些隱含規則如,編譯C語程式一般是使用.c檔案,產.o檔案。因 make此和檔案名的後置就可以決定使用編譯C語言源程式的隱含規則系列的隱含規則可按如,make可以從一個.y檔案助‘.c檔案重建一個.o檔案參閱隱含規則鏈內建隱含規則 的命令要使用變數這些變數的值,您就可以改變隱含規則的工作模式。例如,變數CFLAGS控制隱含規則編譯C程式C編譯的標誌參閱隱含規則使用的變數透過編寫樣式規則,您可以立您的隱含規則 參閱定義和重新定義樣式規則
後置規則(suffix rule)是對定義隱含規則最有性。樣式規則一般比通用和清楚,但是後置規則(suffix rule) 性。參閱舊式的後置規則(suffix rule)
10.1 使用隱含規則
make一個目標檔案尋的更新,您所有避免指定任何命令。可以編寫沒有命令行的規則或編寫任何規則。這make將根據存在的檔案的類型或要生成的檔案類型決定使用種隱含規則
如,假設makefile檔案是下面的格式
foo : foo.o bar.o cc -o foo foo.o bar.o $(CFLAGS) $(LDFLAGS)
您提檔案foo.o’,但是您沒有給出它的規則make自動尋一條隱含規則,該規則能夠告訴make怎樣更 新檔案。無論檔案foo.o’存在與否,make都會這樣執行 如果能夠找到一條隱含規則則它就能夠對命令和一個或多個先決條件(源檔案)提供支援。如果您要指定附加的先 決條件如頭檔案,但隱含規則不能支援,您需要為目標foo.o寫一條命令行的規則
一條隱含規則有目標樣式和先決條件格式;也許多條隱含規則有相同的目標樣式如,有數不清的規則.o檔案使用C編譯編譯.C檔案使用Pascal編譯編譯.p檔案等等。實用的規則是那些先決條件在或可以的規則以,如果您有一個.C檔案make執行C編譯器;如果您有一個.p檔案make 行Pascal編譯器;等等 當然,您編寫一個makefile檔案時,您知要make使用一條隱含規則,以您知make一條規則,因您 知個先決條件檔案假設在的預定義的隱含規則單的詳細內容參閱隱含規則目錄。 首,我們說一條隱含規則可以應,該規則的先決條件必須‘存在或可以立’。一個檔案‘可以立’是說該
案在makefile中作為目標或先決條件者該檔案可以經過一條隱含規則的遞迴後能夠立。如果一條隱含規則 的先決條件另一條隱含規則的結果,我們說產了‘’。參閱隱含規則鏈 上說,make為一個目標搜尋隱含規則為沒有命令行的雙冒號規則(::)搜尋隱含規則。僅作為先決條件的 檔案,將一個目標,如果該目標的規則沒有指定任何內容 make為它搜尋隱含規則。對於詳細的搜尋過程 參閱隱含規則的搜尋算法 注意,任何具體的先決條件都不影響隱含規則的搜尋如,認這是一條具體的規則
foo.o: foo.p
檔案foo.p不是首要條件,這意make按照隱含規則可以從一個Pascal程式(‘.p檔案立OBJ檔案,也就是說 一個.o檔案可根據‘.p檔案進行更新。但檔案foo.p並不是對必要的如,如果檔案foo.c也存,按照隱含規 則則是從檔案foo.c重建foo.o,這是因為C編譯規則在預定義的隱含規則單中Pascal規則靠前,參閱隱含規則目錄 如果您不希望使用隱含規則建一個沒有命令行的目標,您可以透過加分號為目標指定空命令參閱使用空命令
10.2隱含規則目錄
這裡列預定義的隱含規則的目錄,這些隱含規則是經用的,當然如果您在makefile檔案中重載或刪除後,這些 隱含規則將會失去作用,詳細內容參閱刪除隱含規則。選項-r--no-builtin-rules’將刪除所有預定義的隱含規則不是所有的隱含規則都是預定義的在make中很多預定義的隱含規則後置規則(suffix rule)的展開,因此,那些預 定義的隱含規則和後置規則(suffix rule)的特殊目標.SUFFIXES的先決條件)。預設的後置單為.out, .a, .ln, .o, .c, .cc, .C, .p, .f, .F, .r, .y, .l, .s, .S, .mod, .sym, .def, .h, .info, .dvi, .tex, .texinfo, .texi, .txinfo, .w, .ch .web, .sh, .elc, .el所有下面描述的隱含規則,如果的先決條件中有一個出現下這個後置單中後置規則 (suffix
rule)。如果您改這個後置那些由一個或兩個出現下您指定的單中的後置命名的預定義後置規則(suffix rule)作用;那些後置沒有出現下清單中的規則。對於詳細的關後置規則(suffix rule)的述參閱舊式的後置規 則(suffix rule) Compiling C programs編譯C程式
n.o' 自動由‘n.c' 使用命令 $(CC) -c $(CPPFLAGS) $(CFLAGS)'生成
Compiling C++ programs 編譯C++程式
n.o'自動由‘n.cc' 或n.C'使用命令$(CXX) -c $(CPPFLAGS) $(CXXFLAGS)生成我們鼓勵您對C++檔案使用後置
.cc' 代替後置.C’。 Compiling Pascal programs 編譯Pascal程式
n.o'自動由‘n.p'使用命令$(PC) -c $(PFLAGS)'生成
Compiling Fortran and Ratfor programs 編譯Fortran 和 Ratfor程式
n.o'自動由‘n.r', n.F'或n.f' 執行Fortran編譯生成使用的精確命令如下︰
`.f' `$(FC) -c $(FFLAGS)'. `.F' `$(FC) -c $(FFLAGS) $(CPPFLAGS)'. `.r' `$(FC) -c $(FFLAGS) $(RFLAGS)'. Preprocessing Fortran and Ratfor programs 預處理Fortran 和 Ratfor程式
n.f' 自動 n.r'或n.F'得到。該規則僅僅是與處理器把一個Ratfor 程式或能夠預處理的 Fortran 程式轉變為標
Fortran 程式使用的精確命令如下︰ `.F' `$(FC) -F $(CPPFLAGS) $(FFLAGS)'. `.r' `$(FC) -F $(FFLAGS) $(RFLAGS)'. Compiling Modula-2 programs編譯Modula-2程式
n.sym'自動由‘n.def'使用命令$(M2C) $(M2FLAGS) $(DEFFLAGS)'生成 n.o' 從‘ n.mod'生成命令為:$(M2C) $(M2FLAGS) $(MODFLAGS)'
Assembling and preprocessing assembler programs 預處理組合程式
n.o'自n.S'執行C編譯器,cpp生成命令為:‘$(CPP) $(CPPFLAGS)'。
Linking a single object file 連接一個簡單的OBJ檔案
n' 自動由‘n.o' 執行C編譯中的連接程式 linker (通常為 ld)生成命令為: ‘$(CC) $(LDFLAGS) n.o $(LOADLIBES)
$(LDLIBS)'。該規則對僅有一個程式的簡單程式或對同時含有多個OBJ檔案(可能來於不同檔案的程式都能常工作。如果同時含有多個OBJ檔案則其中有一個OBJ檔案的名字和執行檔案名匹配如︰
x: y.o z.o
當‘x.c', ‘y.c' 和‘z.c' 都存在時則執行︰
cc -c x.c -o x.o cc -c y.c -o y.o cc -c z.c -o z.o cc x.o y.o z.o -o x rm -f x.o rm -f y.o rm -f z.o
對於複雜情況,沒有一個OBJ檔案的名字和執行檔案名匹配,您必須為連接寫一條具體的命令。每一種自 動生成.o的檔案,可以在沒有-c選項的情況下使用編譯($(CC)',$(FC)'或$(PC)' C編譯器‘$(CC)'也適程式)自動連接。當然也可以使用OBJ檔案作為中檔案,但編譯連接一將快
Yacc for C programs (由Yacc生成C程式)
‘n.c'自動由‘n.y'使用命令‘$(YACC) $(YFLAGS)'執行 Yacc生成
Lex for C programs (由Lex生成C程式
n.c'自動由‘n.l' 執行 Lex生成命令為︰‘$(LEX) $(LFLAGS)'。
Lex for Ratfor programs (由Lex生成Rator程式
n.r'自動由‘n.l' 執行 Lex生成命令為︰‘$(LEX) $(LFLAGS)'。 對於所有的Lex檔案,無論它們產生C代或Ratfor 代
,都使用相同的後置.l進行轉換在特定合下,使用make自動使用種語言是不可能。如果make使用.l檔案重建一個OBJ檔案必須想使用種編譯器。很可能想使用的是 C 編譯器, 因為C 編譯器更加普
如果您使用 Ratfor語言, 請確保在makefile檔案中提了‘n.r',使make知您的選。否則,如果您專用Ratfor語言,不
使用任何C 檔案, 在隱含規則後置單中將‘.c
.SUFFIXES: .SUFFIXES: .o .r .f .l ...
Making Lint Libraries from C, Yacc, or Lex programs(由C, Yacc, 或 Lex程式建Lint庫 n.ln' 可以從‘n.c' 執行lint命令為︰‘ $(LINT) $(LINTFLAGS) $(CPPFLAGS) i’。於C程式的命令和用於‘n.y'n.l'程式相同。 TeX and WebTeX 和 Web
‘n.dvi'可以從‘n.tex' 使用命令‘$(TEX)'得到。‘n.tex'可以從‘n.web'使用命令‘$(WEAVE)'得到;或者從‘n.w' (和‘n.ch',如 果‘n.ch'存在或可以建) 使用命令‘$(CWEAVE)'。‘n.p' 可以從‘n.web'使用命令‘$(TANGLE)'產生。‘n.c' 可以從‘n.w' (和 ‘n.ch',如果‘n.ch'存在或可以建) 使用命令‘$(CTANGLE)'得到。
Texinfo and InfoTexinfo和Info
n.dvi'可以從‘n.texinfo',n.texi', 或n.txinfo', 使用命令‘$(TEXI2DVI) $(TEXI2DVI_FLAGS)'得到。‘n.info'可以從 ‘n.texinfo',n.texi', 或n.txinfo', 使用命令‘$(MAKEINFO) $(MAKEINFO_FLAGS)'建立。
RCS 檔案n'時可以從名為n,v'或‘RCS/n,v'的RCS檔案中具體命令是︰‘$(CO) $(COFLAGS)'檔案‘n'如果已,即使RCS檔案它新不能從RCS檔案中於RCS的規則最終的規則參閱萬用規則以RCS不能 夠從任何源檔案們必須存
SCCS 檔案n'時可以從名為s.n'或SCCS/s.n'的SCCS檔案中。具體命令是︰‘$(GET) $(GFLAGS)'。用SCCS的規則 最終的規則參閱萬用規則SCCS不能夠從任何源檔案們必須存SCCS的點是,檔案 n' 可以從 檔案 n.sh'拷貝並生成執行檔案(任何都可以)。這用於shell的本,該腳本在SCCS內查。因為RCS 許保持檔 案的執行性,以您沒有將該於RCS檔案。我們推您避免使用SCCS,RCS不但使用廣泛,而且是免 體代替相當劣的收費,是您對體的支援 通常情況下,您僅僅改上表中的變數,需要參閱下面的文檔
隱含規則的命令實際使用諸如COMPILE.c, LINK.p, 和 PREPROCESS.S等等變數的值引入(include)以上列出的命令 Make按照慣例進行處理,如,編譯.x’源檔案的規則使用變數COMPILE.x’;從‘.x’源檔案生成執行檔案使 用變數LINK.x’;預處理.x’源檔案使用變數PREPROCESS.x’。
任何產OBJ檔案的規則使用變數‘OUTPUT_OPTION’;make依據編譯時間選項定義變數的值是‘-o $@’或空 值。當源檔案分不同的目錄中,您應該使用-O’選項保證輸出到正確的檔案中使用變數VPATH時同參閱 為先決條件搜尋目錄)。些系統的編譯器不對OBJ檔案的-o’開;如果您樣的系統上執行並使用 變數VPATH檔案的編譯輸出可能會錯誤的地方。解是將變數OUTPUT_OPTION值設為︰‘; mv $*.o
$@’。
10.3隱含規則使用的變數
內建隱含規則的命令預定義變數的使用是開;您可以在makefile檔案中變變數的值,也可以使用make的執行參 數或在環境中,如不對這些規則本重新定義的情況下,就可以改這些規則的工作模式。您可以使用 選項-R’--no-builtin-variables刪除所有隱含規則使用的變數
如,編譯C程式的命令是‘$(CC) -c $(CFLAGS) $(CPPFLAGS)’,變數預設的值是‘cc或空值,該命令 cc c’。如重新定義變數CC的值為ncc’,則所有隱含規則使用ncc作為編譯C語言源程式的編譯器。 過重新定義變數CFLAGS的值為-g’,您可將‘-g選項給每個編譯器。所有的隱含規則編譯C程式時都使$CC編譯的名稱,且都編譯的參數中引入(include)$(CFLAGS)’。
隱含規則使用的變數分為兩類一類程式名變數cc),另一類引入(include)程式執行參數的變數 CFLAGS)。(程式名’可能也引入(include)一命令參數,但是必須以一個可以執行的程式名。) 如果一個 變數值中引入(include)多個參數們之間用空格開。
這裡是內建規則中程式名變數
AR 檔案理程式預設為︰‘ar'.
AS 彙編編譯程式預設為︰‘as'. CC C語編譯程式預設為︰‘cc'. CXX C++編譯程式預設為︰‘g++'. CO 從RCS檔案中解抽取檔案程式;預設為︰‘co'. CPP 帶有標準輸出的C語預處理程式預設為︰‘$(CC) -E'. FC Fortran Ratfor 語的編譯和預處理程式預設為︰‘f77'. GET 從SCCS檔案中解抽取檔案程式;預設為︰‘get'. LEX 將 Lex 語言轉變為 C 或 Ratfor程式的程式;預設為︰‘lex'. PC Pascal 程式編譯程式預設為︰‘pc'.
YACC Yacc語轉變為 C程式的程式預設為︰‘yacc'. YACCR Yacc語轉變為 Ratfor程式的程式預設為︰‘yacc -r'.
MAKEINFO 將Texinfo 源檔案轉換為訊檔案的程式;預設為︰‘makeinfo'. TEX 從TeX源產生TeX DVI檔案的程式;預設為︰‘tex'. TEXI2DVI 從Texinfo源產生TeX DVI 檔案的程式;預設為︰‘texi2dvi'. WEAVE Web譯成TeX的程式預設為︰‘weave'. CWEAVE 將CWeb翻譯成TeX的程式;預設為︰‘cweave'. TANGLE Web翻譯成 Pascal的程式;預設為︰‘tangle'. CTANGLE Web翻譯成C的程式;預設為︰‘ctangle'.
RM 刪除檔案的命令;預設為︰‘rm -f'.
這裡是值為述程式附加參數的變數在沒有注明情況下,所有變數的值為空值
ARFLAGS 檔案理程式的標誌預設為︰‘rv'. ASFLAGS 編編譯標誌 (具體呼叫.s'或.S'檔案) CFLAGS C編譯標誌 CXXFLAGS C++編譯標誌 COFLAGS 於RCS co程式的標誌 CPPFLAGS C預處理使用它的程式的標誌 (C和 Fortran 編譯) FFLAGS Fortran編譯標誌 GFLAGS SCCS get程式的標誌 LDFLAGS 呼叫linker(‘ld’)的編譯標誌 LFLAGS Lex的標誌 PFLAGS Pascal編譯標誌
RFLAGS 處理Ratfor程式的Fortran編譯標誌 YFLAGS 於Yacc的額標誌。Yacc
10.4 隱含規則鏈
生成一個檔案要使用多個隱含規則成的序列。如,從檔案n.y生成檔案n.o’,首先執行隱含規則
Yacc,其次執行規則cc。這樣的隱含規則序列稱為隱含規則鏈 如果檔案n.c’存在或在makefile檔案中不需任何特定搜尋make發現過C編譯編譯n.c’可生成 該OBJ檔案,考生成n.c’時,則使用執行Yacc的規則。這最終更新n.cn.o’。 即使在檔案n.c’不存在或在makefile檔案中沒有情況下,make也能在檔案n.yn.o’缺連接情況下,‘n.c’稱為中檔案make決定使用中檔案將把檔案入資料庫好像檔案在
makefile檔案中一樣;按照隱含規則的述建檔案
檔案和其它檔案一樣使用自的規則重建,但是檔案和其它檔案相比有兩種不同的處理模式 一個不同的處理模式是如果檔案不存在make的行為不同︰平常的檔案b如果不存make為一個目標依靠檔 案b檔案b,然根據檔案b更新目標;但是檔案b檔案make可能不進行的工作,即
檔案b,也不更新最終目標有在檔案b的先決條件最終目標’時或有其它原因時,才更新最終目標。 第不同點是make在更新目標建檔案b後,如果檔案bmake將把它刪除一個中檔案在make執行 之前和make執行都不存Make向您報告刪除時列一條rm f命令,表明有檔案刪除
通常情況下,任何在makefile檔案中的目標和先決條件都不是檔案。但是,您可以指定一檔案為中檔 案法為︰將要指定為中檔案的檔案作為特殊目標 .INTERMEDIATE的先決條件。這使
具體的檔案也能
透過檔案標誌為secondary檔案可以阻止自動刪除中檔案。這時,您將您需留的中檔案指定為特殊目標 .SECONDARY的先決條件即可。對於secondary檔案,make不會因為它不存在而去建立它,也不會自動刪除它。secondary 檔案必須也是檔案 您可以列舉一個隱含規則的目標樣式%.o作為特殊目標 .PRECIOUS的先決條件,這您就可以保那些由隱 含規則建的檔案名匹配格式的中檔案參閱中斷和關閉make 一個隱含規則鏈至少包含兩個隱含規則如,從‘RCS/foo.y,v檔案foo’需要執行RCSYacc和cc檔案foo.y 和foo.c檔案在執行 沒有一條隱含規則可以在隱含規則鏈中出現兩次以上(含兩次)。這意著,make不會簡單的認為從檔案‘foo.o.o’建 檔案foo不是執行linker兩次。這可以強製make在搜尋一個隱含規則鏈阻止無限循環特殊的隱含規則化隱含規則鏈控制的特定情況。如,從檔案foo.c建檔案foo可以有編譯和連接的規則 鏈控制它使用foo.o作為中檔案。但是對於這種情況存在一條特的規則,使用簡單的命令cc可以同時編譯和連接。 化規則在規則中的前面,優化規則和一的規則鏈相比,優先使用化規則
10.5定義與重新定義樣式規則
您可以過編寫樣式規則定義隱含規則。該規則通規則類,不同之處在樣式規則的目標中含字符‘% ’(有一個)。目標是匹配檔案名的格式;字符‘%’可以匹配任何空的字元串,而其它字符僅僅和它們自己相匹
先決條件用%’表示的名字和目標名關聯。 格式%.o : %.c’是說將任何‘stem.c檔案編譯為stem.o檔案 在樣式規則中使用的%’展開是在所有變數和函數展開以後進行的們是在makefile檔案讀入時完成的參閱使用 變數和轉換文字(text)函數
10.5.1樣式規則簡介
樣式規則在目標中引入(include)字符‘%’(有一個的規則其它方面看通規則相同。目標是可以匹配 檔案名的格式符‘%’可以匹配任何空的字元串,而其它字符僅僅和它己相匹配如‘%.c匹配任何以‘.c’結的檔案名;‘s.%.c匹配以‘s.’開且以‘.c’結的檔案名,該檔案名至少引 入(include)5個字符(因%至少匹配一個字符)。匹配%的子字元串為俓(stem)先決條件中使用%’表示的名字中含有和目標名相同的stem。要使用樣式規則檔案名必須匹配目標的格式,而且符合先決條件格式的檔案 必須存在或可以立。下面規則
%.o : %.c ; command...
表明要建檔案n.o’,使用n.c作為它的先決條件,而且檔案n.c’ 必須存在或可以立。
在樣式規則中先決條件有時不含有%’。這表明採用該樣式規則建立的所有檔案都是採用相同的先決條件。這種固 定先決條件的樣式規則在有合十分有用
樣式規則的先決條件不必都引入(include)字符‘%’,這樣的規則一個有的常規萬用字元它為任何匹配目標樣 式規則的檔案提供立方參閱定義最新類型的預設規則 樣式規則可以有多個目標,不常的規則,這種規則不能扮演具有相同先決條件和命令的多條不同規則。如果一樣 式規則具有多個目標make規則的命令對於所有目標來說都是可靠,這些命令有在建所目標時才執行。當 為匹配一目標搜尋樣式規則時,規則的目標樣式和規則要匹配的目標不同是十見的make僅僅前對檔 案給出命令和先決條件是否有問題。注意該檔案的命令一執行所有目標的時間戳都會更新
樣式規則在makefile檔案中的次序重要,因這也是考的次序。對於多個都能使用的規則使用最先出現的規 則。您親自編寫的規則比內建的規則先。注意先決條件存在或及的規則於先決條件需要經過隱含規則鏈生成 的規則
10.5.2樣式規則的例子
這裡有一些實在make中預定義的樣式規則例子,第一個編譯.c檔案生成.o檔案的規則
%.o : %.c
$(CC) -c $(CFLAGS) $(CPPFLAGS) $< -o $@
定義一條編譯x.c檔案生成x.o檔案的規則命令使用自動變數$@’$<’ 替換任何情況使用規則的 目標檔案和檔案參閱自動變數
個內建的例子
% :: RCS/%,v
$(CO) $(COFLAGS) $<
定義在子目錄‘RCS根據相應檔案x.v生成檔案x的規則。因為目標是‘%’,相對應的先決條件檔 案,該規則可以應於任何檔案雙冒號表示該規則最終規則著不能是檔案參閱萬用規則 下面的樣式規則有兩個目標
%.tab.c %.tab.h: %.y bison -d $<
這告訴make執行命令bison -d x.y’將立‘x.tab.cx.tab.h’。如果檔案foo依靠檔案parse.tab.oscan.o’, 而檔案scan.o依靠檔案parse.tab.h’,當‘parse.y’發生變化命令bison -d parse.y執行一次。‘parse.tab.oscan.o的先決條件更新。(假設檔案parse.tab.o’由檔案parse.tab.c編譯生成檔案scan.o’由檔案scan.c生成,當連接parse.tab.o’、‘scan.o和其它先決條件生成檔案foo時,上述規則能夠很好執行。)
10.5.3自動變數
假設編寫一個編譯.c檔案生成.o檔案的規則︰您怎樣編寫命令CC’,使它能夠操正確的檔案名您當
然不能將檔案名接寫進命令中,因次使用隱含規則作的檔案名都不一樣。 您應該使用make的另一個特點,自動變數。這些變數在規則次執行時都目標和先決條件生新值例如您可以使 用變數$@’代替目標檔案名變數$<’代替先決條件檔案名。 下面是自動變數
$@
規則的目標檔案名。如果目標是一個資料庫成員,則變數‘$@’ 資料庫檔案的檔案名。對於有多個目標的樣式規則(
參閱樣式規則簡介),變數$@’是那導致規則命令執行的目標檔案名
$%
目標資料庫成員時,該變數目標成,參閱使用make更新資料庫檔案如,如果目標是‘foo.a(bar.o)'
$%'的值是‘bar.o',‘$@'的值是‘foo.a'。如果目標不是資料庫成員,$%'空值
$<
一個先決條件的檔案名。如果目標更新命令來源於隱含規則,該變數的值隱含規則加的一個先決條件參閱使
用隱含規則
$?
所有目標的先決條件名名字之間用空格。對於為資料庫成員的先決條件,能使用命名的成員。參閱
使用make更新資料庫檔案
$^
所有先決條件的名字名字之間用空格開。對於為資料庫成員的先決條件,能使用命名的成員。參閱使用make更
新資料庫檔案。對同一個目標來說,一個檔案作為一個先決條件,不檔案的檔案名在先決條件單中出現
以,如果在先決條件單中,同一個檔案名出現多次變數$^的值然僅引入(include)檔案名一次
$+
變數$^',但是,過一次列出的先決條件將按照在makefile檔案中出現的次序。這要的用是對於 按照特定序重庫檔案名義的地方使用連接命令
$*
和隱含規則匹配的俓(stem),參閱樣式匹配。如果一個目標為‘dir/a.foo.b',目標樣式規則為︰‘a.%.b' 則stem為
dir/foo'關檔案名stem 分有用。在靜態樣式規則中stem匹配目標樣式中字符‘%的檔案名中
。在一個沒有stem具體規則中變數$*' 不能以該方法設定。如果目標名以一種推的後置結(參閱舊式的後置規 則(suffix rule)),變數$*'設定為目標後置後的如,如果目標名是‘foo.c'則變數$*' 設定為foo',
因為‘.c' 是一個後置。GNU make 處理這樣奇怪的事情是為了和其它版本的make容。在隱含規則和靜態樣式規則以外 ,您應該盡量避免使用變數$*'。在具體規則中如果目標名不以推的後置結,則變數‘$*’在該規則中設定為空 值。
當您希望僅僅操那些改變的先決條件變數$?' 使在具體的規則中有用如,假設名為lib的資料庫檔
OBJ檔案的拷貝下面的規則僅將發生變化的OBJ檔案拷貝資料庫檔案 lib: foo.o bar.o lose.o win.o ar r lib $?
上面列的變數中個值單個檔案名三個值檔案名。這七個放檔案的路俓(stem)名或放目錄下檔案 名的變體變數的變體名是由變數名加字‘D’F。這些變體在GNU make中處於廢狀態,原因是使用 函數T dir和notdir 能夠得到相同結果。參閱檔案名函數。注意,‘F'變體略所有在dir函數中是輸出的結尾斜線(/) 裡是這些變體的
`$(@D)' 目標檔案名中的路俓(stem),結尾斜線(/) 移走。如果變數`$@'的值是`dir/foo.o',變體 `$(@D)'的值是`dir'。 如果 數`$@'的值包括斜線(/) 則變體的值`.' `$(@F)' 目標檔案名中的真正檔案名。如果變數`$@'的值`dir/foo.o'變體 `$(@F)'的值` foo.o '`$(@F)' 同於 `$(notdir $@)' `$(*D)' `$(*F)' 俓(stem)中的路俓(stem)名和檔案名個例子中它的值分`dir' 和 `foo' `$(%D)' `$(%F)' 資料庫成名中的路俓(stem)名和檔案名;這僅對archive(member)’形式的資料庫成目標有且當 引入(include)路俓(stem)名時才有用參閱資料庫成目標
`$(<D)' `$(<F)' 一個先決條件名中的路俓(stem)名和檔案名 `$(^D)' `$(^F)' 所有先決條件名中的路俓(stem)名和檔案名 `$(?D)' `$(?F)' 所有目標的先決條件名中的路俓(stem)名和檔案名 注意,我們討論自動變數時,我們使用特殊格式的;我們寫"the value of$<'", 而不是"the variable <" 我們通變數變數 objects 和 CFLAGS一樣。我們認為這種慣例在這種情況下看起來更加自然。這並沒有其它意義, 變數‘$<'的變數名為 < 和變數‘$(CFLAGS)' 實際變數名為CFLAGS一樣。您也可以使用‘$(<)'代替‘$<'
10.5.4樣式匹配
目標樣式是由前、後置和它們之間的萬用字元%組中的一個或兩個都可以是空值。樣式匹配一個檔案名檔案名是以前後置,而且者不的條件下,才算匹配。前後置之間的文字 (text)成為俓 (stem)。當樣式%.o匹配檔案名test.o’時,俓(stem)是‘test’。樣式規則中的先決條件俓(stem)替換字%,從
而得出檔案名。對於上例中,如果一個先決條件為%.c’,可展開test.c’。
目標樣式中斜線(/) (實不是這),則檔案名中的路俓(stem)名,然,將其和格式中的和後置相比在比,以斜線(/) 的路俓(stem)名,將會加在根據樣式規則的先決條件規則生的先決條件 前面。有在尋隱含規則路俓(stem)名被忽略,路俓(stem)名不能略。
如,‘e%t和檔案名src/eat匹配俓(stem)是‘src/a’。當先決條件轉化為檔案名時,stem中的路俓(stem)名加 在前面,俓(stem)的其分替換%’。使用俓(stem) src/a和先決條件樣式規則c%r匹配得到檔案名 src/car’。
10.5.5萬用規則match-anything rules.
一個樣式規則的目標僅僅%’,可以匹配任何檔案名,我們稱這些規則為萬用規則常有用,但是make 使用它時也,因為make必須為作為目標和作為先決條件列出一個檔案都考樣的規則
假設makefile檔案檔案foo.c。為立該目標make將考過連接一個OBJ檔案foo.c.o立,過使 用一的C編譯連接程式檔案foo.c.c建立,編譯連接Pascal程式foo.c.p建立,以其它的可能性
我們知make這些可能性是,因為foo.c就是一個C語言源程式,不是一個執行程式。如果make這 些可能性,將因這些檔案諸如foo.c.o和foo.c.p都不存在最終拒絕們。但是這些可能性以導致make的執
極慢快速,我們為make匹配萬用規則的模式設定了限有兩種不同類型的可以應用的您每次定義 一個萬用規則時,您必須定義的規則在兩種類型中選一種
一種選標誌萬用規則最終規則,即在定義使用雙冒號定義一個規則為最終規則時,有在它的先決條件 時才能應,即使先決條件可以由隱含規則建立也不。換句話說,在最終規則中沒有進一的鏈
如,從RCS和SCCS檔案中抽取檔案的內建的隱含規則最終規則如果檔案foo.c,v' 不存make不會試圖 一個中檔案foo.c,v.o‘RCS/SCCS/s.foo.c,v在建 RCS 和 SCCS 檔案一般都是最終檔案不能從其 它任何檔案重新建立,以,make可以記錄時間戳,但不重建它的模式
如果您不將萬用規則標誌為最終規則,那麼就是非最終規則一個非最終萬用規則不能指定特殊類型數的檔 案。如果存在其它規則(非萬用規則的目標匹配一檔案名檔案名就是指定特殊類型數的檔案名如,檔案名foo.c' 和樣式規則 `%.c : %.y' (規則執行Yacc)。無論該規則是否實際使用(如果碰巧存在檔案‘foo.y’, 規則執行)和目標匹配的事實就能阻止任何非最終萬用規則在檔案foo.c使用。這make 就不試圖 檔案foo.c.o',foo.c.c', foo.c.p'等建立可執行的foo.c' 內建的特殊樣式規則來認定一特定的檔案名處理這些檔案名的檔案時不能使用非最終萬用規則。這些樣 式規則沒有先決條件和命令其它目的時被忽略。如,內建的隱含規則
%.p : 可以保證Pascal程式如‘foo.p' 匹配特定的目標樣式,從而阻止浪費時間找‘foo.p.o' 或foo.p.c' 在後置規則(suffix rule)中為後置單中的一個有後置立了樣式規則,如‘ %.p' 參閱舊式的後置規則 (suffix rule)
10.5.6刪除隱含規則
過定義新的具有相同目標和先決條件但不同命令的規則,您可以重載內建的隱含規則或重載定義的規則定義新的規則內建的規則代替 新規則在隱含規則次序中的由您編寫規則的地方決定
過定義新的具有相同目標和先決條件但不含命令的規則,您可以刪除內建的隱含規則如,下面的定義規則 除執行編編譯的隱含規則 %.o : %.s
10.6 定義最新類型的預設規則
透過編寫含先決條件的最終萬用樣式規則,您可以定義最新類型的預設規則參閱萬用規則。這和其它規則基本一處在可以匹配任何目標。因,這樣的規則的命令所有沒有自的命令的目標和先決條件,以 於那些沒有其它隱含規則可以應用的目標和先決條件如,在測試makefile時,您可能不心源檔案是否含有真實據,僅僅們是否存。那麼,您可以這做︰
%:: touch $@
這導致所有必需檔案作為先決條件)都自動建立。
您可以為沒有規則的目標那些沒有具體指定命令的目標定義命令要完成上述任務,您需要為特殊目標.DEFAULT 編寫規則。這樣的規則可以在所有具體規則中用沒有作為目標出現以不能使用隱含規則的先決條件自然,如果您編寫定義則沒有特殊目標.DEFAULT 的規則
如果您使用特殊目標.DEFAULT 而不任何規則和命令:
.DEFAULT: 則以前為目標.DEFAULT定義的命令。如make的行為和您從來沒有定義目標.DEFAULT一樣 如果您不需要一個目標萬用規則和目標.DEFAULT 中得到命令,也不想為目標執行任何命令,您可以在定義使 用空命令參閱使用空命令 您可以使用最新類型規則重載另一個makefile檔案的一分內容參閱重載其它makefile檔案
10.7 舊式的後置規則(suffix rule)
後置規則(suffix rule)定義隱含規則的過時方後置規則(suffix rule)為樣式規則更為和簡被廢棄在 GNU make中得到支援期的makefile檔案分為單後置和雙後置規則(suffix rule) 雙後置規則(suffix rule)後置定義目標後置和檔案後置可以匹配任何檔案名目標後置的檔案。相應 的隱含先決條件過在檔案名中目標後置替換為檔案後置得到。一個目標和檔案後置分.o.c雙後 置規則(suffix rule)相當於樣式規則`%.o : %.c'
單後置規則(suffix rule)單後置定義,該後置是源檔案的後置。它匹配任何檔案名相應的先決條件名是將檔案名檔案後置得到。源檔案後置為.c的單後置規則(suffix rule)相當於樣式規則% : %.c’。 規則目標和定義的知後置識別規則。當make見一個目標後置知後置的規則時,該規則一個單後置規則(suffix rule)。當make見一個目標後置引入(include)兩個後置的規則時,該規則一個 雙後置規則(suffix rule)
如,‘.o.c’都是預設單中的後置。所以,如果您定義一個規則其目標是‘.c.o’,則make一個 雙後置規則(suffix rule),源檔案後置是‘.c’,目標後置是‘.o’。這裡有一個用舊式的方法定義編譯C語言程式的規
.c.o: $(CC) -c $(CFLAGS) $(CPPFLAGS) -o $@ $<
後置規則(suffix rule)不能任何的先決條件。如果有先決條件們將不是作為後置規則(suffix rule) 使用,而是以啼笑皆的模式處理常的檔案如,規則
.c.o: foo.h $(CC) -c $(CFLAGS) $(CPPFLAGS) -o $@ $<
告訴從先決條件foo.h生成檔案名為.c.o的檔案不是樣式規則 %.o: %.c foo.h
$(CC) -c $(CFLAGS) $(CPPFLAGS) -o $@ $< 告訴從‘.c'檔案生成 ‘.o' 檔案‘.c'的方法︰建立所有‘.o' 檔案使用該樣式規則,而且同時使用先決條件檔案‘foo.h'。 沒有命令的後置規則(suffix rule)也沒有意義。它們並不沒有命令的樣式規則那樣移去以前的規則(參閱刪除隱含規則) 。們僅僅簡單的在資料庫中加入後置或雙後置作為一個目標。
知的後置特殊目標.SUFFIXES簡單的先決條件名過為特殊目標.SUFFIXES編寫規則加入更多的先決條,您可以後置如︰
.SUFFIXES: .hack .win
把‘.hack' 和.win'到了後置單中。 如果您希望除預設的後置而不是僅僅加後置,那麼您可以為特殊目標.SUFFIXES編寫沒有先決條件的
規則。透種模式,可以完全除特殊目標.SUFFIXES’存在的先決條件著您可以編寫另一個規則加的後置如,
.SUFFIXES: # 刪除預設後置 .SUFFIXES: .c .o .h # 定義自的後置單 標誌-r'或--no-builtin-rules'也能把預設的後置 變數SUFFIXES在make讀入任何makefile檔案之前定義預設的後置。您可以使用特殊目標.SUFFIXES’改變後置,但這不能改變變數SUFFIXES的值
10.8隱含規則搜尋算法
這裡是make為一個目標t搜尋隱含規則的過程。這個過程用於任何沒有命令的雙冒號規則(::)於任何不含命令的
通規則的目標,以於任何不是其它規則目標的先決條件。這個過程也能於來自 隱含規則的先決條件遞迴
程搜尋規則鏈
在本算法中不提任何後置規則(suffix rule),因為後置規則(suffix rule)在makefile檔案讀入轉化為樣式規則
對於是‘archive(member)的資料庫成目標,下述算法重兩次,第一次使用個目標名t’,如果第一次執行 沒有發現規則次使用(member)作為目標t’。
1t中分離出路俓(stem),稱d’,下部n。例如如果‘t’是‘src/foo.o’, 那麼‘d’是‘src/’;‘n’是‘foo.o’。
2所有目標名匹配tn的樣式規則列表如果目標樣式中含有斜線(/) ,則匹配‘t’,否匹配n’。 3 如果列表中有一個規則不是萬用規則從列表中刪除所有最終萬用規則 4 沒有命令的規則也從列表移走 5 對每列表中的樣式規則
1 stems’,也就是和目標樣式中%匹配的tn’部 2使用stems如果目標樣式不引入(include)斜線(/) ,則將‘d’添加在每個先決條件的前
面。
3測試所有的依是否存在或能夠。(如果任何檔案在makefile中作為目標或先決條件 們說應該存。)如果所有先決條件在或能夠立,或沒有先決條件使用規則
6 如果到現沒有發現能使用的規則進一對每一個單中的規則
1 如果規則最終規則繼續一條規則 2 述一樣 3 測試所有的是否存在或能夠立。
4 對於不存在的,按照該算法遞迴查找是否能夠用隱含規則建立。
5 如果所有在或使用隱含規則建立,規則
7如果沒有隱含規則,則如有用於目標‘.DEFAULT’規則,則應用該規則。在情況下,將目標
.DEFAULT的命令t’。
旦找到可以應用的規則,對每一個匹配的目標樣式(無論是‘tn’)使用stems替換%,將得到的檔案名 到執行命令更新目標檔案t’。這些命令執行,把每一個存的檔案名入資料庫標誌 更新時間戳和目標檔案t一樣 如果樣式規則的命令為建立‘t執行自動變數設定為相應的目標和先決條件參閱自動變數)。
11使用make更新資料庫檔案
資料庫檔案引入(include)子檔案的檔案,這些子檔案有自的檔案名般將們稱為成員;資料庫檔案和程式ar一 ,它要用是作為連接的例程庫
11.1資料庫成目標
立的檔案資料庫成員可以在make中用作目標或先決條件。按照下面的模式,您可以在資料庫檔案archive中指定名member的成員︰
archive(member)
架構僅僅在目標和先決條件中使用不能在命令中﹗絕多數程式都不在命令中支援個語法,而且也不 能對資料庫成有程式ar和那些為操作資料庫檔案設的程式才能這樣做。所以合法的更新資料庫成員的
命令一定使用ar如,下述規則表明拷貝檔案hack.o在檔案foolib中建員‘hack.o: foolib(hack.o) : hack.o ar cr foolib hack.o
上,幾所有的資料庫成目標種模式更新的有一條隱含規則為您專更新資料庫成目標。注 意︰如果資料庫檔案沒有程式ar的c標誌是需要的
相同的檔案中同時指定個成員,您可以號中一所有的成如︰ foolib(hack.o kludge.o) 同於︰ foolib(hack.o) foolib(kludge.o) 可以在資料庫成引用中使用shell類型的萬用字元參閱在檔案名中使用萬用字元。例如,‘foolib(*.o)' 展開為在檔foolib中所有以‘.o’結的成員。也許相當於︰‘foolib(hack.o) foolib(kludge.o)'
11.2 資料庫成目標的隱含規則
目標a(m)’表示名為m的成在資料庫檔案a Make為種目標搜尋隱含規則時,是用它另一個的特殊特點︰make為匹配(m)的隱含規則也同時匹配
a(m)’。 該點導致一個特殊的規則它的目標是‘(%)’。該規則透過檔案m拷貝檔案中更新目標a(m)’。例如,它過將檔案‘bar.o’拷貝到檔案‘foo.a’中更新資料庫成員目標‘foo.a(bar.o)’。 如果該規則和其它規則組成鏈,功能十分強大。‘make "foo.a(bar.o)"'(注意使用雙引號了保護圓括可被shell解釋 )即使沒有makefile檔案僅存在檔案bar.c’就可以保證以下命令執行
cc -c bar.c -o bar.o ar r foo.a bar.o rm -f bar.o
這裡make假設檔案bar.o’是檔案參閱隱含規則鏈。 諸如這樣的隱含規則使用自動變數$%編寫的參閱自動變數
資料庫成不能引入(include)路俓(stem)名,但是在makefile檔案中路俓(stem)名有用的。如果您寫一個資料庫成規 則foo.a(dir/file.o)’,make自動使用述命令更新
ar r foo.a dir/file.o
它的結果是拷貝檔案dir/file.o進入名為file.a的檔案中樣的任務時使用自動變數%D%F
11.2.1更新檔案的
用作庫的資料庫檔案通常引入(include)一個名為__.SYMDEF 特殊的成員,員‘__.SYMDEF引入(include)所有 其它成定義的外部符號名的表。更新其它成,您必須更新成員‘__.SYMDEF’,從而使成 __.SYMDEF’可以合適其它成員。成成員‘__.SYMDEF的更新要執行ranlib程式
ranlib archivefile
正常情況下,您應該將該命令到資料庫檔案的規則中,把所有資料庫檔案的成員作為該規則的先決條件。例如︰ libfoo.a: libfoo.a(x.o) libfoo.a(y.o) ... ranlib libfoo.a 上述程式的結果是更新資料庫成員‘x.o',‘y.o', 等等, 然後過執行程式ranlib更新符號索引表表成員‘__.SYMDEF’。 更新成員的規則這裡沒有列出,多數情況下,您可以略它們,使用隱含規則把檔案拷貝到檔案中,具體描述見以前 的內容。 使用GNU ar程式時這不是必要的,因為它自動更新成員‘__.SYMDEF’。
11.3 使用檔案的危險
同時使用並行執行(-j參閱並行執行和檔案應該十小心。如果多個命令同時對相同的資料庫檔案們 相互不知可能破壞檔案。將來的make版本可能對該問題提供一個,即將所有相同資料庫檔案的命令
串行化。但是現下,您必須在編寫的makefile檔案避免問題用其它模式者不使用選項-j
11.4 資料庫檔案的後置規則(suffix rule)
為處理資料庫檔案,您可以編寫一個特殊類型的後置規則(suffix rule)所有後置的展開請參閱舊式的後置規則 (suffix rule)檔案後置規則(suffix rule)在GNU make中已被廢棄,因為用檔案的樣式規則更加通用參閱資料庫成目 標的隱含規則),但是和其它版本的make 編寫用檔案的後置規則(suffix rule),您可以簡單的編寫一個用目標後置.a的後置規則(suffix rule)即可。
如,這裡有一個用於從C語言源檔案更新檔案庫的過後置規則(suffix rule) .c.a: $(CC) $(CFLAGS) $(CPPFLAGS) -c $< -o $*.o $(AR) r $@ $*.o $(RM) $*.o 下面的樣式規則工作完全一樣 (%.o): %.c $(CC) $(CFLAGS) $(CPPFLAGS) -c $< -o $*.o $(AR) r $@ $*.o $(RM) $*.o
上,這僅僅是make看到一個以‘.a作為後置的後置規則(suffix rule)時,它所的工作。任何雙後置規則(suffix rule).x.a' 轉化為一個樣式規則,該樣式規則的目標樣式是‘(%.o)' 先決條件格式是‘%.x'. 您可能要使用.a' 作為一個檔案類型的後置make也以正常模式轉換檔案後置規則(suffix rule)為樣式規則參閱 舊式的後置規則(suffix rule)。這樣一個雙後置規則(suffix rule).x.a' 生兩個樣式規則︰‘(%.o): %.x' 和%.a: %.x'.
12 GNU make的特
這裡是GNU make的特結,於比其它版本的make。我們以4.2 BSD 中的make的特為基準。如果您要編寫一個的makefile檔案,您不要使用這裡列出的make的特點,也不要使用不相失去的特列出的內容
多特在System V 中的make也存
變數VPATH 它特殊的參閱在目錄中搜尋先決條件。這個特點存System V 中的make,但沒有事
證明。4.3 BSD make含有點(據說是仿System V中變數VPATFH的特點)。
引入(include)其它makefile檔案。參閱引入(include)其它makefile檔案使用一個指令引入(include)多個檔案
GNU的展開。
過環境變數可以讀入和通訊參閱環境變數
過變數MAKEFLAGS 在遞迴make時可以遞選項參閱和子make通訊選項
在檔案引用中自動變數$% 設定為成參閱自動變數
自動變數$@, $*, $<, $%,$? 有變體$(@F)和$(@D)。我們把並使用它自動變數$^ 進行了明
展開。參閱自動變數
變數引用參閱變數引用基礎
命令行選項-b'和-m'略。在System V make中,這些選項際起作用
即使指定選項‘-n',‘-q'或‘-t',也能透過變數MAKE執行歸呼叫make的命令。參閱遞迴make。
在後置規則(suffix rule)中支援後置.a'參閱用資料庫檔案的後置規則(suffix rule)。這個特在GNU make中
,因為規則鏈更加通用的特點(參閱隱含規則鏈一個樣式規則用在檔案中安裝
(參閱用於資料庫成員目標的隱含規則)。 在命令中行排列反斜線(\)-新行結合依舊保,當命令列時,它們出現的格式和它們在makefile檔案中基本一樣, 不同之處是去始化空白
下面的特不同版本的make吸收,但哪些版本吸收了哪些不十清楚。
在樣式規則中使用%’。不同版本的make使用了該點。我們不能確認是發明了,但發展
快。參閱定義與重新定義樣式規則
規則鏈以隱含中檔案。這個特點首Stu Feldman 在它的make版本中實現,並用AT&T 版Unix研究
AT&T貝拉驗室的Andrew Hume 在它的mk程式中(這裡稱“傳遞閉合”)。我們不清楚是從
們那裡得到這個特是同時我們己開發出來參閱隱含規則鏈
自動變數引入(include)當前目標的所有先決條件的。我們點也不知參閱自動變數。自動變數$+
變數$^的簡單展開。
"what if" 標誌(GNU make中的-W') Andrew Hume 在mk中發明參閱代替執行命令
並行執行的概多版本的make中,儘System V 或BSD 並沒有實現。參閱執行命令
使用格式替換變變數引用SunOS 4參閱變數引用基礎在GNU make中,這在變換語法和SunOS
4之前由函數patsubst提供。不知威權,因為GNU make 使用函數 patsubst 在 SunOS 4 發布之前。
在命令行前面+有特殊重要的參閱代替執行命令)。 這是由IEEE Standard 1003.2-1992
(POSIX.2)定義的
使用+=語法為變數加值SunOS 4 make參閱為變數值附加文字(text)
語法archive(mem1 mem2...)'在單一資料庫檔案中多個成員來SunOS 4 make.參閱資料庫成目標
-include指令包括makefile檔案且對於不存在的檔案也不產生錯誤。該withSunOS 4 make(但是SunOS 4 make 在單個指令中指定多個makefile檔案) 和SGI make 的sinclude 相同,
剩餘的特點是由GNU make發明
使用-v'或`--version'選項版本和拷貝權
使用-h' 或--help' 選項make的選項
簡單展開型變數參閱變數的兩特特色
在遞迴make時,過變數MAKE自動遞命令行變數參閱遞迴make
使用命令選項-C' 或--directory'變路俓(stem)參閱選項概要
定義多行變數參閱定義多行變數
使用特殊目標.PHONY聲假想(phony)目標AT&T 貝拉驗室Andrew Hume 使用不同的語法在它的mk程式中
實現了該能。這似乎並行的發現。參閱假想(phony)目標
呼叫函數作文字(text)參閱用轉換文字(text)的函數
使用-o'或--old-file'選項假檔案舊檔案參閱避免重新編譯檔案
條件執行。該不同版本make中經實現很長時間了;似乎C與處理程式和類巨集的自
展開,而不是的概參閱makefile檔案中的條件語句
指定引入(include)的makefile檔案的搜尋路俓(stem)參閱引入(include)其它makefile檔案
使用環境變數指定的makefile檔案參閱變數MAKEFILES
檔案名中前導斜線(/) `./' ,因,‘./file' 和file' 一個檔案
使用特搜尋法搜尋如‘-lname的庫先決條件參閱連接庫(Link Libraries)搜尋目錄
後置規則(suffix rule)中的後置引入(include)任何符(參閱舊式的後置規則(suffix rule))。在其它版本的
make中後置必須以‘.’開且不能引入(include)/符。
當前make用的變數MAKWFILES的值參閱遞迴make
將任何在命令行中給出的目標入變數MAKECMDGOALS參閱指定最終目標的參數
指定靜態樣式規則參閱靜態樣式規則
提供vpath搜尋參閱在目錄中搜尋先決條件
提供可算的變數引用參閱變數引用基礎
更新makefile檔案參閱重建makefile檔案System V make 中有常有於該它用
makeSCCS檔案
各種新建的隱含規則參閱隱含規則目錄
內建變數`MAKE_VERSION' 給出make的版本號
13 不相失去的特
其它版本的make程式分特在GNU make中沒有實現。POSIX.2 標 (IEEE Standard 1003.2-1992)規定不需
這些點。
‘file((entry))' 式的目標代一個資料庫檔案的成file員不使用檔案名,而是過一個定義連接
號enty的OBJ檔案。該特點沒有GNU make 吸收因為該非標組件將為make加入資料庫檔案符號表的內部知
參閱更新檔案表。
在後置規則(suffix rule)中以符‘~’結的後置在System V make中有特的含義指和檔案名中沒有~
的檔案通訊的SCCS 檔案例如,後置規則(suffix rule)‘.c~.o'將從名為‘s.n.c'的SCCS檔案中取檔案‘n.o'。
了完全覆蓋,需系列的後置規則(suffix rule)參閱舊式的後置規則(suffix rule)在GNU make中,這種
系列的後置規則(suffix rule)於從SCCS檔案取的兩個樣式規則們可和通用的規則結合成規則鏈
參閱隱含規則鏈 在System V make中, 字元串$$@'又奇特的含義在含有多個規則的先決條件中它代表正在處理的特殊目標。這在 GNU make沒有定義,因為字元串$$'代一個常的字符‘$'使用靜態樣式規則可以實現該的一參閱靜 態樣式規則)。System V make 中的規則 $(targets): $$@.o lib.a 在 GNU make 中可以用靜態樣式規則代替
$(targets): %: %.o lib.a
在System V 和 4.3 BSD make中 過VPATH搜尋參閱為先決條件搜尋目錄)發現的檔案的檔案名
變後加入命令字元串中。我們認為使用自動變數更簡單明了,以不引進點。
在一些Unix make中自動變數$*出現下規則的先決條件中有令的特殊特點︰展開規則的目標
我們不能明白Unix make 在心中對這是怎樣考慮的,它和正常的變數$*定義完全不同。 在一些Unix make中,隱含規則搜尋(參閱使用隱含規則)明顯是為所有目標做的,而不僅僅為那些沒有命令的目標。 這意著︰
foo.o: cc -c foo.c
在Unix make 有foo.o' 依靠‘foo.c'。我們認樣的用法易導致亂。Make中先決條件的
至少對於GNU make是這),做這樣的事情不合
GNU make引入(include)任何編譯與處理EFL程式的隱含規則。如果我們使用EFL,我們意把
加入 在 SVR4 make中一條後置規則(suffix rule)可以不含命令它的處理模式和它含有空命令的處理模式一樣參閱使用空 命令)。如︰ .c.a: 重載內建的後置規則(suffix rule).c.a' 。我們得對沒有命令的規則簡單的為目標加先決條件更為簡。上述例子和 在GNU make中例的行為相同。
.c.a: ;
版本的make 呼叫shell使用-e'標誌,而不是‘-k'標誌 (參閱測試程式編譯)標誌-e'告訴shell 一程式執行狀態就立即退出。我們認根據每一命令行是否需要特殊處理接寫入命令中更為清楚。
14 makefile檔案
章描述為GNU make編寫makefile檔案的使用Automake將幫助您按照這些慣例編寫makefile檔案
14.1 makefile檔案的通用
任何makefile檔案都應該引入(include)
SHELL = /bin/sh
避免在系統中變數SHELL可能環境中值的麻煩。(在GNU make中這從來不是問題。)
不同的make程式有不同的後置單和隱含規則,這可能造成或錯誤的行為。因此最設定後置該清單中,僅僅引入(include)在特定makefile檔案中使用的後置如︰
.SUFFIXES: .SUFFIXES: .c .o
一行後置,第行定義makefile中可能隱含規則使用的後置
要假設‘.' 是命令執行的路俓(stem)。當您在建程式過程中,需要執行僅是您程式中一分的程式時,請確認如 果該程式要建程式的一分使用./’,如果該程式是源變的分使用$(srcdir)’。沒有這些前,僅僅
當前路俓(stem)索。目錄build directory )‘./目錄(source directory) $(srcdir)區別重要的,因為用戶可以configure中使用--srcdir選項建一個單的目錄。下面的規則 foo.1 : foo.man sedscript sed -e sedscript foo.man > foo.1 如果的目錄不是源目錄將失,因為檔案foo.mansedscript目錄下。
在使用GNU make時,依靠變數VPATH搜尋檔案在單個檔案情況下可以很好工作,因為make中自 動變數$<’中含有檔案的在路俓(stem)。(許多版本的make在隱含規則中設值變數$<’。)如這樣的 makefile檔案目標 foo.o : bar.c $(CC) -I. -I$(srcdir) $(CFLAGS) -c bar.c -o foo.o 被替換為 foo.o : bar.c $(CC) -I. -I$(srcdir) $(CFLAGS) -c $< -o $@
這是了保證變數VPATH’正確的工作目標含有多個先決條件時,使用名$(srcdir)’是最容保證該規則 很好工作的如,以上例子中的目標foo.l寫為
foo.1 : foo.man sedscript sed -e $(srcdir)/sedscript $(srcdir)/foo.man > $@
GNU的分類中通常引入(include)一些不是源檔案的檔案──如,‘Info檔案、從Autoconf, Automake, Bison 或 Flex中輸 的檔案等。這些檔案在檔案目錄下,們也應該檔案目錄下,不應該在建造目錄下。因此makefile規則檔 案目錄更新它們。
然而,如果一個檔案沒有在分類中出現,makefile檔案不應把到源檔案目錄下,因按照通常情況一個程式 ,不應該以任何模式更改源檔案目錄
的建安裝目標至少(以的子目標)可在並行的make中正確的工作
14.2 makefile檔案的工具
編寫在shell sh中執行而不在csh中執行的makefile檔案命令(shell的如‘configure),不要使用任何ksh或 bash的特殊特點。安裝configure本和Makefile 規則除下面列出工具外不應該接使用其它的任何工具 cat cmp cp diff echo egrep expr false grep install-info ln ls mkdir mv pwd rm rmdir sed sleep sort tar test touch true
程式gzip在dist規則中使用使用用於這些程式的通用選項如,不要使用mkdir -p'可能比便,但是其它多數系統卻不支援
避免在makefile中號連接錯的注意,因為一些系統不支援
安裝的Makefile 規則可以使用編譯器以關的程式,但應該過make變數使用它們,這可以方便 使用的進行替換。這裡按照我們的理編寫一程式 ar bison cc flex install ld ldconfig lex make makeinfo ranlib texi2dvi yacc 使用述make變數執行這些程式:
$(AR) $(BISON) $(CC) $(FLEX) $(INSTALL) $(LD) $(LDCONFIG) $(LEX) $(MAKE) $(MAKEINFO) $(RANLIB) $(TEXI2DVI) $(YACC)
使用ranlib或ldconfig,您應該確如果系統不存在要使用的程式不會起任何作用。安排忽略這些命令生的錯誤且列告訴戶該命令執行不意著存在問題。(AutoconfAC_PROG_RANLIB'巨集這方面幫助 您。)如果您使用號連接,對於不支援號連接的系統您應該有一個低效率執行
附加的工具也可過make變數使用 chgrp chmod chown mknod 它在makefile中本中),您知引入(include)這些工具的特定系統中它都可以很好的工作
14.3 指定命令的變數
Makefile檔案應該為重載的特定命令選項等提供變數 特別在執行大部分工具時都應該應用變數,如果您要使用程式Bison, 名為BISON 的變數它的預設值設定為 BISON = bison’,您需要使用程式Bison時,您可以使用$(BISON)引用 檔案工具ln, rm, mv等等,不必要使用種模式引用,因為用戶不可能使用別的程式替換它們。 一個程式變數應該和用於向該程式提供選項的選項變數一起提供。在程式名變數後添FLAGS'表示向該程式提供 選項的選項變數--例如, BISONFLAGS(名為CFLAGS的變數C編譯器提供選項, 名為YFLAGS的變數yacc提供選項 名為LFLAGS的變數lex提供選項等是這個規則例外,但因為它們是以我們保們。) 在任何進行預處理的編 譯命令中使用變數CPPFLAGS 任何進行連接的編譯命令中使用變數LDFLAGS 和直接使用程式ld一樣 對於C編譯在編譯特定檔案時必須使用的選項,不應引入(include)在變數CFLAGS中,因為用戶希望們能夠的 指定變數CFLAGS。 要獨立於變數CFLAGS安排向C編譯器傳這些必要的選項, 可以將這些選項寫入編譯命令行中或隱 含規則的定義中,如下 CFLAGS = -g ALL_CFLAGS = -I. $(CFLAGS) .c.o: $(CC) -c $(CPPFLAGS) $(ALL_CFLAGS) $< 變數CFLAGS中包括選項-g’,因為它對於編譯並不是必需,您可以認為它預設推薦的選項。如果據包
立使用GCC作為編譯器,則變數CFLAGS中包括選項‘-o’,而且以它為預設值。 將變數CFLAGS到編譯命令的最後,在引入(include)編譯選項其它變數的後,因此用戶可以使用變數CFLAGS對其 它變數進行重載。
每次呼叫C編譯器都用到變數CFLAGS ,無論進行編譯或連接都一樣。 任何Makefile檔案都定義變數INSTALL,變數INSTALL是將檔案安裝到系統中的基本命令。 任何Makefile檔案都定義變數INSTALL_PROGRAM 和INSTALL_DATA,(它們的預設值都是$(INSTALL)。) 在實安裝程
時,不論可執行程式或執行程式般都使用它作為命令。下面是使用這些變數的例子 $(INSTALL_PROGRAM) foo $(bindir)/foo $(INSTALL_DATA) libfoo.a $(libdir)/libfoo.a
您可以意將變數DESTDIR預先設定為目標檔案名。這許安裝程式建後在目標檔案系統安裝檔案的 快照。不makefile檔案中設定變數DESTDIR,也不要引入(include)在安裝檔案中用變數DERSTDIR改述例子
$(INSTALL_PROGRAM) foo $(DESTDIR)$(bindir)/foo $(INSTALL_DATA) libfoo.a $(DESTDIR)$(libdir)/libfoo.a
安裝命令中一使用檔案名而不是路俓(stem)名作為個參數。對每一個安裝檔案使用單的命令
14.4安裝路俓(stem)變數
安裝目錄變數命名在非準地方安裝也很容易,這些變數的標名字下面介紹。安裝目錄依據 檔案系統佈局變數的變體已在SVR4, 4.4BSD, Linux, Ultrix v4, 以及其它代作業系統中使用 以下兩個變數設定安裝檔案的目錄所有的其它安裝目錄都是其中一個的子目錄沒有任何檔案可以直接安裝
兩個目錄下。
`prefix' 構造以下列舉變數的預設值變數prefix預設值是‘/usr/local'。建的GNU系統時,變數prefix的預設值 空值,‘/usr' 是符號連接符‘/'。(如果您使用Autoconf,應將它寫為‘@prefix@'。)使用不同於程式變數prefix的值 執行make install',不會重新編譯程式
`exec_prefix' 構造以下列舉變數的預設值變數exec_prefix預設值$(prefix). (如果您使用Autoconf,應將它寫為 `@exec_prefix@'。) 一般情況下。變數$(exec_prefix) 用於存引入(include)機器特定檔案的目錄,(如可執行檔案和例程),變數$(prefix) 其它目錄。使用不同於程式變數exec_prefix的值執行make install',不會重新編譯程
執行程式安裝以下目錄中 `bindir'
這個目錄 下用 於安裝用 戶可 以執行的可 執行程式 。其 正常 的值 是‘/usr/local/bin',但 是使用時應 將它寫為 ‘$(exec_prefix)/bin'。 (如果您使用Autoconf, 應將它寫為‘@bindir@'。)
`sbindir'
這個目錄下用於安裝從shell中呼叫執行的可執行程式。它僅僅對系統理員有作用。它的正常的值是‘/usr/local/sbin',但 是使用時應將它寫為‘$(exec_prefix)/sbin'。 (如果您使用Autoconf, 應將它寫為‘@sbindir@'。)
`libexecdir'
這個目錄下用於安裝其它程式呼叫的可執行程式。其正常的值是‘/usr/local/libexec',但是使用時應將它寫為 ‘$(exec_prefix)/libexec'。(如果您使用Autoconf, 應將它寫為‘@libexecdir@'。)
程式執行使用的數檔案分為兩類
程式可以正常更的檔案和不能正常更的檔案(雖然戶可以其中的一分檔案)。
架構關檔案這些檔案所有機器系相關檔案僅僅可以相同類型機器、業系統的檔 案其它永遠不能兩個機器的檔案
這可產不同可能性。我們使用體系相關的檔案,當然OBJ檔案和庫檔案除外。使用其它體系無關的數檔案更加簡且,這做也不是很難
以,這裡有 Makefile變數用指定路俓(stem)
`datadir'
這個目錄下 用 於安 裝 只讀型體系無關 數據檔 案。 其 正常 的值是 ‘ /usr/local/share' ,但 是 使用時應將它寫 為 ‘$(prefix)/share'。(如果您使用Autoconf, 應將它寫為‘@datadir@'。) 作為例外,參閱下述的變數‘$(infodir)'和$(includedir)'
`sysconfdir'
個目錄於安裝從單個機器的只讀數檔案,這些檔案是︰配置主的檔案。郵服務、路配置檔案,/etc/passwd',等等都於這裡的檔案所有目錄的檔案都是平常的ASCII文字(text)檔案常的值是 ‘/usr/local/etc', 但是使用時應將它寫為‘$(prefix)/etc'. (如果您使用Autoconf, 應將它寫為‘@sysconfdir@'.) 不要在這裡安 裝可執行檔案們可能於‘$(libexecdir)'或‘$(sbindir)')。也不要在這裡安裝那些在使用要更的檔案(這些程式
於改系統拒絕的配置)。們可能於‘$(localstatedir)'
`sharedstatedir' 個目錄於安裝程式執行中要生變化的體系無關數檔案常的值是‘/usr/local/com',但是使用時應將它寫$(prefix)/com' (如果您使用Autoconf, 應將它寫為‘@sharedstatedir@')
`localstatedir' 個目錄於安裝程式執行中要生變化的數檔案。但特定的機器。永遠不需要在目錄檔案 配置程式選項 ;將這些 配 置訊息 放 在 分的 檔案中 ,這些檔 案$(datadir)'或$(sysconfdir)'中
$(localstatedir)'常的值是‘/usr/local/var',但是使用時應將它寫為$(prefix)/var' (如果您使用Autoconf, 應將它寫為‘
@localstatedir@'。)
`libdir' 個目錄於存OBJ檔案和庫的OBJ。不要在這裡安裝可執行檔案們可能應於‘$(libexecdir)'變數libdir 常的值是‘/usr/local/lib',但是使用時應將它寫為$(exec_prefix)/lib'(如果您使用Autoconf, 應將它寫為 ‘@libdir@')
`infodir'
這個目錄下用於安裝軟件的 Info 檔案。預設情況下其值是‘/usr/local/info',但是使用時應將它寫為‘$(prefix)/info'. ( 如果您使用Autoconf, 應將它寫為‘@infodir@'.)
`lispdir' 這個目錄下用於安裝軟件的Emacs Lisp 檔案。預設情況下其值是 ‘/usr/local/share/emacs/site-lisp',但是使用時應將它 寫為‘$(prefix)/share/emacs/site-lisp'。如果您使用Autoconf, 應將它寫為‘@lispdir@'。為了保證‘@lispdir@'工作,您需要將 以下幾行加入到您的‘configure.in'檔案中︰
lispdir='${datadir}/emacs/site-lisp' AC_SUBST(lispdir)
`includedir' 個目錄於安裝程式中C#include'預處理指令引入(include)的檔案常的值是‘/usr/local/include',但是 使用時應將它寫為$(prefix)/include'。 (如果您使用Autoconf, 應將它寫為‘@includedir@'。) 除GCC多數編譯器不 目錄/usr/local/include'搜尋檔案,因安裝模式僅僅適GCC。有時,這也不是問題,因為一分庫檔案僅僅 依靠GCC才能工作。但也有一分庫檔案依靠編譯器,們將檔案安裝到兩個地方,一個變數 includedir 指定另一個變數oldincludedir指定
`oldincludedir'
這個目錄下用於安裝‘#include'的頭檔案,這些頭檔案用於除GCC外的其它C語言編譯器。其正常的值是‘/usr/include'。( 如果您使用Autoconf, 應將它寫為 ‘@oldincludedir@'。) Makefile命令變數oldincludedir 的值是否為空,如果是空值,它們 不在試使用它,它們還刪除二次安裝的頭檔案。一個軟件在該目錄下替換經存在的頭檔案,除頭檔案來 源於同一個軟件。例如,如果您的套裝件Foo 提供一個頭檔案‘foo.h',則它在變數oldincludedir指定的目錄下安裝 的條件是 (1) 這裡沒有檔案‘foo.h' 或 (2) 來源於件Foo的頭檔案‘foo.h'已經在該目錄下存在。要檢查頭檔案 ‘foo.h'是否來自於軟件Foo,將一個magic字元串到檔案中—作為命令的一部分--然後使用正則規則(grep)查找 該字元串。
Unix風格的幫助檔案安裝以下目錄中 `mandir'
安裝該軟件的幫助(如果有)目錄。其正常的值是‘/usr/local/man',但是使用時應將它寫為‘$(prefix)/man'。 ( 如果您使用Autoconf, 應將它寫為‘@mandir@'。)
`man1dir' 個目錄於安裝第幫助。常的值是‘$(mandir)/man1' `man2dir' 個目錄於安裝第幫助。常的值是‘$(mandir)/man2' `...' 將任何GNU 體的要文檔作為幫助。應該編寫使用手冊。幫助僅僅是在Unix上方便執行GNU的執行程式 `manext' 檔案名表示對安裝幫助展開。它引入(include)一定的適當的數字,正常為1’。 `man1ext' 檔案名表示對安裝幫助分的展開。 `man2ext' 檔案名表示對安裝幫助分的展開。 `...' 使用這些檔案名代替`manext'。如果該件的幫助安裝使用手冊的多個章節。 最後您應該設定一變數
`srcdir'
這個目錄下用於安裝要編譯的原檔案。該變數正常的值由shell本configure入。(如果您使用Autoconf, 應將它寫為 ‘srcdir = @srcdir@'.)
如︰
#於安裝路俓(stem)的 # 注意︰該您開安裝時必須存
prefix = /usr/local exec_prefix = $(prefix) # 這裡置`gcc'命令呼叫的執行檔案 bindir = $(exec_prefix)/bin # 這裡置編譯使用的目錄 libexecdir = $(exec_prefix)/libexec #這裡置Info檔案 infodir = $(prefix)/info
如果您的程式要在標指定的目錄中安裝大的檔案,將該程式的檔案指定的子目錄中要的 。如果您做,您應該安裝規則建立這些子目錄。 不要期的變數值中包括這些子目錄,對於安裝目錄使用一變數名的法使用戶能夠對於不同
GNU件指定精確的值使法有用所有的必須使用們能夠的工作
14.5用目標
所有的GNU程式中在makefile中下列目標
`all' 編譯個程式。這應該是預設的目標。該目標不必重建文檔檔案,Info檔案正常情況下應該包括在各個發布的檔案中
,DVI檔案有在明確請情況下才重建預設時,make規則編譯和連接使用選項‘-g',所以程式調只是像徵性的。 對於不意缺幫助的用戶如果們希望將可執行程式和幫助開,可以從離出可執行程式
`install' 編譯程式並將可執行程式、庫檔案拷貝使用的檔案名下。如果是證實程式是否適合安裝的簡單測試,則 目標應該執行測試程式。不要在安裝時離可執行程式魔鬼可能心那些使用install-strip目標離可執行程 式的。如果這是可行的,編寫的install目標規則不應該更改程式建的目錄下的任何東西,僅僅提供‘make all'一
能完。這是了方便命名和在其它系統安裝程式,如果安裝程式的目錄不存,該命令應能所有這 些目錄,這包括變數prefix和exec_prefix特指定的目錄和所有要的子目錄。完該任務助下面描述的目標 installdirs在所有安裝幫助的命令使用-'使make 能夠略這些命令生的錯誤,這可以確保在沒有Unix幫助 系統上安裝該時能夠進行。安裝Info檔案的使用變數$(INSTALL_DATA)Info檔案拷貝變數$(infodir)'中參閱指定命令的變數),如果 install-info程式在則執行它install-info是一個編輯Info‘dir'檔案的程式,
可以為Info檔案加或更新選單Texinfo裝軟件的一這裡有一個安裝Info檔案的例子
$(DESTDIR)$(infodir)/foo.info: foo.info $(POST_INSTALL) # 可能.’下有新的檔案在srcdir中沒有
-if test -f foo.info; then d=.; \ else d=$(srcdir); fi; \ $(INSTALL_DATA) $$d/foo.info $(DESTDIR)$@; \
#如果 install-info程式存在則執行它。 # 使用if'代替在命令行-' # ,我們可以注意到執行install-info生的真正錯誤 # 我們使用$(SHELL) -c' 是因為在一shell中 # 遇知的命令不會執行失
if $(SHELL) -c 'install-info --version' \ >/dev/null 2>&1; then \ install-info --dir-file=$(DESTDIR)$(infodir)/dir \ $(DESTDIR)$(infodir)/foo.info; \
else true; fi
在編寫install目標時,您必須把所有的命令︰正常的命令 安裝前命令和安裝後命令參閱安裝命令分類
`uninstall' 刪除所有安裝的檔案install目標拷貝的檔案。該規則不應更改編譯產生的目錄,僅僅刪除安裝檔案的目錄。 命令安裝命令一樣分為參閱安裝命令分類
`install-strip' 和目標install類,但安裝時僅僅離出可執行檔案情況下,該目標的定義常簡單
install-strip: $(MAKE) INSTALL_PROGRAM='$(INSTALL_PROGRAM) -s' \ install
情況下我們不離可執行程式進行安裝,只有您確這些程式不會產生問題時才能這離安裝一個 執行的執行檔案同時存那些合存在BUG的執行檔案而易見的
`clean' 刪除所有當前目錄的檔案,這些檔案情況下是那些‘程式的檔案。不要刪除那些記錄配置的檔案 同時也應該保那些‘程式’能夠修改的檔案,正情況下要刪除的那些檔案包括這些檔案,因發布檔案這些檔案一。如果‘.dvi'檔案不是檔案發布檔案的一則使用目標clean’將同時刪除.dvi'檔案
`distclean' 刪除所有當前目錄的檔案,這些檔案情況下是那些‘程式配置程式的檔案。如果您不解 程式,‘程式’不會立任何其它檔案,‘make distclean'將僅在檔案發布檔案中下原有的檔案
`mostlyclean' 和目標clean'類,但是避免刪除們正情況下不編譯的檔案如,GCC的目標mostlyclean刪除檔案 libgcc.a',因為在多數情況下都不需要重新編譯
`maintainer-clean' 乎在當前目錄刪除所有能夠使用makefile檔案可以重建的檔案使用目標刪除的檔案包括使用目標distclean,刪除 的檔案加上從Bison生的C語言源檔案和標誌、 Info檔案等等。我們說“幾乎所有檔案”的原因是執行命令‘make maintainer-clean'刪除configure',即使configure'可以使用Makefile檔案建立。地說,執行make maintainer-clean'刪除為執行configure'程式的的所有檔案。這是執行make maintainer-clean' 刪除所有能夠重新建檔案不能刪除的一類檔案目標maintainer-clean'由該件的養護程式使用,不能 通用使用。您可以使用特殊的工具重建目標make maintainer-clean'刪除的檔案。因這些檔案情況下引入 (include)在發布的檔案中,我們們是否重建。如果您發現您需對全部發布的檔案重新,您不能
我們。幫助make 的用戶意到這點,目標maintainer-clean 應以以下兩行為
@echo‘該命令僅僅養護程式;’ @echo它刪除的所有檔案都能使用特殊工具重建。’
`TAGS' 更新程式的標誌表。
`info' 要的Info檔案編寫下面規則
info: foo.info
foo.info: foo.texi chap1.texi chap2.texi $(MAKEINFO) $(srcdir)/foo.texi
您必須在makefile檔案中定變數MAKEINFO。它將執行makeinfo程式,該程式是發布程式中Texinfo的一部分。正情況 下,一個GNU發布程式和Info檔案一立,這意Info檔案於源檔案的目錄下。當一個 般情況下,make更新Info檔案,因為它更新最新了。
`dvi' 建立DVI檔案用更新Texinfo文檔如︰
dvi: foo.dvi
foo.dvi: foo.texi chap1.texi chap2.texi $(TEXI2DVI) $(srcdir)/foo.texi
您必須在makefile檔案中定義變數TEXI2DVI執行程式texi2dvi,該程式是發布的Texinfo一么僅僅編寫依靠 檔案GNU make提供命令者必選其一
`dist' 為程式建一個tar檔案tar檔案可以將其中的檔案名子目錄名,這些子目錄名可以是於發布件 名。另外,這些檔案名中也可以引入(include)版本號如,發布的GCC 1.40版的tar檔案的子目錄為gcc-1.40'
便立合適的子目錄名,如使用in或cp作為子目錄在它下面安裝適當的檔案,然tar檔案 到這些子目錄中使用gzip壓縮這些tar檔案,例如,實的GCC 1.40版的發布檔案叫‘gcc-1.40.tar.gz'。目標dist明顯的依所有的發布檔案中不是源檔案的檔案應確保發布中的這些檔案更新參閱GNU標中建立發布
`check' 執行自查。戶應該在執行測試之前,應該先建程式,但不必安裝這些程式;您應該編寫一個自測試程式 在程式立但沒有安裝時執行
以下目標建使用,對於各種程式它很有用
installcheck
執行自查。用戶應該在執行測試之前,應該先建立、安裝這些程式。您不因該假設‘$(bindir)'在搜尋路俓(stem)中
installdirs
加名為‘installdirs'目標對於檔案要安裝的目錄它們目錄分有用mkinstalldirs'是專樣處理便編寫的;您可以在Texinfo件中找到,您可以樣使用規則
# 確保所有安裝目錄(例 $(bindir)) # 都實存在,如果沒有則建立它們。
installdirs: mkinstalldirs $(srcdir)/mkinstalldirs $(bindir) $(datadir) \ $(libdir) $(infodir) \ $(mandir)
規則並編譯的目錄僅僅立安裝目錄
14.6 安裝命令分類
編寫安裝目標,您必須將所有命令分為︰正常的命令、安裝前命令和安裝後命令
正常情況下,命令把檔案動到合適的地方,並設定它們的模式。它們不會改變任何檔案,僅僅把它們從軟件中抽取出來。 安裝前命令和安裝後命令可能更改一些檔案,如,它們編輯配置檔案後資料庫檔案。 安裝前命令在正常命令之前執行,安裝後命令在正常命令執行後執行。 安裝後命令最普通的用是執行install-info程式。 這種工作不能由正常命令完成,因為它更改了一個檔案(Info 目錄) ,該檔案不能全部、單獨從裝軟件中安裝。它是一個安裝後命令,因為它需要在正常命令安裝件中的Info檔案 後才能執行。
多程式不需安裝前命令,但是我們提供這個特點,以便時可以使用
將安裝規則的命令分為,應在命令中入category lines分類行)。 分類行指定了下面述的命令的類 分類行引入(include)一個Tab、一個特殊的make變數引用,以釋。您可以使用個變數,每一個變數對
一個類變數名指定分類行不能出現下普通的執行檔案中,因這些make變數由正常的定義(您也不 應在makefile檔案中定義)。
這裡種分類行釋解釋了它的含義
$(PRE_INSTALL) # 以下是安裝前命令 $(POST_INSTALL) # 以下是安裝後命令 $(NORMAL_INSTALL) # 以下是正常命令 如果安裝規則沒有使用分類行則在一個分類行出現之前的所有命令都是正常命令。如果您沒有使用任何 分類行則所有命令都是正常命令 這是安裝的分類行 $(PRE_UNINSTALL) #以下是安裝前命令 $(POST_UNINSTALL) #以下是安裝後命令 $(NORMAL_UNINSTALL) #以下是正常命令
安裝前命令的型用法是從Info目錄刪除全部內容 如果目標install或 uninstall 有先決條件作為安裝程式的次程序,那麼您應該使用分類行先一個先決條件的命令
使用分類行目標的命令。無論哪一個先決條件執行,這種模式都能保證每一條命令到了正確的分 類中
安裝前命令和安裝後命令除了對於下述命令外,不能執行其它程式 basename bash cat chgrp chmod chown cmp cp dd diff echo egrep expand expr false fgrep find getopt grep gunzip gzip hostname install install-info kill ldconfig ln ls md5sum mkdir mkfifo mknod mv printenv pwd rm rmdir sed sort tee test touch true uname xargs yes
按照這種模式分命令的原因是二進制軟件典型的進制軟件包括所有執行檔案、必須安裝的其 它檔案它自安裝檔案──進制不需要執行任何正常命令。但是安裝進制要執行 安裝前命令和安裝後命令造二進制件的程式安裝前命令和安裝後命令工作。這裡有一個安裝前命令的 make -n install -o all \ PRE_INSTALL=pre-install \ POST_INSTALL=post-install \ NORMAL_INSTALL=normal-install \ | gawk -f pre-install.awk
這裡檔案pre-install.awk'可能包括 $0 ~ /^\t[ \t]*(normal_install|post_install)[ \t]*$/ {on = 0} on {print $0} $0 ~ /^\t[ \t]*pre_install[ \t]*$/ {on = 1}
安裝前命令的結果檔案安裝二進制軟件的一分shell本一樣執行
15 快速
這是對指令文字(text)作函數GNU make能夠的變數。對於其方面參閱特殊的內建目標名 隱含規則目錄選項概要
這裡是GNU make別的指令的結︰
define variable endef
定義多行遞迴展開型變數參閱定義固定次序的命令
ifdef variable ifndef variable ifeq (a,b) ifeq "a" "b" ifeq 'a' 'b' ifneq (a,b) ifneq "a" "b" ifneq 'a' 'b' else endif
makefile檔案中的條件展開,參閱makefile檔案中的條件語句
include file
-include file sinclude file
引入(include)其它makefile檔案參閱引入(include)其它makefile檔案
override variable = value override variable := value override variable += value override variable ?= value override define variable endef
定義變數、對以前的定義重載、以在命令行中定義的變數重載參閱撤銷(override)指令
export
告訴make預設子過程輸出所有變數參閱與子make通訊的變數
export variable export variable = value export variable := value export variable += value export variable ?= value unexport variable
告訴make是否向子過程輸出一個特殊的變數與子make通訊的變數
vpath pattern path
定搜尋匹配%’樣式的檔案的路俓(stem)參閱vpath指令
vpath pattern
以前pattern指定的所有搜尋路俓(stem)
vpath
以前用vpath指令指定的所有搜尋路俓(stem)
這裡是操作文字(text)函數的結,參閱文字(text)轉換函數
$(subst from,to,text)
text中用to代替from’,參閱字元串替換與分析函數
$(patsubst pattern,replacement,text)
text中用replacement代替匹配pattern參閱字元串替換與分析函數
$(strip string)
字元串中移多餘的空格參閱字元串替換與分析函數
$(findstring find,text)
findtext中的參閱字元串替換與分析函數
$(filter pattern...,
text)
text中選匹配pattern的字參閱字元串替換與分析函數
$(filter-out pattern...,
text)
text中選匹配pattern的字參閱字元串替換與分析函數
$(sort list)
將‘list中的字字母順並刪除重的字參閱字元串替換與分析函數
$(dir names...)
檔案名中抽取路俓(stem)名參閱檔案名函數
$(notdir names...)
檔案名中抽取路俓(stem)參閱檔案名函數
$(suffix names...)
檔案名中抽路俓(stem)參閱檔案名函數
$(basename names...)
檔案名中抽取基本檔案名參閱檔案名函數
$(addsuffix suffix,names...)
names中的個字加後置參閱檔案名函數
$(addprefix prefix,names...)
names中的個字參閱檔案名函數
$(join list1,list2)
連接兩個並行的字參閱檔案名函數
$(word n,text)
從‘text中抽n個字參閱檔案名函數
$(words text)
text中字的數目參閱檔案名函數
$(wordlist s,e,text)
text中se之間的字參閱檔案名函數
$(firstword names...)
names…’中的一個字參閱檔案名函數
$(wildcard pattern...)
匹配shell檔案名樣式的檔案名參閱wildcard函數
$(error text...)
函數執行時,make生訊息text命錯誤參閱控制make的函數
$(warning text...)
函數執行時,make生訊息text的警告。參閱控制make的函數
$(shell command)
執行shell命令並回它的輸出。參閱函數shell
$(origin variable)
回make變數variable的定義訊參閱函數origin
$(foreach var,words,text)
將清單words中的一個字對應後接var中的一個字,將結果在text中參閱函數foreach
$(call var,param,...)
使用對$(1), $(2)...對變數算變數 var ,變數$(1), $(2)...分代替參數 param 第一個、第個…的值。參閱函數call。 這裡是對自動變數的結,完整的描述參閱自動變數。
$@ 目標檔案名
$% 目標資料庫成員時,表示目標成
$< 第一個先決條件名
$? 所有目標的先決條件的名字名字之間用空格開。對於為資料庫成員的先決條件,能使用命名的成員。參 閱使用make更新資料庫檔案
$^ $+
所有先決條件的名字名字之間用空格開。對於為資料庫成員的先決條件,能使用命名的成員。參閱使用make更新 資料庫檔案變數 $^ 略了的先決條件,而變數 $+按照原來次序
$* 和隱含規則匹配的俓(stem)參閱樣式匹配
$(@D) $(@F) 變數$@.中的路俓(stem)分和檔案名
$(*D) $(*F) 變數$*中的路俓(stem)分和檔案名
$(%D)
$(%F) 變數$%中的路俓(stem)分和檔案名
$(<D) $(<F) 變數$<中的路俓(stem)分和檔案名
$(^D) $(^F) 變數$^中的路俓(stem)分和檔案名
$(+D) $(+F) 變數$+中的路俓(stem)分和檔案名
$(?D) $(?F)
變數$?中的路俓(stem)分和檔案名
以下是GNU make使用變數
MAKEFILES 次呼叫make要讀入的Makefiles檔案參閱變數MAKEFILES
VPATH 當前目錄下不能找到的檔案搜的路俓(stem)參閱VPATH: 所有先決條件的搜尋路俓(stem)
SHELL 系統預設命令解釋程式名通常`/bin/sh'。您可以在makefile檔案中設值變數SHELL變執行程式使用的shell參閱執行 命令
MAKESHELL 變數MS-DOSmake使用的命令解釋程式名,該變數的值變數SHELL的值參閱執行命令
MAKE 呼叫的make名在命令行中使用變數有特殊的參閱變數MAKE的工作模式
MAKELEVEL 遞迴的數(子makes)參閱與子make通訊的變數
MAKEFLAGS make提供標誌。您可以在環境或makefile檔案中使用變數設定標誌參閱與子make通訊的變數。在命令行中不能 使用變數,應為它的內容不能在shell中正確引用,但遞迴make過環境子make
MAKECMDGOALS 目標在命令行中提供給make的設定變數make的行為沒有任何影響參閱特目標的參數 CURDIR 設定當前工作目錄的路俓(stem)名參閱遞迴make SUFFIXES 在讀入任何makefile檔案之前的後置
.LIBPATTERNS
定義make搜尋的庫檔案名,以搜尋次序參閱連接庫(Link Libraries)搜尋目錄
16 make生的錯誤
這裡是您可以看到make多數通錯誤,以及它的含義和修正make生的錯誤不是致命的,如在命令本行前面存情況下,和在命令行使用選向‘-k情況下 生的錯誤都不是致命錯誤使用字元串***將產命的錯誤 錯誤訊前面都使用,前的內容是產生錯誤的程式名或makefile檔案中在錯誤的檔案名和引入(include)錯誤 的行的行號和述的錯誤單中略了普通的 `[foo] Error NN' `[foo] signal description'
這些錯誤並不是真的make的錯誤它們意著make呼叫的程式狀態值,錯誤碼(Error NN),這種情況make解常模式退出(類型),參閱命令錯誤。如果中沒有附加***子過程,但
makefile檔案中的條規則有特殊,因此make忽略該錯誤 `missing separator. Stop.' `missing separator (did you mean TAB instead of 8 spaces?). Stop.' 這意make在讀取命令行到不能的內容GNU make 檢查各種分隔(:, =,TAB等) 從而幫助確定它在 命令行中遇到了什麼類型的錯誤。這意味著,make不能發現一個合法的分隔符。出現該訊息的最可能的原因是您(或許 的編輯器,大部ms-windows的編輯器)在命令行進使用空格代替Tab。這情況下,make使用 述的第二生錯誤訊息一定切記,任何命令行都以Tab開始,個空格也不算數參閱規則的語法 `commands commence before first target. Stop.' `missing rule before commands. Stop.' 這意在makefile中似乎命令行︰以Tab字符開,但不是一個法的命令行如,一個變數的賦)。任何 命令行必須和一定的目標相聯繫。產第二種的錯誤訊息一行的一個非空白字為分號make對此解釋是您 了規則中的"target: prerequisite" 參閱規則的語法 `No rule to make target `xxx'.' `No rule to make target `xxx', needed by `yyy'.' 這意make決定必須一個目標,但卻不能在makefile檔案中發現任何立該目標的指令包括具體規則和隱 含規則。如果您希望建立該目標,您需要另外為改目標編寫規則。其它關於該問題原因可能是makefile檔案稿 檔案名錯破壞了源檔案樹一個檔案不能按照畫重建,僅僅由於一個先決條件的問題)。 `No targets specified and no makefile found. Stop.' `No targets. Stop.'
前者意著您沒有為命令行提供要建的目標make不能讀入任何makefile檔案後者意著一些makefile檔案被找到,沒有引入(include)預設目標命令行GNU make在情況下無可做。參閱指定makefile檔案的參數
`Makefile `xxx' was not found.' `Included makefile `xxx' was not found.' 在命令行中指定一個makefile檔案(前者)或引入(include)的makefile 檔案者)沒有找到。 `warning: overriding commands for target `xxx'' `warning: ignoring old commands for target `xxx'' GNU make命令在一個規則中能對一個命令使用一次(雙冒號規則(::)除)。如果您為一個目標指定一個命令,而 命令在目標定義定義過,這告就會產;第二個訊表明設定的命令將改以前對該命令的設定 參閱具有多條規則的目標 `Circular xxx <- yyy dependency dropped.'
這意make檢一個相互依靠一個循在跟目標xxx的先決條件yyy 時發現,先決條件yyy的先決條件中一個xxx為先決條件
`Recursive variable `xxx' references itself (eventually). Stop.' 這意著您定義一個遞迴性)make變數xxx,當展開時,引用它自。無論對於簡單展開型變數(:=)或
定義+=),這也都是不能參閱使用變數 `Unterminated variable reference. Stop.' 這意著您在變數引用或函數呼叫忘記寫右括 `insufficient arguments to function `xxx'. Stop.' 這意著您在呼叫函數是您提供需要數目的參數函數參數的詳細描述參閱文字(text)轉換函數 `missing target pattern. Stop.' `multiple target patterns. Stop.' `target pattern contains no `%'. Stop.'
這些錯誤訊的靜態樣式規則引。第一條在規則的目標分沒有規則,第二條在目標分有 多個規則,第沒有引入(include)樣式%參閱靜態樣式規則語法 `warning: -jN forced in submake: disabling jobserver mode.' 告是在make與子make通訊的系統中引入(include)並行處理的錯誤參閱與子make通訊選 項)。該告訊是如果遞迴一個make過程,而且還使用了‘-jn’選項(這裡n大於1)。這種情況可能發生,例如,
如果您設定環境變數MAKE為‘make j2’。這種情況下,子make不能與其它make過程通訊, 而且還簡單假裝它由兩個 任務。
`warning: jobserver unavailable: using -j1. Add `+' to parent make rule.' 為了保證make過程之間通訊make遞訊子make。這可能導致問題,因為子過程有可能不是實的一個 make,而過程僅僅認為子過程一個make而將所有資訊子過程過程常的算法決定這些參閱 變數MAKE的工作模式)。如果makefile檔案了這樣的過程它並不知子過程是否為make,那麼,子過程 那些沒有用的訊。這情況下,子過程就會產,然按照它內建的次序模式進行處理
17 複雜的makfile檔案例子
這是一個用GNU tar程式的makefile檔案;這是一個中等複雜的makefile檔案。 因all’是第一個目標預設目標。該makefile檔案一個有地方是‘testpad.h'是由testpad程式建 ,而且該程式自身由‘testpad.c'編譯得到。 如果您鍵make'或`make all'則make建名為tar'執行檔案, 提供遠的進程rmt'和名為tar.info'的 Info檔案。 如果您鍵make install'則make不但立‘tar',rmt',和tar.info',而且安裝們。 如果您鍵make clean', 則make刪除所有.o'檔案,以及‘tar',rmt',testpad', testpad.h',和core檔案。 如果您鍵make distclean', 則make不僅刪除make clean'刪除的所有檔案,而且包括檔案TAGS', Makefile', 和config.status' 檔案。(雖然不明,但該 makefile (和config.status')用configure程式生的,該程式是由發布的tar 檔案提供,但這裡不進行說明。) 如果您鍵make realclean', 則make刪除make distclean '刪除的所有檔案,而且包括由‘tar.texinfo'生的Info檔案
外,目標shar和dist創造了發布檔案的心。
# 自動makefile.in #GNU tar 程式的Unix Makefile # Copyright (C) 1991 Free Software Foundation, Inc.
# 本程式軟體GNU條情況下 # 您可以重新發布它或更它 # 公眾許可證 ...
... ...
SHELL = /bin/sh
#### 系統配置####
srcdir = .
# 如果您使用gcc, 您應該在執行 # 和它一起建的固定引入(include)的本程式及 # 使用-traditional選項執行gcc中選擇其一 # 另的ioctl呼叫在一些系統上不能正確編譯 CC = gcc -O YACC = bison -y
INSTALL = /usr/local/bin/install -c INSTALLDATA = /usr/local/bin/install -c -m 644
# 您應該DEFS中添加的內容 # -DSTDC_HEADERS 如果您有標C的檔案和庫檔案 # -DPOSIX 如果您有POSIX.1的檔案和庫檔案 # -DBSD42 如果您有sys/dir.h (除非您使用-DPOSIX), sys/file.h,和st_blocks在`struct stat'中 # -DUSG 如果您有System V/ANSI C字元串和內控制函數和檔案 sys/sysmacros.h,fcntl.h, getcwd, no # valloc, 和 ndir.h (除非您使用-DDIRENT)。 # -DNO_MEMORY_H 如果USG或STDC_HEADERS 但是不包括memory.h. # -DDIRENT 如果USG而且您又用dirent.h代替ndir.h # -DSIGTYPE=int 如果您的信號控制單元回int,非void. # -DNO_MTIO 如果您缺少sys/mtio.h (magtape ioctls). # -DNO_REMOTE 如果您沒有一個遠程shell或rexec. # -DUSE_REXEC 遠程帶使用rexec作代替分支rsh或remsh. # -DVPRINTF_MISSING 如果您缺少函數vprintf(但是有_doprnt). # -DDOPRNT_MISSING 如果您缺少函數 _doprnt.要定義 -DVPRINTF_MISSING. # -DFTIME_MISSING 如果您缺系統呼叫ftime
# -DSTRSTR_MISSING 如果您缺少函數strstr # -DVALLOC_MISSING 如果您缺少函數valloc # -DMKDIR_MISSING 如果您缺系統呼叫mkdir和rmdir。 # -DRENAME_MISSING 如果您缺系統呼叫rename。 # -DFTRUNCATE_MISSING 如果您缺系統呼叫ftruncate。 # -DV7 在Unix版本7 (沒有進行長期測試). # -DEMUL_OPEN3 如果您缺少3-參數版本的open, 並想透過有的系統呼叫模 # -DNO_OPEN3 如果您缺少3-參數版本的open並要止tar k選項代替模open. # -DXENIX 如果您有sys/inode.h並要它引入(include)94
DEFS = -DSIGTYPE=int -DDIRENT -DSTRSTR_MISSING \
-DVPRINTF_MISSING -DBSD42
# 設定為rtapelib.o 使它為空 # 定義NO_REMOTE,
RTAPELIB = rtapelib.o LIBS =
DEF_AR_FILE = /dev/rmt8 DEFBLOCKING = 20
CDEBUG = -g CFLAGS = $(CDEBUG) -I. -I$(srcdir) $(DEFS) \
-DDEF_AR_FILE=\"$(DEF_AR_FILE)\" \
-DDEFBLOCKING=$(DEFBLOCKING) LDFLAGS = -g
prefix = /usr/local
# 一個安裝程式的 #常為空或`g' binprefix =
# 安裝tar的路俓(stem) bindir = $(prefix)/bin
# 安裝info檔案的路俓(stem). infodir = $(prefix)/info
#### 系統配置分 ####
SRC1 = tar.c create.c extract.c buffer.c \ getoldopt.c update.c gnu.c mangle.c SRC2 = version.c list.c names.c diffarch.c \ port.c wildmat.c getopt.c SRC3 = getopt1.c regex.c getdate.y SRCS = $(SRC1) $(SRC2) $(SRC3) OBJ1 = tar.o create.o extract.o buffer.o \ getoldopt.o update.o gnu.o mangle.o OBJ2 = version.o list.o names.o diffarch.o \ port.o wildmat.o getopt.o
OBJ3 = getopt1.o regex.o getdate.o $(RTAPELIB) OBJS = $(OBJ1) $(OBJ2) $(OBJ3)
AUX = README COPYING ChangeLog Makefile.in \ makefile.pc configure configure.in \ tar.texinfo tar.info* texinfo.tex \ tar.h port.h open3.h getopt.h regex.h \ rmt.h rmt.c rtapelib.c alloca.c \ msd_dir.h msd_dir.c tcexparg.c \
level-0 level-1 backup-specs testpad.c
all: tar rmt tar.info
tar: $(OBJS) $(CC) $(LDFLAGS) -o $@ $(OBJS) $(LIBS)
rmt: rmt.c $(CC) $(CFLAGS) $(LDFLAGS) -o $@ rmt.c
tar.info: tar.texinfo makeinfo tar.texinfo
install: all $(INSTALL) tar $(bindir)/$(binprefix)tar
-test ! -f rmt || $(INSTALL) rmt /etc/rmt $(INSTALLDATA) $(srcdir)/tar.info* $(infodir)
$(OBJS): tar.h port.h testpad.h regex.o buffer.o tar.o: regex.h # getdate.y 有8個變換/少衝突
testpad.h: testpad ./testpad
testpad: testpad.o $(CC) -o $@ testpad.o
TAGS: $(SRCS) etags $(SRCS)
clean: rm -f *.o tar rmt testpad testpad.h core
distclean: clean rm -f TAGS Makefile config.status
realclean: distclean rm -f tar.info*
shar: $(SRCS) $(AUX) shar $(SRCS) $(AUX) | compress \ > tar-`sed -e '/version_string/!d' \
-e 's/[^0-9.]*\([0-9.]*\).*/\1/' \
-e q version.c`.shar.Z
dist: $(SRCS) $(AUX) echo tar-`sed \
-e '/version_string/!d' \
-e 's/[^0-9.]*\([0-9.]*\).*/\1/' \
-e q version.c` > .fname
-rm -rf `cat .fname` mkdir `cat .fname` ln $(SRCS) $(AUX) `cat .fname`
tar chZf `cat .fname`.tar.Z `cat .fname`
-rm -rf `cat .fname` .fname
tar.zoo: $(SRCS) $(AUX)
-rm -rf tmp.dir
-mkdir tmp.dir
-rm tar.zoo for X in $(SRCS) $(AUX) ; do \ echo $$X ; \ sed 's/$$/^M/' $$X \ > tmp.dir/$$X ; done cd tmp.dir ; zoo aM ../tar.zoo *
-rm -rf tmp.dir
(1)
為 MS-DOS 和 MS-Windows編譯的GNU Make和將前定義為DJGPP的行為相同。
(2)
在MS-DOS上, 當前工作目錄的值global, 因此改變它將影響這些系統後的命令行
(3)
本文檔的版所有,不於任何行為
詞翻對照表
archive 資料庫 archive member targets 資料庫成目標 arguments of functions 函數參數 automatic variables 自動變數 backslash (\) 反斜線(\) basename 基本檔案名 binary packages 進制 compatibility data base 資料庫 default directries 預設目錄 default goal 預設最終目標 defining variables verbatim 定義多行變數 directive 指令 dummy pattern rule 樣式規則 echoing of commands 命令回顯 editor 輯器 empty commands 空命令 empty targets 空目標
environment 環境 explicit rule 具體規則 file name functions 檔案名函數 file name suffix 檔案名後置 flags 標誌 flavors of variables 變數的特色 functions 函數 goal 最終目標 implicit rule 隱含規則 incompatibilities 不相 intermediate files 檔案 match-anything rule 萬用規則 options 選項 parallel execution 並行執行
pattern 樣式
pattern rule 樣式規則 phony targets 假想(phony)目標 prefix prerequisite 先決條件 recompilation 重新編譯 rule 規則 shell command shell命令 slash (/) 斜線(/) static pattern rule 靜態樣式規則 stem 俓(stem) sub-make 子make subdirectories 子目錄 suffix 後置 suffix rule 後置規則 switches 關 target 目標 value 值 variable 變數 wildcard 萬用字元
word
Loading...