2017年12月27日 星期三

簡單學 makefile - makefile 教學 (2)

 

這個第二部分的makefile教學會說明一些有關於makefile的細節,為前一部分的延伸,已挑選過章節,不會有太難太偏的內容。



在規則中使用通配符
make支援三個通配符:“*”,“?”和“~”。這是和Unix的B-Shell是相同的。
  1. "*" : "*"可以代表任何文字,"*.c"表示所有後綴為c的文件,例如 rm -f *.o。
  2. "?" : "?"僅代表單個字。
  3. "~" : "~"在文件名中也有比較特殊的用途。

如果是"~/test",這就表示當前用戶的$HOME目錄下的test目錄。而"~hchen/test"則表示用戶hchen的宿主目錄下的test目錄;在Windows或是 MS-DOS下,用戶沒有宿主目錄,那麼波浪號所指的目錄則根據環境變量“HOME”而定。

規則中使用通配符範例

clean:
 rm -f *.o




文件搜尋
在一些大的工程中,有大量的源文件,我們通常的做法是把這許多的源文件分類,並存放在不同的目錄中。所以,當make需要去找尋文件的依賴關係時,你可以在文件前加上路徑,但最好的方法是把一個路徑告訴make,讓make自動去找。

Makefile文件中的特殊變量“VPATH”就是完成這個功能的,如果沒有指明這個變量,make只會在當前的目錄中去找尋依賴文件和目標文件。如果定義了這個變量,那麼,make就會在當前目錄找不到的情況下,到所指定的目錄中去找尋文件了。

1.   特殊變量"VPATH"

VPATH = src : ../headers

上面的的定義指定兩個目錄,“src”和“../headers”,make會按照這個順序進行搜索。目錄由“冒號”分隔。當前目錄永遠是最高優先搜索的地方。

2.   使用make的“vpath”關鍵字
(注意 : vpath是全小寫的,不是變量,是一個make的關鍵字)
  • a.   vpath <pattern> <directories>
    為符合模式<pattern>的文件指定搜索目錄<directories>。
    例如:vpath %.h ../headers  (“%”的意思是匹配零或若干字符)
  • b.   vpath <pattern>
    清除符合模式<pattern>的文件的搜索目錄。
  • c.   vpath
    清除所有已被設置好了的文件搜索目錄。




偽目標
最早先的一個例子中,我們提到過一個“clean”的目標,這是一個“偽目標”,正像我們前面例子中的“clean”一樣,既然我們生成了許多文件編譯文件,我們也應該提供一個清除它們的“目標”以備完整地重編譯而用。 (以“make clean”來使用該目標)

clean:
 rm -f *.o


因為,我們並不生成“clean”這個文件。“偽目標”並不是一個文件,只是一個標籤,由於“偽目標”不是文件,所以make無法生成它的依賴關係和決定它是否要執行。我們只有通過顯式地指明這個“目標”才能讓其生效。當然,“偽目標”的取名不能和文件名重名,不然其就失去了“偽目標”的意義了。

.phony

為了避免在makefile中定義的只執行命令的目標和工作目錄下的實際文件出現名字沖突,另一種是提交執行makefile時的效率。





隱含規則 - 一般隱含規則
隱含規則也就是一種慣例,make會按照這種慣例運行,即使我們的Makefile中沒有書寫這樣的規則。
  • 例如,把[.c]文件編譯成[.o]文件這一規則,不需撰寫make會自動推導出這種規則,並生成我們需要的[.o]文件。

另外,隱含規則會使用一些我們系統變量,我們可以改變這些系統變量的值來定製隱含規則的運行時的參數。
  • 例如,系統變量"CFLAGS"可以控制編譯時的編譯器參數。

隱含規則範例

//隱含規則範例

foo : foo.o bar.o
        cc o foo foo.o bar.o $(CFLAGS) $(LDFLAGS)

//下面兩條規則可以省略:

foo.o : foo.c
        cc c foo.c $(CFLAGS)
bar.o : bar.c
    cc c bar.c $(CFLAGS)





隱含規則 - 變量隱含規則
在隱含規則中的命令中,基本上都是使用了一些預先設置的變量。你可以在你的makefile中改變這些變量的值,或是在make的命令行中傳入這些值,或是在你的環境變量中設置這些值,無論怎麼樣,只要設置了這些特定的變量,那麼其就會對隱含規則起作用。

我們可以把隱含規則中使用的變量分成兩種:一種是命令相關的,如"CC";一種是參數相的關,如"CFLAGS"。下面是所有隱含規則中會用到的變量:


1、關於命令的變量。
  • 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源文件(.texi)到Info文件程式。默認命令是“makeinfo”。
  • TEX : 從TeX源文件創建TeX DVI文件的程式。默認命令是“tex”。
  • TEXI2DVI : 從Texinfo源文件創建軍TeX DVI 文件的程式。默認命令是“texi2dvi”。
  • WEAVE : 轉換Web到TeX的程式。默認命令是“weave”。
  • CWEAVE : 轉換C Web 到 TeX的程式。默認命令是“cweave”。
  • TANGLE : 轉換Web到Pascal語言的程式。默認命令是“tangle”。
  • CTANGLE : 轉換C Web 到 C。默認命令是“ctangle”。
  • RM : 刪除文件命令。默認命令是“rm –f”。


2、關於命令參數的變量
下面的這些變量都是相關上面的命令的參數。如果沒有指明其默認值,那麼其默認值都是空。
  • ARFLAGS : 函數庫打包程式AR命令的參數。默認值是“rv”。
  • ASFLAGS : 彙編語言編譯器參數。(當明顯地調用“.s”或“.S”文件時)。
  • CFLAGS : C語言編譯器參數。
  • CXXFLAGS :C++語言編譯器參數。
  • COFLAGS : RCS命令參數。
  • CPPFLAGS : C預處理器參數。( C 和 Fortran 編譯器也會用到)。
  • FFLAGS : Fortran語言編譯器參數。
  • GFLAGS : SCCS "get"程式參數。
  • LDFLAGS : 鏈接器參數。(如:“ld”)
  • LFLAGS : Lex文法分析器參數。
  • PFLAGS : Pascal語言編譯器參數。
  • RFLAGS : Ratfor 程式的Fortran 編譯器參數。
  • YFLAGS : Yacc文法分析器參數。




知道 = 和 := 的差別 知道 patsubstr, wildcard 等指令用法



最後,介紹一下make程式的開發者,都是重量級人物。


Richard Stallman (RMS)
美國的自由軟體運動精神領袖、GNU工程的發起者以及自由軟體基金會的創立者。作為一個著名的黑客,他的主要作品包括Emacs及後來的GNU Emacs,GNU C編譯器及GNU除錯器。他所作的GNU通用公共許可證是世上最廣為採用的自由軟體許可證,為copyleft觀念開拓出一條嶄新的道路。

1990年代中期,斯托曼作為一個政治運動者,為自由軟體辯護,對抗軟體專利及版權法的擴張。他對程式設計方面的投入都放在Emacs上。

他最大的影響是為自由軟體運動豎立道德、政治及法律框架。他被許多人譽為當今自由軟體的鬥士、偉大的理想主義者。

個人主頁:http://www.stallman.org/


Roland McGrath
下面是他的一些事蹟:

  1. 合作編寫了並維護GNU make。
  2. 和Thomas Bushnell一同編寫了GNU Hurd。
  3. 編寫並維護GNU C library。
  4. 合作編寫並維護部分的GNU Emacs。










技術提供:Blogger.