makefile規則

makefile中的規則

概述

規則的通常形式:shell

target: <normal-prerequisites> | <order-only-prerequisites> <; commands>
    <commands>

makefile的構成主體是各類規則。不管是什麼形式的規則,都會描述一個三元組:目標、必要條件、命令。一個規則能夠同時描述一個或者多個甚至無數個工做目標(實際上是無數個規則構成的模式),多目標的規則能夠視爲多個規則的疊加描述,均可拆分紅單一工做目標的規則。工做目標是某個文件名,或者某個「動做」,但不能爲空。必要條件也能夠是具體的文件或者「動做」,能夠爲空。命令是發生更新時交給子shell執行的命令,能夠多條,每條交給一個shell,若是要把全部的命令都給一個shell執行,要把它們整成一行或用連行符號\數據庫

目標和必要條件中的變量會當即擴展,而命令不會擴展。(make會在全部的變量和命令都被加載到數據庫以後,在將要執行命令以前擴展命令中的變量。)若是在定義了.SECONDEXPANSION這個目標,以後的規則中的必要條件都會進行兩次擴展。第二次擴展發生在make讀入全部的變量和規則以後,在執行規則以前。函數

當make讀入makefile後,須要根據必要條件的類型和時間戳與目標的時間戳,決定是否採起更新動做(把命令交給子shell執行)。
必要條件分爲兩種:
普通必要條件。更新目標以前先更新普通必要條件。只要該必要條件的時間戳大於或等於目標的時間戳(尚不存在的文件時間戳能夠認爲是負無窮或者某個古老的時間點),就會致使更新動做;
「order-only「必要條件,(只執行一次的必要條件,|以後的必要條件)。Make要更新這個必要條件時會檢查是否存在該文件,若是存在,就不會繼續更新這個必要條件(無論他的時間戳)也不會所以更新目標;若是不存在,則檢查在這次執行make的過程當中是否執行過以該必要條件爲目標的規則,若是沒有則執行一次,不然結束對此必要條件的更新。ui

下面是常常用到的例子,跟新目標文件之間要求目標文件夾已存在,但總不能每條跟新目標文件的規則裏都執行mkdir -p,這樣雖然也能幹活,但看着難受。更好的辦法是讓目標文件order-only依賴與文件夾,而後針對文件夾的更新動做是mkdir -p,這樣mkdir就只執行一次了。unix

OBJDIR := objdir
OBJS := $(addprefix $(OBJDIR)/,foo.o bar.o baz.o)
$(OBJDIR)/%.o : %.c
    $(COMPILE.c) $(OUTPUT_OPTION) $<
all: $(OBJS)

$(OBJS): | $(OBJDIR)
$(OBJDIR):
    mkdir $(OBJDIR)

具體規則,指定具體的工做目標,若是必要條件中有時間戳靠後的文件,則執行命令。這是最多見的規則。模式規則中,目標使用的是通配符而不是具體的文件名,這讓make對與模式相符的工做目標應用該規則。隱含規則能夠是模式規則,也能夠是內置於make的後綴規則。code

具體規則

具體規則以特定的文件做爲工做目標和必要條件。每一個規則能夠由多個工做目標。意味着每一個工做目標都依賴後面的必要條件。
規則沒必要一次性定義徹底。每當make看到一個工做目標,就會將該工做目標和必要條件加入依存圖。若是工做目標已經存在,任何額外的必要條件會被添加到依存圖中。若是一個工做目標屢次制定了命令(不是一次命令由多條命令組成),則取最後一次命令做爲更新動做,忽略以前的命令,make會給出警告。orm

假想工做目標:工做目標能夠不是真實的文件,表示一個動做,成爲假想工做目標。它老是未更新的,很「舊」,因此每次該規則的命令都會被執行。爲了防止該動做可能與某個文件重名,可用.PHONY:聲明。get

模式規則

背景:it

  • 在包含不少文件的大型程序中,手動指定每條規則將會不切實際。並且,這些命令極可能是重複的代碼,若是修改某處可能引發多處修改,產生難以維護的問題。
  • 許多程序在讀取輸入文件以及產生輸出文件時都會依照慣例。

模式

模式規則中的百分號字符%大致上等效於unix中的星號*,它能夠表明任意多個字符。百分比字符能夠放在模式的任何地方,但只能出現一次。當make搜索要使用的模式規則時,它首先會查找符合的模式規則工做目標,將百分號表明的部分替換到必要條件中來檢查模式規則的必要條件。編譯

例如:

%: %.mod
    $(COMPILE.mod) -o $@ -e $@ $^

%: %.cpp
    $(LINK.cpp) $^ $(LOADLIBES) $(LDLIBS) -o $@

%: %.sh
    cat $< >$@
    chmod a+x $@

靜態模式規則

靜態模式規則與通常模式規則的惟一差異是指定了工做目標的匹配集合。

$(OBJECTS): %.o: %.c
    $(CC) -c $(CFLAGS) $< -o $@

後綴規則

後綴規則是舊時沒有模式規則時的替代品,已棄用。

隱含規則

隱含規則是內置於make的模式規則。要查看make內置了那些規則,可使用-p, --print-data-base命令顯示。此命令還能夠看到內置的變量定義。

當make檢查一個工做目標時,若是找不到它的具體規則,就會使用隱含規則。
使用不帶命令的模式規則能夠屏蔽相應的隱含規則。

例如:

hello:
hello: hello.c

都會自動執行相應的編譯過程。

%: %.o

能夠屏蔽從.o文件連接可執行程序的規則。

雜項

規則中可使用shell的模式匹配,而其餘地方要使用wildcard函數。

規則中的必要條件沒必要一次描述徹底,能夠分爲屢次,可是對於同一規則的命令,只取最後一次描述中的命令。好比:

hello : hello.c
    echo hello
    
hello : include.h
    gcc -o hello hello.c

以hello爲目標的規則中有兩個必要條件hello.cinclude.h,此規則的命令只有gcc -o hello hello.c

相關文章
相關標籤/搜索