OK6410 --- Makefile

----------更新日期2019-07-11----------

參考文檔:GNU make Version 4.2

GNU make是由Richard Stallman和Roland McGrath實現的,並從3.76版本開始由Paul D. Smith負責開發。make工具自動確定一個大型程序中的哪些部分需要重新編譯,併發出命令以重新編譯它們。

本系列博文中將使用C語言編寫的程序作爲示例。當然,你也可以使用make這個工具來編譯其他語言,只要它的編譯器可以通過shell命令行運行。實際上,make不但可以用於編譯程序,還可以用於其它的任務,如當修改一些文件時,會根據修改的文件自動更新或重建與其相關的其他文件。

要使用make工具,首先要創建文件名爲Makefile的文件,該文件用於描述程序中文件之間的關係,如該程序中哪些源文件需要編譯,如何鏈接編譯後的目標文件,如何生成最終的執行文件等等。一旦Makefile文件中的編譯規則編寫好,編寫的格式正確,在該Makefile文件當前目錄下的命令行中輸入make命令,make工具就會根據Makefile的數據庫和最後修改的時間確定更新哪些文件並如何更新。Makefile數據庫中記錄着如何處理每個程序文件的規則方法。你還可以通過爲make命令添加命令選項來控制那個文件應該被重新編譯或如何重新編譯。

1 Makefile簡介

簡單來說,Makefile這個文件就是告訴make該做什麼。通常,makefile告訴make如何編譯和鏈接程序。make 通過比較對應文件(規則的目標和依賴,)的最後修改時間,來決定哪些文件需要更新、那些文件不需要更新。對需要更新的文件 make 就執行數據庫中所記錄的相應命令(在 make 讀取 Makefile 以後會建立一個編譯過程的描述數據庫。此數據庫中記錄了所有各個文件之間的相互關係,以及它們的關係描述)來重建它,對於不需要重建的文件 make 什麼也不做。

1.1 Makefile規則的簡單介紹

規則書寫的模板:
要生成的目標文件:需要依賴的文件
[tab]生成目標文件所需要執行的命令1(注意:需要在每條命令的開頭輸入一個製表符,即[tab]鍵)
[tab]命令2
[tab]命令3
[tab]........

示例1:
如創建一個點亮裸板LED的程序,我們最終需要下載到開發板的程序是一個二進制的文件led.bin。所以,Makefile可以如下:

led.bin:led.elf(規則1)
	arm-linux-objcopy -O binary -S -g $^ $@(命令1.1)

led.elf:led.o(規則2)
	arm-linux-ld -Ttext 0xc000000 -o $@ $^	(命令2.1)

led.o:led.s(規則3)
	arm-linux-gcc -c -g -o $@ $^(命令3.1)

1.2 make是如何工作的

默認的情況下,make執行的是Makefile中的第一個規則,此規則的第一個目標稱之爲“最終目標”或者“終極目標”(就是一個Makefile最終需要更新或者創建的目標)。示例1中的“led.bin”就是Makefile中的第一個目標,也就是最終目標。它依賴led.elf這個文件,make會作出三種處理情況:

  1. 如果led.elf不存在,則執行規則2中的操作,依賴led.o文件生成led.elf目標文件;
  2. 如果led.elf存在,但源文件led.s的時間比led.elf“更新”,則重新編譯程序,更新led.bin文件;
  3. 如果led.elf存在,且led.elf的修改時間比led.o或led.s“更新”,則不做任何操作。

由示例1的規則可知,從源文件led.s到led.bin,需要三步操作,led.s(執行命令3.1,生成)led.o(執行命令2.1,生成)led.elf(執行命令1.1,生成)led.bin。這就像一種遞歸,首先明確最終目標led.bin,led.bin依賴led.elf,但led.elf不存在,就需要執行以led.elf作爲目標的規則來生成led.elf(即執行規則2);而led.elf又依賴led.o,如果led.o也不存在,則執行規則3來生成led.o;當規則3和規則2執行完,就可以順利得到led.elf文件,再執行規則1就可以得到led.bin文件。

當修改了源文件led.s後,由於led.s文件的時間比led.o“更新”,所以需要重新編譯源文件led.s,得到led.o文件;以此類推,最終目標led.bin也將被更新。

在make命令運行過程中,任何一條規則出錯,make將報錯並退出。整個過程 make 只是負責執行規則,而對具體規則所描述的依賴關係的正確性、規則所定義的命令的正確性不做任何判斷。就是說,一個規則的依賴關係是否正確、描述重建目標的規則命令行是否正確,make 不做任何錯誤檢查。因此,需要正確的編譯一個工程。需要在提供給 make 程序的 Makefile 中來保證其依賴關係的正確性、和執行命令的正確性。

1.3 清除工作目錄中的過程文件

通常,當我在工作目錄環境下的命令行中輸入make命令後,除了在工作目錄裏生成最終目標,如示例1中的led.bin,還會生成相關的中間目標文件,如示例1中的led.o,led.elf。這些文件一般是沒有什麼用途的,因爲我們只需要led.bin用於下載到開發板。那麼,我們就可以通過輸入命令make clean來清理這些在編譯過程中產生的臨時文件。下面修改一下示例1,如下:

led.bin:led.elf(規則1)
	arm-linux-objcopy -O binary -S -g $^ $@(命令1.1)

led.elf:led.o(規則2)
	arm-linux-ld -Ttext 0xc000000 -o $@ $^	(命令2.1)

led.o:led.s(規則3)
	arm-linux-gcc -c -g -o $@ $^(命令3.1)

.PHONY:clean all_clean
#刪除當前目錄下的所有.o,.elf後綴的文件
clean:
    rm *.o *.elf
#刪除當前目錄下的所有.o,.elf,以及.bin後綴的文件
all_clean:
    make clean
    rm *.bin

 

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