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可以是當前作業系統shell的檔案模式(可以保含路徑和萬用字元)
在include前面可以有一些空字元,但是絕不能是[tab]鍵開始。include和;可以用乙個或多個空格隔開。舉個例子,你有這樣幾個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、如果目錄;/include(一般是:/usr/local/bin或/usr/include)存在的話,make也會去找。
如果有檔案沒有找到的話,make會生成一條警告資訊,但不會馬上出現致命錯誤。它會繼續載入其它的檔案,一旦完成makefile的讀取,make會再重試這些沒有找到,或是不能讀取的檔案,如果還是不行,make才會出現一條致命資訊。如果你想讓make不理那些無法讀取的檔案,而繼續執行,你可以在include前加乙個減號「-」。如:
-include ;
其表示,無論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更為熟悉。有了這個基礎,後續部分也就容易看懂了。
Makefile檔案中的 PHONY 的作用
我們可以看到即使不要.phony這一行,make proto命令也是正常執行,那.phony的作用究竟是什麼呢?我先在makefile的同級目錄下建乙個檔名為proto檔案。phony後面跟的目標都被稱為偽目標,也就是說我們 make 命令後面跟的引數如果出現在.phony 定義的偽目標中,那就直接...
面試題 makefile檔案的作用
make命令和makefile檔案的結合提供了乙個在專案管理領域十分強大的工具。它不僅常被用於控制源 的編譯和鏈結,而且還用於手冊頁的編寫以及將應用程式安裝到目標目錄。makefile檔案由一組依賴關係和規則構成。每個依賴關係又乙個目標 即將要建立的檔案 和一組該目標所依賴的原始檔組成。而規則描述了...
make 與makefile的作用
在開發乙個系統時,一般是將乙個系統分成幾個模組,這樣做提高了系統的可維護性,但由於各個模組間不可避免存在關聯,所以當乙個模組改動後,其他模組也許會有所更新,當然對小系統來說,手工編譯連線是沒問題,但是如果是乙個大系統,存在很多個模組,那麼手工編譯的方法就不適用了。為此,在linux系統中,專門提供了...