Linux下的makefile編寫 ——陳皓《跟我一起寫Makefile》學習筆記(二)

慧珊家的羊發表於2020-10-25

學習書籍原地址《跟我一起寫Makefile》,感謝原作者的付出!

Makefile總述

一、Makefile裡有什麼

主要包含 :顯示規則、隱晦規則、變數定義、檔案指示和註釋。

  1. 顯示規則
    顯示規則說明如何生成一個或多個目標檔案,寫Makefile的時候都是在寫顯示規則。
  2. 隱晦規則
    因為make的自動推導功能,可以將Makefile簡化。
  3. 變數的定義
    變數一般都為字串,類似於c的巨集,呼叫時使用$(變數名)格式呼叫。
  4. 檔案指示
    包括三個部分:
    1) 在一個Makefile中引用另一個Makefile,就像include;
    2)根據某些情況指定Makefile中的有效部分,就像#if;
    3)定義一個多行命令。
  5. 註釋
    Make中只有行註釋,用“#”字元進行註釋。

二、Makefile的檔名

預設情況下,make會在目錄下尋找名字為“GNUmakefile”、“makefile”和“Makefile”的檔案。
最好使用“Makefile”,首字母大寫,有種醒目的感覺;最好不要使用“GNUmakefile”,只有GNU的make對這個檔名敏感;有些make只對“makefile”敏感。

若要自定義檔名,可以在make後加上“-f”或者“–file”引數來指定你的自定義Makefile。

make -f myMake.Linux

或者

make --file myMake.Linux

三、引用其他的Makefile

語法:

include <filename>

filename可以使當前作業系統Shell的檔案模式(可以包含路徑和萬用字元)
在include前可以有一些空字元,但不能是[TAB]鍵開始;include可以同時包含幾個Makefile,和變數差不多。例如:

  1. 目錄下有多個.mk字尾的Makefile檔案(a.mk b.mk c.mk):

    include *.mk
    

    等價於

    include a.mk b.mk c.mk 
    
  2. 滿足1的基礎上,定義一個變數$(makefiles),裡面包含了d.mk和e.mk:

    #定義變數
    makefiles = d.mk e.mk
    

    則要包含所有的Makefile檔案,可以這樣寫:

    #包含所有makefile
    include *.mk $(makefiles)
    

    等價於

    include a.mk b.mk c.mk d.mk e.mk
    

當make執行時,會將include所指出的其他Makefile的內容暫時安置在當前位置,就像c/c++的#include。如果檔案都沒有指定絕對路徑或是相對路徑的話,make會在當前目錄下首先尋找,如果當前目錄下沒有找到,那麼:

  1. 如果make後有“-I”或者“–include-dir”引數,make會在引數指定的目錄下尋找。

  2. 如果目錄/include(一般是/usr/local/bin或者/usr/include) 存在的話,make也會去找。

  3. 如果檔案沒有找到,make會生成一條警告資訊,然後繼續載入其他檔案,完成Makefile的讀取後,make會再次重新查詢沒有找到的檔案,如果還是沒有,那麼make會生成致命資訊,退出執行。可以在include前加一個“-”號讓make忽略那些找不到的檔案,繼續執行下去:

    -include <filename>
    

    “-”在之前的clean命令中使用過,它的意思是:無論在命令執行過程中出現什麼錯誤,都不要報錯並繼續執行。
    -include和其他版本的make相容的相關命令是sininclude,作用相同。

四、環境變數MAKEFILES

MAKEFILES變數作用和include類似,其值是其他的Makefile,空格分隔。與include不同的地方在於用這個方法引入的Makefile裡的“target”不會起作用,如果MAKEFILES中定義的檔案有錯誤,make也不會報錯。
建議不要使用MAKEFILES,因為當你使用這個變數,並且make時,所有的Makefile都會被影響。如果有時候Makefile出現的異常,可以看看當前環境中有沒有這個變數。

五、make的工作方式

GNU make(其他的make類似):

  • 第一階段

    1. 讀取所有的Makefile;
    2. 讀入被include的其它Makefile;
    3. 初始化檔案中的變數;
    4. 推導隱晦規則,並分析所有規則;
    5. 為所有的目標檔案建立依賴關係鏈。
  • 第二階段

    1. 根據依賴關係,決定哪些目標要重新生成;
    2. 執行生成命令。

在第一個階段中,make會將定義的變數在當前位置展開,但make並不會完全馬上展開,如果變數出現在依賴關係的規則中,那麼僅當這條依賴被決定要使用了,變數才會在其內部展開。

相關文章