天天看點

makefile

【makefile的規則】

  在講述這個makefile之前,還是讓我們先來粗略地看一看makefile的規則。

  

makefile

  target可以是一個object

file(目标檔案),也可以是一個執行檔案,還可以是一個标簽(label)。對于标簽這種特性,在後續的“僞目标”章節中會有叙述。

  prerequisites就是,要生成那個target所需要的檔案或是目标。

  command也就是make需要執行的指令。(任意的shell指令)

  這是一個檔案的依賴關系,也就是說,target這一個或多個的目标檔案依賴于prerequisites中的檔案,其生成規則定義在

command中。說白一點就是說,prerequisites中如果有一個以上的檔案比target檔案要新的話,command所定義的指令就會被執行。這就是makefile的規則。也就是makefile中最核心的内容。

  說到底,makefile的東西就是這樣一點,好像我的這篇文檔也該結束了。呵呵。還不盡然,這是makefile的主線和核心,但要寫好一個makefile還不夠,我會以後面一點一點地結合我的工作經驗給你慢慢道來。内容還多着呢。:)

【一個示例】

  正如前面所說的,如果一個工程有3個頭檔案,和8個c檔案,我們為了完成前面所述的那三個規則,我們的makefile應該是下面這個樣子的。

makefile

  反斜杠(\)是換行符的意思。這樣比較便于makefile的易讀。我們可以把這個内容儲存在名字為“makefile”或“makefile”

的檔案中,然後在該目錄下直接輸入指令“make”就可以生成執行檔案edit。如果要删除執行檔案和所有的中間目标檔案,那麼,隻要簡單地執行一下 “make

clean”就可以了。

在這個makefile中,目标檔案(target)包含:執行檔案edit和中間目标檔案(*.o),依賴檔案(prerequisites)就是冒号後面的那些

.c 檔案和 .h檔案。每一個 .o 檔案都有一組依賴檔案,而這些 .o 檔案又是執行檔案 edit

的依賴檔案。依賴關系的實質上就是說明了目标檔案是由哪些檔案生成的,換言之,目标檔案是哪些檔案更新的。

在定義好依賴關系後,後續的那一行定義了如何生成目标檔案的作業系統指令,一定要以一個tab鍵作為開頭。記住,make并不管指令是怎麼工作的,他隻管執行所定義的指令。make會比較targets檔案和prerequisites檔案的修改日期,如果prerequisites檔案的日期要比targets檔案的日期要新,或者target不存在的話,那麼,make就會執行後續定義的指令。

這裡要說明一點的是,clean不是一個檔案,它隻不過是一個動作名字,有點像c語言中的lable一樣,其冒号後什麼也沒有,那麼,make就不會自動去找它的依賴性,也就不會自動執行其後所定義的指令。要執行其後的指令(不僅用于clean,其他lable同樣适用),就要在make指令後明顯得指出這個lable的名字。這樣的方法非常有用,我們可以在一個makefile中定義不用的編譯或是和編譯無關的指令,比如程式的打包,程式的備份,等等。

【make是如何工作的】

在預設的方式下,也就是我們隻輸入make指令。那麼,

make會在目前目錄下找名字叫“makefile”或“makefile”的檔案。

如果找到,它會找檔案中的第一個目标檔案(target),在上面的例子中,他會找到“edit”這個檔案,并把這個檔案作為最終的目标檔案。

如果edit檔案不存在,或是edit所依賴的後面的 .o

檔案的檔案修改時間要比edit這個檔案新,那麼,他就會執行後面所定義的指令來生成edit這個檔案。

如果edit所依賴的.o檔案也不存在,那麼make會在目前檔案中找目标為.o檔案的依賴性,如果找到則再根據那一個規則生成.o檔案。(這有點像一個堆棧的過程)

當然,你的c檔案和h檔案是存在的啦,于是make會生成 .o 檔案,然後再用 .o 檔案生成make的終極任務,也就是執行檔案edit了。

  這就是整個make的依賴性,make會一層又一層地去找檔案的依賴關系,直到最終編譯出第一個目标檔案。在找尋的過程中,如果出現錯誤,比如最後被依賴的檔案找不到,那麼make就會直接退出,并報錯,而對于所定義的指令的錯誤,或是編譯不成功,make根本不理。make隻管檔案的依賴性,即,如果在我找了依賴關系之後,冒号後面的檔案還是不在,那麼對不起,我就不工作啦。

  通過上述分析,我們知道,像clean這種,沒有被第一個目标檔案直接或間接關聯,那麼它後面所定義的指令将不會被自動執行,不過,我們可以顯示要make執行。即指令——“make

clean”,以此來清除所有的目标檔案,以便重編譯。

  于是在我們程式設計中,如果這個工程已被編譯過了,當我們修改了其中一個源檔案,比如file.c,那麼根據我們的依賴性,我們的目标file.o會被重編譯(也就是在這個依性關系後面所定義的指令),于是file.o的檔案也是最新的啦,于是file.o的檔案修改時間要比edit要新,是以

edit也會被重新連結了(詳見edit目标檔案後定義的指令)。

  而如果我們改變了“command.h”,那麼,kdb.o、command.o和files.o都會被重編譯,并且,edit會被重連結。

參考: