[英]Unreliable parallel builds in a makefile with .INTERMEDIATE?
我有一個生成多個輸出文件的工具,眾所周知難以在make中建模。 我正在使用GNU Makefile規則中的配方從單個源文件生成一些目標 ,這看起來簡單可靠。 它幾乎可以工作。
不幸的是,我看到了一些關於並行構建的非常奇怪的行為,它似乎有時會丟棄依賴項; 而且我不明白為什么。
這是我的測試用例:
out3: out1 out2
touch out3
.INTERMEDIATE: out.intermediate
out1 out2: out.intermediate
out.intermediate: in
touch out1 out2
如果我構建一次,它的工作原理:
$ touch in
$ make -f test.mk out3 -j4
touch out1 out2
touch out3
out1
和out2
一起構建,一次,這很好; 然后out3
是從結果中構建的。
現在我觸摸輸入文件,模擬增量構建,然后再試一次:
$ touch in
$ make -f test.mk out3 -j4
touch out1 out2
那是正確地重建out1
和out2
......但是它沒有重建out3
,它應該有。 然后,如果我做另一個構建:
$ make -f test.mk out3 -j4
touch out3
......它趕上了。
這僅適用於並行構建。 -j1
構建工作正常。
這很糟糕 - 我需要能夠依賴正確的構建。 有沒有人知道發生了什么?
這是GNU Make 4.1。
您鏈接的SO答案有錯誤; 令人驚訝的是,很多人顯然已經成功地使用了它。
發生了什么(您可以將-rRd
選項添加到make調用以查看更詳細的內容)是GNU make的目錄緩存的結果。 GNU make不希望文件系統狀態以makefile描述的方式之外的任何方式進行更改,因此它會緩存目錄的內容以提供顯着的性能提升(對於大型makefile /目錄)。
基本上,當make運行規則時:
out.intermediate: in
touch out1 out2
它不會期望此配方將更新除規則中列出的目標之外的任何目標: out.intermediate
。 如果其他文件out1
和out2
已經內置在目錄緩存中(它們將存在,因為它們存在並且我們已經將它們作為out3
先決條件檢查out3
),那么make將不會返回到文件系統並查看它們是否存在已更新或未更新:make“know”他們無法更改,因為根據makefile,沒有任何規則可以更改它們。
有一個簡單的,一個字符的修復,使所有這些工作。 改變這一行:
out1 out2: out.intermediate
對此:
out1 out2: out.intermediate ;
如果你想更明確,你也可以使用這個:
out1 out2: out.intermediate
@:
甚至這個,用於調試:
out1 out2: out.intermediate
@echo Do nothing
所有這些共同點是你現在不僅定義了目標和先決條件之間的依賴關系,而且你還給出了一個應該為該規則調用的配方 。 即使配方為空(如第一個示例中所示),因此make實際上並不運行任何命令,make仍然會推斷out1
和/或out2
上的時間戳可能已更改,並且它將使緩存的修改無效這些目標的時間並從文件系統中重新檢索它們。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.