建構圖表融合

建構圖融合是單一建構叫用的屬性 以正確順序執行所有必要行動 輸出的內容比輸入

Fuchsia 採用時間戳記導向的 Ninja 建構系統,Ninja 表達 會將建構作業轉換為輸入/輸出檔案和動作的圖表 會產生輸出內容

執行建構時,例如如果使用 fx build,Ninja 會掃遍建構圖表 執行輸出值不存在或輸入 自上次執行後變更過,所有按照頂端順序排列 (依附元件早於 相依項目)。

不過,建構圖表動作並未經過驗證,無法實現 輸出量比輸入值還新,這可能會導致收斂問題。

常見根本原因

導致 Ninja 融合問題的方式有很多種。儘管如此 瞭解造成這些問題的常見根本原因。

未產生輸出內容

如果宣告建構動作會產生輸出內容,但實際上並未產生 產生輸出內容 (在某些情況下) 就會引發收斂 以負載平衡機制分配流量 即可降低應用程式發生效能問題的風險例如,動作可能會宣告在 成功,卻無法產生或輕觸此戳記檔案,或儲存至不正確的圖章 或 HTTP/HTTPS 位置

輸出內容已過時 (並非所有輸入內容的更新時間)

Ninja 知道輸出值比所有輸入值還新。如果有 輸入的資料有所改變,Ninja 就會重複輸入 產生輸出內容所需的步驟。

不過,如果產生輸出內容的動作並未更新輸出內容, 這樣一來,模型就會造成 過時。

這是因為動作檢查輸入內容、 和輸出內容的內容無關,但沒有 更新輸出內容中的修改時間戳記 (即「觸控」或「戳記」) 輸出內容)。

修改輸入內容

動作可以修改輸入內容。通常是動作的輸入內容 它應該只以唯讀存取權開啟。不過, 不只能寫入。也就是說,如果你的動作需要修改輸入內容 請務必在寫入任何輸出內容前執行或者您必須在寫入後修改輸入內容 請務必更新輸出內容的時間戳記,再退出 動作。否則,您的一或多個輸入值就會更新。 導致 Ninja 無法理解 輸出已過時

修改動作的輸入內容可能也會帶來競爭狀況, 重現問題的非確定性問題。如果有多個動作 其中一個輸入內容會修改輸入內容,建構作業就會無法 導致任何動作造成的輸入時間戳記較新。 與任何動作相較輸出內容在依依附元件排序的執行作業中, 無法保證獨立動作的順序。

避免修改輸入內容。

Ninja 建構系統會依符號連結判斷時間戳記。這可以 可使系統將軟符號連結參與 Ninja 規則, 輸入依附元件或輸出內容符號連結的時間戳記 (而非 才視為過時和即時性。詳情請見 ninja#1186stat()lstat() 和 示範硬連結 (不含 -sln) 會造成問題,導致多個 參照指向同一個檔案系統物件 時間戳記。

即使是簡單的連結動作,也可能會造成問題。假設想一個簡單的動作 輸入 src、輸出 $target_out_dir/dst,而叫用的動作為 ln src $target_out_dir/dst。顧名思義,這個行動會正確凝聚在一起。不過 action() 的行為可能會在建構系統的其他位置覆寫,例如 納入動作和其他動作因此,您的內部動作 如果 src 的時間戳記比包裝函式動作的舊時間戳記更早,就會認定為免人工管理 指令碼隨後會視為已超過 dst (其輸出內容 其中有輸入的時間戳記)。copy() 不同 因為這類物件就不會包裝

避免在動作輸入和輸出內容中使用符號連結和硬連結。

如要建立副本,建議使用內建的 copy() 目標。

時間戳記精細程度

新型檔案系統會儲存檔案的時間戳記,例如上次使用時間 奈秒解析度)。一些較舊的執行階段,例如 Python 2.7 以較低解析度保留檔案時間戳記,例如執行個體毫秒。是 因此,動作就算是讀取輸入,並寫入 系統視為「現在」的時間戳記但實際上早於時間戳記 而輸入內容 (如果是輸入和輸出值) 且輸出內容的時間戳記會在毫秒後截斷 數字。

在本文撰寫期間,我們設有機制, 建構中的 Python 動作會使用 Python 3.x 執行,部分操作可避免此問題。

建立對話診斷

我們使用以下工具診斷建構融合問題:

  • 修訂佇列中的 Ninja 免人工管理
  • 檔案系統存取操作追蹤

Ninja 免人工管理

Fuchsia 的承諾使用佇列 (CQ) 會驗證變更是否成功建構, 也要讓建構系統處於完全不處理狀態 建構叫用。

CQ 的建構收斂錯誤示例:

fuchsia confirm no-op
ninja build does not converge to a no-op

同一個版本會在 CQ 中執行,變更才能合併到來源樹狀結構中。 確保變更不會導致建構作業中斷完成建構作業後 成功後,CQ 會再次叫用 Ninja,並預期 Ninja 回報 "no work to do"。這可做為可信度檢查,因為構圖應有正確的建構圖 變更為「converge」免人工管理

如果這項聲度檢查失敗,CQ 就會在名為 fuchsia confirm no-op

重現 Ninja 融合問題

當來源樹狀結構與您的變更保持同步時,只要嘗試下列方法即可:

fx build

這個指令應會顯示:

ninja: no work to do.

如果情況並非如此,而且正在執行實際的建構動作,請執行 執行同樣的指令如果第二次叫用還是「沒有運作」 那你的問題就重現了如果您抵達「沒有公司」仍,請嘗試 包括:

# Clean your build cache
rm -rf out
# Set up the build specification again
fx set ...
# Build
fx build
# Build again, expecting no-op
fx build

排解 Ninja 融合問題

在 CQ 結果頁面中,失敗步驟 confirm no-op 下方會顯示 數個連結:

  • 執行作業詳細資料
  • 忍者 -d 說明 -n -v
  • 骯髒路徑

ninja -d explain -n -v 連結會顯示應有的資訊 執行下列指令,在本機重現:

fx ninja -C $(fx get-build-dir) -d explain -n -v

這個連結會導向「骯髒的路徑」列出關聯性最高 可能不準確或不適當您可能會看到一行文字檔案,內容最有可能如下:

ninja explain: output <...> doesn't exist
...

這個檔案中的每一行線條都像骨磚塊。請先開始排解問題 我們要看第一個發起鏈反應的骨牌積木 代表你付出額外心力例如,在上述範例中,某個輸出內容 檔案不存在,使 Ninja 會重新執行 ,接著重新執行相依動作。

檔案系統存取追蹤

也有建構工具可以追蹤動作」檔案系統存取權診斷資料 例如:

Not all outputs of //your:label were written or touched, which can cause subsequent
build invocations to re-execute actions due to a missing file or old timestamp.

Required writes:
...

Missing outputs:
...

Stale outputs:
...

診斷不允許寫入的輸入內容如下:

Unexpected file accesses building //your/target:label, following the order they are accessed:
(FileAccessType.WRITE /path/to/input-that-should-not-be-touched.txt)

相較於 Ninja 免人工管理,這項檢查會逐一檢查每個動作 並立即診斷造成收斂效的眾多原因之一 而不是之後執行完整的 fx build 指令。這個 可讓您找出一些原本可能會因為 競爭狀況。

排解追蹤動作失敗問題

如要在本機啟用動作追蹤,請執行下列其中一項操作:

  • 執行 fx set ... --args=build_should_trace_actions=true
  • 執行 fx args,在編輯器中新增 build_should_trace_actions=true。 儲存並結束

然後fx build //your/failing:target

根據動作的指令碼或指令碼,檢查訊息中的檔案 看看這些伺服器是否屬於 常見問題