假設我們的規則:GNU make的先決條件是什麼?
a: b c d e
和b
,c
,d
和e
是相互獨立的。
b
,c
,d
,e
的定義是否爲定義?看起來他們通常會按順序製造b
,c
,d
,e
,但是有時候會發生這種情況,順序會不同嗎?
假設我們的規則:GNU make的先決條件是什麼?
a: b c d e
和b
,c
,d
和e
是相互獨立的。
b
,c
,d
,e
的定義是否爲定義?看起來他們通常會按順序製造b
,c
,d
,e
,但是有時候會發生這種情況,順序會不同嗎?
當然,如果我用make -j a
,他們可能都得到在同一時間建(取決於是否b
,c
,d
或e
又將有其他/相互依存關係)。
在權利命令,根據您提供的規則。對於您的特定示例,這可能意味着許多不同(4!= 24,來自內存)訂單中的任何一個。
所有make
程序可以自由選擇他們喜歡的順序,只要依賴關係得到遵守即可。如果您的示例中有其他規則,例如c: b
,那麼c
將在b
之前生成(但事實並非如此,正如您指出的那樣)。
如果您需要依賴特定訂單,則需要更多規則來執行該訂單。否則make
可以做它喜歡的。 GNU Make的documentation僅說明如何處理規則,而不是處理規則中的依賴關係的順序。最合理的順序(無論如何)是他們上市的順序,但不能保證。
不,訂單沒有定義。這就是整個點使用聲明式依賴性編程:計算機可以選擇最佳評估順序,或者實際上,在同一時間評估它們,甚至。
不,你不能依賴沒有依賴關係的順序。
GNU make的先決條件是什麼?
這取決於前提條件的類型。根據GNU Make Manual,第4節。2:
實際上有由 GNU理解兩種不同類型的先決條件使:如在先前 部分所述正常的先決條件,和訂單僅先決條件。一個正常的先決條件會產生兩個 語句:首先,它會調用調用 的配方的順序:在運行目標的配方之前,目標的所有前提條件的配方將爲 。其次,它強制依賴關係爲 :如果任何先決條件比目標更新,則目標被認爲是過時的並且必須重建。
通常,這正是你想要的:如果目標的先決條件是 更新,那麼目標也應該更新。
然而,有時候,你必須要強加的規則 特定順序被調用不迫使 目標如果執行這些規則之一被更新的情況。在這種情況下,您要定義 訂單先決條件。僅限訂單 先決條件可通過在 先決條件列表中放置管道符號(|)來指定:管道符號 左側的任何先決條件均爲正常;任何先決條件向右是順序僅:當然
targets: normal-prerequisites | order-only-prerequisites
正常的先決條件部分可以是空的。此外,您可能還會爲同一個目標聲明多行必備條件: 它們被適當地附加(正常先決條件會附加到 正常先決條件列表;僅限訂單先決條件是附加到僅限訂單先決條件列表的 ) 。請注意,如果您 聲明同一個文件既是普通訂單也是僅限訂單 先決條件,則普通先決條件優先(因爲它們的 僅具有僅限訂單的先決條件的行爲的超集)。
考慮一個例子,其中您的目標將被放置在單獨的 目錄中,並且該目錄在運行
make
之前可能不存在。在 這種情況下,您希望在任何 目標被放入之前創建該目錄,但是,由於目錄 上的時間戳會隨着文件的添加,刪除或重命名而發生更改,所以我們當然不希望重建所有目錄目錄的 時間戳發生更改時的目標。管理的一種方式是與訂單僅 先決條件:使目錄中的訂單僅在所有 目標的前提條件: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)
現在的規則,以創建「objdir」目錄將被運行,如果需要的話, 建立任何'.o'之前,但不會建立'.o',因爲 'objdir'目錄時間戳已更改。
雖然這並沒有真正強加一個順序,但至少不是一個正常的先決條件。它只是說,對於只有訂單的先決條件,gmake應該忽略時間戳。這是一個先決條件,所以它必須存在才能運行當前規則,但由於它是僅限訂單的先決條件,所以它的時間戳/狀態不會觸發當前規則。 (這不排除其他依賴性導致僅依賴訂單的依賴項執行它們的命令。) – simpleuser 2015-03-19 20:22:56
從上面的gnu make文檔中可以看出:有時候,您有一種情況,您希望對特定的規則一個目標將被調用,而不會強制目標被更新,如果其中一個規則被執行。「這似乎相當糟糕 - 措辭只是爲了或僅僅是先決條件。直到我的理解,訂單唯一的先決條件只是一個先決條件,它不強制'make'在目標發生變化時重建目標。 – SebNag 2017-10-06 10:55:03
如果訂單很重要,您可以選擇使用recursive make來強制執行。例如,假設你不關心b和c的順序是什麼,只要它們都是在d之前創建的,d是在e之前創建的。然後,你可以寫你的規則爲:
a: b c
$(MAKE) d
$(MAKE) e
# Additional steps to make a
注意的是,根據d和e中的複雜性,這種做法可能會做壞事到您的構建時間:爲參數見Recursive Make Considered Harmful(PDF)反對做這種方式。
這並沒有真正回答這個問題,所以我很驚訝它被接受。 – 2009-10-30 01:11:53
我在那裏讀到的問題是:「看起來他們通常會按照'b','c','d','e'的順序製作,但有時候會發生,順序會不同?」。我很確定我提供了一個反例。我想,你的意見可能會有所不同。 – 2009-10-30 06:59:12
*僅限訂單 - 先決條件* **是以特定順序構建的。不過,我不確定海報是否知道除了基於他的假設的正常先決條件之外還有其他任何東西。 – jww 2014-07-27 14:08:39