[make]makefile使用積累

【注】:文中所指手冊皆爲GNU make Version 4.1shell

 

 一、make的通常特性

1.一、Makefiles的構成

  Makefiles包含五種元素: 顯式規則(explicit rules), 隱式規則(implicit rules), 變量定義(variable definitions),指令(directives), 和註釋(comments)。其中沒有提到函數,函數應該歸於變量之中吧。函數

  • 顯式規則:指導什麼時候和怎樣更新一個或多個文件(targets)。
    • 顯式規則
  • 隱式規則

1.二、make如何讀入makefile【手冊3.7節】

  GNU經過兩步徹底分離的步驟來完成這項工做。(其實我以爲是三步,由於第一步明顯地分紅兩個階段)第一階段(read-in),make讀全部相關的makefile(包括include makefiles),創建起其中的變量和規則(makefile就是由變量和規則組成的?);而後構建target和prerequisites的依賴關係;第二階段(target-update),make利用前一步整理的關係決定哪一個target須要重建,從而調用相應的規則。ui

  make的這種「兩步」工做方式決定了變量和函數的兩種不一樣的展開方式:當即展開、延遲展開。當即展開是在第一階段前期作的,(我的理解就是邊讀邊展開);延遲展開是在第一階段後期甚至第二階段才作的(我的理解是在全部makefile都讀入之後,整理各變量和規則依賴關係時展開)遞歸

變量賦值ip

  • immediate = deferred
  • immediate ?= deferred
  • immediate := immediate
  • immediate ::= immediate
  • immediate += deferred or immediate
  • immediate != immediate

變量名都是理解展開的,變量值則分狀況了。ci

規則定義(規則都是一種展開方式,無論它是什麼形式的)
immediate : immediate ; deferred
  deferredrem

二、變量

通常規則:get

  • 變量是一個字符序列,這個序列絕對不能包含‘:’, ‘#’, ‘=’,和空白這四類字符,除數字、字母、下劃線的自它字符也要當心使用;
  • 變量名區分大小寫;
  • 變量引用使用變量引用符號'$'加圓括號或大括號。如‘$(foo)’ or ‘${foo}’都是對foo變量的引用;
  • 若是變量名只有一個字符,引用變量時括號能夠省去,譬如$x,但官方不建議這樣作,這個作法是保留給自動變量使用的;

兩種變量:遞歸變量、簡單變量 (很是重要)it

  • 遞歸展開變量是用「=」符號或define指令定義的變量;
  • 簡單展開變量是用‘:=’ or ‘::=’符號定義的變量,這兩種符號對GNU是同樣的,但POSIX只認‘::=’
  • 簡單變量在定義時就對它的值進行展開,而遞歸變量只有在須要展開時纔對它的值進行展開;
  • 遞歸變量的優勢在於它能夠引用後面定義的變量,由於它的展開在make讀makefile的第二階段

【例1】:遞歸變量與簡單變量定義io

三、規則

3.一、規則通常特性:

targets(目標) ... : prerequisites (依賴)... ; recipes
  recipes
  ...

  • recipe在prerequisites的下一行以tab鍵開始(tab鍵可使用.RECIPEPREFIX變量的第一個值代替,【手冊6.14節】);
  • recipe還能夠緊跟在prerequisites的同一行,以「;」分隔。這個方法在定義「空recipe」時很是有效;
  • 規則除了用於編譯程序,還能用來幹其它事情,見【手冊2.7節】;

3.一、規則分類

  • 規則分顯式規則、隱式規則;
  • 隱式規則又分爲內建隱式規則(built-in implicit rules)和自定義隱式規則,又叫模式規則(pattern rules)【手冊10】;
  • 自定義隱式規則還有一種方法叫後綴規則(Suffix rules)【手冊10】;
  • 和模式規則相比,後綴規則有使用限制,但它是老技術,使用它能夠保留兼容性【手冊10】;
  • 隱式規則能夠鏈式調用(譬如:a.c -> a.y -> a.o)【手冊10】;

 

3.三、顯式規則

3.四、隱式規則

  • 不少文件的remake工做都是標準的,依照慣例的,因此咱們能夠不用爲這些文件的更新制定規則,這就是隱式規則;
  • 咱們想要target使用隱式規則,惟一要作的就是不要給target指定recipe(空recipe規則)甚至不給target寫規則;
  • 事實上,不少時候咱們要作的是阻止隱式規則發揮做用;

規則作什麼

規則還能作什麼

  

3.二、Prerequisites

四、符號

4.一、@

  @出如今recipe的最前面用於關閉recipe回顯,見【手冊5.2節】

  $@

4.二、$

  變量的引用符號

4.三、通配符

  • 跟Bourne Shell同樣,make的通配符也是‘*’, ‘?’ and ‘[...]’(...表示[]中的內容很豐富);
  • 規則中的通配符:targets和prerequisites中的通配符展開是由make來完成的;recipes中的通配符展開則是由shell來完成的;
  • 變量中的通配符make是不展開的;
  • 但含有通配符的變量用在規則中,變量和通配符都會被展開;
  • 要讓變量中的通配符生效,可使用wildcard函數;
  • 文件名中的通配符'*',譬如*.o
    • 表明匹配全部的「o」文件;
    • 若是搜索目錄裏沒有任何一個「o"文件,則「*.o」表明它的字面意思;
    • 若是搜索目錄裏也沒有「*.o」文件(幾乎是必定的),則make可能會報錯;
  • wildcard函數
    • 能夠用於make不進行通配符展開的地方,譬如變量和函數參數;
    • 跟直接使用通配符相比,它也有優點,當沒有匹配時它輸出空,不會出現使用字面含義的狀況;

【4.3例1】

  objects = *.o

  解釋: 因爲通配符是在變量的值中,因此這個變量就是字面的意思,而不是表明全部的「o」文件,可是,若是這個變量出如今prerequisites,「*」就是通配符。

【4.3例2】

  objects := $(wildcard *.o)

 

 

 

 

四、依賴

  依賴類型

相關文章
相關標籤/搜索