makefile 文件的用法

來自:http://blog.sina.com.cn/s/blog_5fd6a0e50100g89d.html

去支付寶面試,面試官問我了一個問題:Makefile的作用,我沒有回答上來。今特找來放到這裏,叫我不要忘記面試那天的情況。

 

     makefile文件保存了編譯器和連接器的參數選項,還表述了所有源文件之間的關係(源代碼文件需要的特定的包含文件,可執行文件要求包含的目標文件模塊及庫等).創建程序(make程序)首先讀取makefile文件,然後再激活編譯器,彙編器,資源編譯器和連接器以便產生最後的輸出,最後輸出並生成的通常是可執行文件.創建程序利用內置的推理規則來激活編譯器,以便通過對特定CPP文件的編譯來產生特定的OBJ文件.  
  附上原文:  
  Experienced   programmers   are   familiar   with   makefiles.   A   makefile   stores  compiler   and   linker   options   and   expresses   all   the   interrelationships   among  source   files.   (A   source   code   file   needs   specific   include   files,   an  executable   file   requires   certain   object   modules   and   libraries,   and   so   forth.)   A   make   program   reads   the   makefile   and   then   invokes   the   compiler,  assembler,   resource   compiler,   and   linker   to   produce   the   final   output,   which  is   generally   an   executable   file.   The   make   program   uses   built-in   inference  rules   that   tell   it,   for   example,   to   invoke   the   compiler   to   generate   an  OBJ   file   from   a   specified   CPP   file.

 

一、Makefile裏有什麼?

Makefile裏主要包含了五個東西:顯式規則、隱晦規則、變量定義、文件指示和註釋。

1、顯式規則。顯式規則說明了,如何生成一個或多的的目標文件。這是由Makefile的書寫者明顯指出,要生成的文件,文件的依賴文件,生成的命令。

2、隱晦規則。由於我們的make有自動推導的功能,所以隱晦的規則可以讓我們比較粗糙地簡略地書寫Makefile,這是由make所支持的。

3、變量的定義。在Makefile中我們要定義一系列的變量,變量一般都是字符串,這個有點你C語言中的宏,當Makefile被執行時,其中的變量都會被擴展到相應的引用位置上。

4、文件指示。其包括了三個部分,一個是在一個Makefile中引用另一個Makefile,就像C語言中的include一樣;另一個是指根 據某些情況指定Makefile中的有效部分,就像C語言中的預編譯#if一樣;還有就是定義一個多行的命令。有關這一部分的內容,我會在後續的部分中講 述。

5、註釋。Makefile中只有行註釋,和UNIX的Shell腳本一樣,其註釋是用“#”字符,這個就像C/C++中的“//”一樣。如果你要在你的Makefile中使用“#”字符,可以用反斜框進行轉義,如:“\#”。

最後,還值得一提的是,在Makefile中的命令,必須要以[Tab]鍵開始。


二、Makefile的文件名

默認的情況下,make命令會在當前目錄下按順序找尋文件名爲“GNUmakefile”、“makefile”、“Makefile”的文件, 找到了解釋這個文件。在這三個文件名中,最好使用“Makefile”這個文件名,因爲,這個文件名第一個字符爲大寫,這樣有一種顯目的感覺。最好不要用 “GNUmakefile”,這個文件是GNU的make識別的。有另外一些make只對全小寫的“makefile”文件名敏感,但是基本上來說,大多 數的make都支持“makefile”和“Makefile”這兩種默認文件名。

當然,你可以使用別的文件名來書寫Makefile,比如:“Make.Linux”,“Make.Solaris”,“Make.AIX”等, 如果要指定特定的Makefile,你可以使用make的“-f”和“--file”參數,如:make -f Make.Linux或 make --file Make.AIX。


三、引用其它的Makefile

在Makefile使用include關鍵字可以把別的Makefile包含進來,這很像C語言的#include,被包含的文件會原模原樣的放在當前文件的包含位置。include的語法是:

     include <filename>;

     filename可以是當前操作系統Shell的文件模式(可以保含路徑和通配符)

在include前面可以有一些空字符,但是絕不能是[Tab]鍵開始。include和<filename>;可以用一個或多個空 格隔開。舉個例子,你有這樣幾個Makefile:a.mk、b.mk、c.mk,還有一個文件叫foo.make,以及一個變量$(bar),其包含了 e.mk和f.mk,那麼,下面的語句:

     include foo.make *.mk $(bar)

     等價於:

     include foo.make a.mk b.mk c.mk e.mk f.mk

make命令開始時,會把找尋include所指出的其它Makefile,並把其內容安置在當前的位置。就好像C/C++的#include指 令一樣。如果文件都沒有指定絕對路徑或是相對路徑的話,make會在當前目錄下首先尋找,如果當前目錄下沒有找到,那麼,make還會在下面的幾個目錄下 找:

     1、如果make執行時,有“-I”或“--include-dir”參數,那麼make就會在這個參數所指定的目錄下去尋找。
     2、如果目錄<prefix>;/include(一般是:/usr/local/bin或/usr/include)存在的話,make也會去找。

如果有文件沒有找到的話,make會生成一條警告信息,但不會馬上出現致命錯誤。它會繼續載入其它的文件,一旦完成makefile的讀 取,make會再重試這些沒有找到,或是不能讀取的文件,如果還是不行,make纔會出現一條致命信息。如果你想讓make不理那些無法讀取的文件,而繼 續執行,你可以在include前加一個減號“-”。如:

     -include <filename>;
     其表示,無論include過程中出現什麼錯誤,都不要報錯繼續執行。和其它版本make兼容的相關命令是sinclude,其作用和這一個是一樣的。


四、環境變量 MAKEFILES

如果你的當前環境中定義了環境變量MAKEFILES,那麼,make會把這個變量中的值做一個類似於include的動作。這個變量中的值是其 它的Makefile,用空格分隔。只是,它和include不同的是,從這個環境變中引入的Makefile的“目標”不會起作用,如果環境變量中定義 的文件發現錯誤,make也會不理。

但是在這裏我還是建議不要使用這個環境變量,因爲只要這個變量一被定義,那麼當你使用make時,所有的Makefile都會受到它的影響,這絕 不是你想看到的。在這裏提這個事,只是爲了告訴大家,也許有時候你的Makefile出現了怪事,那麼你可以看看當前環境中有沒有定義這個變量。


五、make的工作方式

GNU的make工作時的執行步驟入下:(想來其它的make也是類似)

     1、讀入所有的Makefile。
     2、讀入被include的其它Makefile。
     3、初始化文件中的變量。
     4、推導隱晦規則,並分析所有規則。
     5、爲所有的目標文件創建依賴關係鏈。
     6、根據依賴關係,決定哪些目標要重新生成。
     7、執行生成命令。

1-5步爲第一個階段,6-7爲第二個階段。第一個階段中,如果定義的變量被使用了,那麼,make會把其展開在使用的位置。但make並不會完 全馬上展開,make使用的是拖延戰術,如果變量出現在依賴關係的規則中,那麼僅當這條依賴被決定要使用了,變量纔會在其內部展開。

當然,這個工作方式你不一定要清楚,但是知道這個方式你也會對make更爲熟悉。有了這個基礎,後續部分也就容易看懂了


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章