GNU make/打印版
聲明,本文翻譯的是GNU make 3.8.1版用戶手冊;本手冊的原作者是司徒文(Richard M. Stallman),麥家府(Roland McGrath),史密斯(Paul D. Smith)。原手冊發佈於2006年4月。此為原文下載地址
make概述
[編輯]make工具能自動判斷一個大程序的哪些部分需要再編譯,並且能用命令來執行再編譯操作。本文檔討論的GNU make原來是由司徒文與麥家府開發製作的,從3.76版開始由史密斯接管開發工作。
GNU make遵從IEEE 1003.2-1992標準(POSIX.2)第6.2條。
在本文例子中,筆者用的是C語言程序,這是因為C語言最為流行,但讀者也可以用make來完成其他程式語言的編譯工作,前提是這種語言的編譯器能在 shell下運行。當然,make的應用不局限於程序;如果遇到一些任務,這些任務的文件必須隨着其他文件或數據的變化而更新,那麼讀者就可以用make 來應對這些任務。
在使用make之前,請讀者先寫好Makefile文件,該文件須描述清楚程序文件之間的關係,還要給出更新每個文件的命令。通常,一個程序的可執行文件由OBJ文件來更新,而這些OBJ文件則由原始碼編譯產生。
只要有合適的Makefile文件,在修改了一些原始碼後,只要在Shell命令行下輸入:
- make
就足以完成所有必要的再編譯。make程序通過Makefile的數據庫以及諸文件的最後修改時間來判斷哪些文件需要更新。對於每個需要更新的文件, make會用數據庫中記錄的命令來對其操作。
讀者可以給make加上命令行參數,以此告訴make哪些文件需要再編譯、怎樣再編譯。參見第九章如何運行make。
如何使用本文檔
[編輯]如果讀者是個make新手,或者想閱讀大體介紹,那麼在閱讀每章時只需少量的看前幾節,後面幾節可以略過。每章的前幾節會有該章介紹以及該章的大體信息,而後幾節則會包括一些特殊的或技術性的信息。但第二章 make簡介是個例外,全章都是介紹性的內容。
如果讀者對其他make程序比較熟悉的話,請參閱第十二章 GNU make的特色功能,該章列出了GNU make的增強功能;另外請參閱第十三章 GNU make與標準make不兼容的部分,該章舉出GNU make在少數功能上遜色於其他make的例子。
如果需要閱讀摘要,請看第九章第七節 選項摘要、附錄 A 快速參考以及第四章第八節所講的特殊目標。
問題與漏洞
[編輯]如果讀者發現了GNU make的一些問題或者認為發現了漏洞,那麼請與開發者聯繫;我們不作任何承諾,但我們會盡力解決問題。
在提交漏洞報告之前,請核實漏洞的真實性。另外請認真反覆閱讀文檔,確定文檔介紹的應用方法在實際操作中有效,如果文檔對功能上的一些問題沒有闡述清楚,那麼也請提交報告,這些都是文檔的「漏洞」!
在提交漏洞報告或者自己解決漏洞之前,請將Makefile文件簡化至最小且能體現漏洞問題的程度。然後把Makefile文件連同出錯和警告信息一齊發給我們。請勿改動原信息,最好將其剪切複製到漏洞報告中。請確保用以生成最簡Makefile文件的命令中不使用非自由軟件或者不常用的程序(其實對於這種工具,讀者隨時都可以用簡單的幾句Shell命令來測試)。最後,請詳述Makefile本應有的預期結果,以便於我們判斷問題是否出在文檔上。
如果讀者發現了一個如假包換的錯誤,那麼可以通過以下兩種途徑提交報告:一、通過發送電子郵件到:
與我們聯繫;
二、使用我們的在線項目管理來提交報告,網址是:
除了上述的信息以外,請將使用的make完整的版本號一併發給我們;讀者可以通過使用命令「make --version」來獲取版本信息。請確保報告中包含make所運行機器的硬件信息與作業系統信息;順便提一句,獲取這些信息的一種方法是使用命令 「make --help」,一切盡在命令的最後一行輸出中。
make簡介
[編輯]首先要有一個名為「Makefile」的文件告訴make需要作什麼。絕大多數情況下,Makefile主要讓make完成編譯與連結程序的工作。
本章我們討論一個簡單的Makefile,這個Makefile會編譯與連結一個由八個C原始碼文件和三個頭文件組成的文本編輯器程序。該 Makefile還會告訴make如何在有明確指示的時候運行各種各樣的命令(比如說接到清除指示時,make運行刪除某些文件的命令)。要閱讀更複雜的 Makefile代碼,翻至附錄C 一個複雜的Makefile實例。
當make重新編譯該文本編輯器時,所有的C原始碼文件都會被重新編譯。如果一個頭文件被修改,那麼為了保證整體程序無損,包含該頭文件的所有C原始碼文件都必須要重新編譯。原始碼文件每經過一次編譯都會有一個與自己對應的OBJ文件生成。最後,若有原始碼文件被重新編譯,所有OBJ文件不管是以前生成的還是新生成的,都會被用來連結生成新的可執行文本編輯器程序。
規則大概是什麼樣的
[編輯]一個簡單的Makefile所包含的「規則」形式如下
目标 ...:先决条件 命令 ... ...
目標的名稱一般與生成的文件名稱一致(像可執行程序和OBJ文件)。目標的名稱
也可以是要進行的動作,比如說「clean」(參見第四章第五節 偽目標)。
先決條件是用以生成目標的輸入文件,而一個目標往往依賴於多個文件。
命令是make要執行的動作,而一個規則往往要多行命令。請注意:在每個命令前都必須輸入一個Tab!一般粗心大意的人容易在這個問題上犯錯。
通常有先決條件規則的命令會在先決條件被改動之後執行。但也有一些執行特殊命令的規則沒有先決條件,比如說目標「clean」所在的規則就沒有先決條件,該規則含有刪除命令。
接下來規則會說明與特定規則關聯的文件應該何時被操作,如何被操作。然後make執行先決條件中的命令,用以生成或更新目標。此外,規則還可以對何時與如何進行一個動作下令。參見第四章 編寫規則。
除了規則之外,Makefile文件也可以有其他內容,但一個簡單的Makefile只需有規則即可。規則寫出來會比模板中所寫的略顯複雜,但或多或少含有與其一致的部分。
一份簡單的Makefile文件
[編輯]下面有一份簡單易懂的Makefile文件,該文件描述了各種依賴關係:可執行程序edit依賴於八個OBJ文件,八個OBJ文件依賴於八個C原始碼文件和三個頭文件。
在本例中,所有C原始碼文件都包含了「defs.h」頭文件,只有定義了編輯命令的C原始碼文件才包含「command.h」頭文件,而只有只有能改變編輯器緩衝區的低層C原始碼文件才包含「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刪除目錄中所有OBJ文件和可執行程序「edit」,請鍵入:
- make clean
在本例中,目標包括,可執行程序「edit」以及OBJ文件「main.o」與「kdb.o」;先決條件也有許多,如「main.c」與「defs.h」;而每個「.o」文件都既為目標,又是先決條件;命令包括「cc -c main.c」與「cc -c kbd.c」。
若目標為文件,則該文件會在其先決條件被改動後重編譯與連結。另外,會自動生成的先決條件首先更新。本例中,「edit」依賴於八個OBJ文件;OBJ文件「main.o」依賴於原始碼文件「main.c」與頭文件「defs.h」。
Shell命令跟隨在目標與先決條件的下一行,該命令控制更新目標文件。每個命令行首必須要有Tab鍵入,以此區分命令行與Makefile中的其他行。(想想看,make全然不知命令是如何工作的,必須由程式設計師提供命令來更新目標。make所能幹的只有執行程式設計師給出命令,然後再根據命令判斷目標文件是否需要更新;如需要,更新之)。
目標「clean」不是一個文件,僅僅是動作的名稱而已。因為這個規則不包含其他動作,而且也不是其他任何規則的先決條件,所以,make不會執行此處操作,除非被特別指定。請注意,此規則既非其他規則之先決條件,亦無先決條件,故此規則唯一目的為運行特定命令。目標若只含命令而與其他文件不相關聯,則稱此目標為偽目標。可參閱第四章第五節 偽目標,了解詳情。另外,請參閱第五章第五節 命令中的報錯信息,了解如何忽略rm或者其他命令的報錯信息。
make如何執行一個Makefie的指令
[編輯]在默認情況下,make的工作始於第一個目標(只要這個目標不是以「。」開頭的)。此目標稱為默認最終目標(如果不想使用這個默認規定,可以在命令行中輸入「make 目標名」(參見第九章第二節 用以確定最終目標的參數)或者更改變量(參見第三章第六節 其它的特殊變量)「.DEFAULT_GOAL」以改變默認最終目標)。
上一節簡單示例中,默認最終目標是更新可執行程序「edit」,故將其列入規則首位。
因此,輸入以下命令:
- make
make首先讀取本目錄的Makefile,而後開始運行第一個規則。在此例中,規則用以重連結「edit」;但在執行這條規則之前,make必須完成所有「edit」依賴的規則,這些規則就是那些OBJ文件;而每個OBJ文件都會運行自己的一套規則,這些規則會通過編譯各自原始碼的方式來更新每個「.o」文件。如果頭文件或者原始碼文件的修改時間比依賴其的OBJ文件要晚,或者OBJ文件不存在,那麼重新編譯就必須要進行。
那些非最終目標之所以會被運行,是因為最終目標與之相關。而與最終目標無關的規則就不會被執行,除非被特指(如「make clean」)。
在重編譯一個OBJ文件之前,make會先更新其先決條件,先決條件包括原始碼文件與頭文件。此例中的Makefile並沒有針對原始碼文件與頭文件的操作,另外這些「.c」與「.h」文件也不是規則的名稱,故make在此不做任何事情。但make會自動更新自動生成的C程序,比如說由Bison或Yacc生成的,由此次規則生成的。
在編譯完所有需要的OBJ文件後,make會決定是否重連結「edit」。如果「edit」文件不存在或者OBJ文件比「edit」文件要新,則重連結工作一定要作。如果OBJ文件是剛編譯出的,其時間晚於「edit」文件,故此時「edit」文件要被重連結。
因此,如果更改了「insert.c」文件再運行make;make會先編譯「insert.c」文件生成「insert.o」文件,再連結生成「edit」文件。若更改的是「command.h」,再運行make;make會編譯生成「kdb.o」、「command.o」、「files.o」再連結生成「edit」。
用變量簡化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文件加入系統,本應可以只添加新文件而不考慮原有的OBJ文件。若採用變量協助工作,則既可減少出錯幾率,亦能簡化Makefile。變量允許先對一段文本字符串定義,以後需要書寫諸OBJ文件時,可以只輸入變量而不需要把所有OBJ文件列出(參見第六章 如何使用變量)。
此處,一個習慣性做法是,在每個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)」代替(參見第六章 如何使用變量)。
下面就是用變量來描述諸OBJ文件的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)
讓make自己推算出要執行的命令
[編輯]不必將每個編譯C原始碼文件的命令全部寫出,因為make可以構造出這些命令:make有一個隱規則可通過命令「cc -c」生成與「.c」文件前綴名一致的「.o」文件的命令,比如將「main.c」編譯成「main.o」的命令「cc -c main.c -o main.o」。此處可以把命令中寫「.o」的部分省略。參閱第十章 使用隱規則。
當「.c」文件以下例方法自動被使用時,「.c」文件會自動加入到先決條件中。在先決條件中省略「.c」文件的同時,編譯命令也被省略了。
下面是個完整的例子。例子中包括了上面兩種省略方法,而且也使用了上一節所說的「objects」變量。
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」規則在其他地方有所討論。參見第四章第五節 偽目標與第五章第五節 命令中的報錯信息)。
隱規則使用簡便,故尤為重要。讀者會頻繁見到隱規則的使用。
另一種格式的Makefile
[編輯]當組成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」與「buffer.h」為特定OBJ文件的先決條件。
不知這樣緊湊的寫法是否為一些人的愛好,但還是有一些人不喜歡這種寫法,認為將一個目標跟與之對應的信息寫在一起顯得比較清楚。
清理目錄的規則
[編輯]編寫Makefile所要寫的不僅僅編譯程序。Makefile還能做一些編譯外的事情,比如說,如何將一個目錄里的OBJ文件與可執行文件清理乾淨。
下面就是一例,演示如何用make以完成清除工作:
clean: rm edit $(objects)
在實際應用中Makefile可能會寫得更複雜,以應對突發事件,下為例:
.PHONY : clean clean : -rm edit $(objects)
本例的Makefile,可在有文件名為「clean」時避免混淆,還可在rm報錯時仍舊執行。(參見第四章第五節 偽目標與第五章第五節 命令中的報錯信息)
此類規則不可置於Makefile文首,這是由於一般不願讓其作為默認規則執行!故在前幾節的完整Makefile示例中,用「edit」為默認規則,以便編譯與重編譯。
因為「clean」並非「edit」的先決條件,故此規則在make沒有參數時不會運行。若要運行此規則,鍵入命令「make clean」(參見第九章 如何運行make)。
編寫Makefile
[編輯]make重編譯系統的信息源於Makefile構建的數據庫。
Makefile裏包含的是什麼
[編輯]「Makefile」文件應該取什麼樣的名字
[編輯]包含其它的Makefile文件
[編輯]「MAKEFILES」變量
[編輯]「MAKEFILE_LIST」變量
[編輯]其它的特殊變量
[編輯]Makefile如可被make再執行
[編輯]調用其它Makefile的重要技巧
[編輯]make如何理解Makefile的內容
[編輯]編寫規則
[編輯]規則的語法結構
[編輯]先決條件的種類
[編輯]在文件名中使用通配符
[編輯]通配符示例
[編輯]使用通配符的陷阱
[編輯]「wildcard」函數
[編輯]為先決條件搜索目錄
[編輯]「VPATH」:為所有先決條件搜索路徑
[編輯]「vpath」指令
[編輯]目錄搜索是如何進行的
[編輯]編寫帶目錄搜索功能的Shell命令
[編輯]目錄搜索與隱規則
[編輯]為連接庫而做的目錄搜索
[編輯]偽目標
[編輯]無先決條件與命令的規則
[編輯]用目標對應的空文件記錄事件
[編輯]特殊內建目標的名稱
[編輯]單規則使用多目標
[編輯]單目標對應多規則
[編輯]靜態模式規則
[編輯]靜態模式規則的語法結構
[編輯]靜態模式規則與隱規則的比較
[編輯]帶雙冒號的規則
[編輯]自動生成先決條件
[編輯]編寫規則中的命令
[編輯]命令的語法結構
[編輯]將命令分為多行的方法
[編輯]在命令中使用變量
[編輯]輸出信息命令
[編輯]命令的執行
[編輯]選擇Shell
[編輯]並行執行
[編輯]命令中的報錯信息
[編輯]中斷或強制結束make
[編輯]遞歸使用make
[編輯]make的變量是怎樣工作的
[編輯]與低層的make互傳變量
[編輯]與低層的make互傳選項
[編輯]「--print-directory」選項
[編輯]定義封裝的命令組
[編輯]使用空命令
[編輯]如何使用變量
[編輯]變量的基本參考
[編輯]變量的兩種風格
[編輯]變量高級功能參考
[編輯]替換功能參考
[編輯]可運算的變量名
[編輯]變量如何獲取其值
[編輯]設置變量
[編輯]向變量追加文本內容
[編輯]「override」指令
[編輯]逐字定義變量
[編輯]來自環境變量的變量
[編輯]目標特定變量的賦值
[編輯]模式特定變量的賦值
[編輯]Makefile的條件控制部分
[編輯]條件示例
[編輯]條件的語法結構
[編輯]測試標誌位的條件
[編輯]文本操控函數
[編輯]函數調用的語法結構
[編輯]對字符串做替換與分解的函數
[編輯]對文件名操作的函數
[編輯]條件控制函數
[編輯]「foreach」函數
[編輯]「call」函數
[編輯]「value」函數
[編輯]「eval」函數
[編輯]「shell」函數
[編輯]控制make的函數
[編輯]如何運行make
[編輯]用以確定Makefile文件的參數
[編輯]用以確定最終目標的參數
[編輯]用其它功能來取代執行命令的參數
[編輯]避免重新編譯某些文件
[編輯]初始變量
[編輯]測試編譯程序
[編輯]選項摘要
[編輯]使用隱規則
[編輯]使用隱規則
[編輯]隱規則章目
[編輯]隱規則使用的變量
[編輯]隱規則鏈
[編輯]定義與重定義模式的規則
[編輯]模式的規則介紹
[編輯]模式的規則示例
[編輯]自變變量
[編輯]模式是如何匹配的
[編輯]匹配一切的模式規則
[編輯]取消隱規則
[編輯]定義去除依賴的默認規則
[編輯]過時的附加規則
[編輯]隱規則的搜索算法
[編輯]使用make更新歸檔文件
[編輯]歸檔成員作為目標
[編輯]為歸檔成員目標而設的隱規則
[編輯]更新歸檔字符目錄
[編輯]使用歸檔的風險
[編輯]歸檔文件的附加規則
[編輯]GNU make的特色功能
[編輯]GNU make與標準make不兼容的部分
[編輯]GNU make的一些不成文規定
[編輯]Makefile的通用習慣
[編輯]Makefile的工具
[編輯]指定變量的命令
[編輯]安裝目錄的變量
[編輯]為用戶設計的標準目標
[編輯]安裝命令的條目
[編輯]附錄
[編輯]A 快速參考
[編輯]B 常見錯誤
[編輯]C 一個複雜的Makefile實例
[編輯]下面是一段為GNU tar程序設計的Makefile代碼,相當複雜。
由於「all」是第一個目標,所以它也是默認目標。下面這個程序段有一個非常有趣的特色,這個特色就是原始碼程序中的「testpad.h」文件是一個由名叫testpad程序自動生成的,而這個testpad又是又是由「testpad.c」這個程序經過編譯產生的。
如果您輸入「make」或者「make all」,則make會讓名為「tar」的目標運行從而開始編譯指令,會讓名為「rmt」的目標運行從而生成一個遠程磁帶數據存取的守護程序,會讓名為 「tar.info」的目標運行從而生成INFO文檔。
如果您輸入「make install」,那麼make就執行的就不僅僅只是「tar」、「rmt」和「tar.info」這三個目標了,還會執行相應的安裝操作。< /br>
如果您輸入「make clean」,那麼make會清除所有的「.o」文件,以及「tar」、「rmt」、「testpad」、「testpad.h」和「core」這些文件。
如果您輸入「make distclean」,那麼make除了會清除「make clean」會清除的文件外,還會清除「TAGS」、「Makefile」和「config.status」這些文件(雖然不明顯,但下面這個 makefile和「config.status」都是用戶通過tar發行版中的「configure」文件生成的,這個「configure」文件這裏沒有列出)。
如果您輸入「make realclean」,那麼make除了清除「make distclean」會清除的文件外,還會清除由「tar.info」生成的INFO文檔。
# Generated automatically from Makefile.in by configure. # Un*x Makefile for GNU tar program. # Copyright (C) 1991 Free Software Foundation, Inc. # This program is free software; you can redistribute # it and/or modify it under the terms of the GNU # General Public License ... ... ... SHELL = /bin/sh #### Start of system configuration section. #### srcdir = . # If you use gcc, you should either run the # fixincludes script that comes with it or else use # gcc with the -traditional option. Otherwise ioctl # calls will be compiled incorrectly on some systems. CC = gcc -O YACC = bison -y INSTALL = /usr/local/bin/install -c INSTALLDATA = /usr/local/bin/install -c -m 644 # Things you might add to DEFS: # -DSTDC_HEADERS If you have ANSI C headers and # libraries. # -DPOSIX If you have POSIX.1 headers and # libraries. # -DBSD42 If you have sys/dir.h (unless # you use -DPOSIX), sys/file.h, # and st_blocks in `struct stat'. # -DUSG If you have System V/ANSI C # string and memory functions # and headers, sys/sysmacros.h, # fcntl.h, getcwd, no valloc, # and ndir.h (unless # you use -DDIRENT). # -DNO_MEMORY_H If USG or STDC_HEADERS but do not # include memory.h. # -DDIRENT If USG and you have dirent.h # instead of ndir.h. # -DSIGTYPE=int If your signal handlers # return int, not void. # -DNO_MTIO If you lack sys/mtio.h # (magtape ioctls). # -DNO_REMOTE If you do not have a remote shell # or rexec. # -DUSE_REXEC To use rexec for remote tape # operations instead of # forking rsh or remsh. # -DVPRINTF_MISSING If you lack vprintf function # (but have _doprnt). # -DDOPRNT_MISSING If you lack _doprnt function. # Also need to define # -DVPRINTF_MISSING. # -DFTIME_MISSING If you lack ftime system call. # -DSTRSTR_MISSING If you lack strstr function. # -DVALLOC_MISSING If you lack valloc function. # -DMKDIR_MISSING If you lack mkdir and # rmdir system calls. # -DRENAME_MISSING If you lack rename system call. # -DFTRUNCATE_MISSING If you lack ftruncate # system call. # -DV7 On Version 7 Unix (not # tested in a long time). # -DEMUL_OPEN3 If you lack a 3-argument version # of open, and want to emulate it # with system calls you do have. # -DNO_OPEN3 If you lack the 3-argument open # and want to disable the tar -k # option instead of emulating open. # -DXENIX If you have sys/inode.h # and need it 94 to be included. DEFS = -DSIGTYPE=int -DDIRENT -DSTRSTR_MISSING \ -DVPRINTF_MISSING -DBSD42 # Set this to rtapelib.o unless you defined NO_REMOTE, # in which case make it empty. 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 # Prefix for each installed program, # normally empty or `g'. binprefix = # The directory to install tar in. bindir = $(prefix)/bin # The directory to install the info files in. infodir = $(prefix)/info #### End of system configuration section. #### 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 .PHONY: all all: tar rmt tar.info .PHONY: tar tar: $(OBJS) $(CC) $(LDFLAGS) -o $@ $(OBJS) $(LIBS) rmt: rmt.c $(CC) $(CFLAGS) $(LDFLAGS) -o $@ rmt.c tar.info: tar.texinfo makeinfo tar.texinfo .PHONY: install 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 has 8 shift/reduce conflicts. testpad.h: testpad ./testpad testpad: testpad.o $(CC) -o $@ testpad.o TAGS: $(SRCS) etags $(SRCS) .PHONY: clean clean: rm -f *.o tar rmt testpad testpad.h core .PHONY: distclean distclean: clean rm -f TAGS Makefile config.status .PHONY: realclean realclean: distclean rm -f tar.info* .PHONY: shar 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 .PHONY: dist 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