文化遺產

回報問題 查看原始碼 Nightly · 8.0 7.4 . 7.3 · 7.2 · 7.1 · 7.0 · 6.5

本頁將說明密封性、使用密封式建構的優點,以及在建構中識別非密封式行為的策略。

總覽

當提供相同的輸入來源程式碼和產品設定時,密封式建構系統會將建構作業與主機系統的變更隔離,因此一律會傳回相同的輸出內容。

為了隔離版本,密封版本對本機或遠端主機電腦上安裝的程式庫和其他軟體不敏感。這些模組會依附特定版本的建構工具 (例如編譯器) 和依附元件 (例如程式庫)。這樣一來,建構程序就會自給自足,因為它不依賴建構環境以外的服務。

密封性有兩個重要面向:

  • 隔離:密封式建構系統會將工具視為原始碼。這些工具會下載工具的副本,並管理其儲存空間和在受管理的檔案樹狀結構中使用的情況。這會在主機和本機使用者之間建立隔離,包括已安裝的語言版本。
  • 來源識別:密封式建構系統會盡力確保輸入內容的一致性。程式碼存放區 (例如 Git) 會使用專屬雜湊碼來識別程式碼變異集。密封式建構系統會使用這個雜湊值,找出建構作業輸入內容的變更。

優點

密封式版本的主要優點如下:

  • 速度:動作的輸出內容可快取,除非輸入內容變更,否則動作不必再次執行。
  • 平行執行:針對指定的輸入和輸出,建構系統可建立所有動作的圖表,以便計算有效的平行執行作業。建構系統會載入規則,並計算動作圖表和雜湊輸入內容,以便在快取中查詢。
  • 多個版本:您可以在同一部電腦上建構多個密封版本,每個版本都使用不同的工具和版本。
  • 可重現性:密封式版本可讓您瞭解產生版本的確切條件,因此非常適合用於疑難排解。

找出非密封性

如果您準備切換至 Bazel,建議您先改善現有版本的密封性,以便日後更輕鬆地進行遷移。以下是導致版本不具備密封性的一些常見原因:

  • .mk 檔案中進行任意處理
  • 非確定性建立檔案的動作或工具,通常會涉及版本 ID 或時間戳記
  • 主機之間不同的系統二進位檔 (例如 /usr/bin 二進位檔、絕對路徑、系統 C++ 編譯器,適用於原生 C++ 規則自動設定)
  • 在建構期間寫入來源樹狀結構。這可避免同一個來源樹狀結構用於其他目標。第一個版本會寫入來源樹狀結構,修正目標 A 的來源樹狀結構。那麼,嘗試建構目標 B 可能會失敗。

排解非密封式建構問題

從本機執行開始,影響本機快取命中的問題會揭露非密封動作。

  • 確保空值的連續建構作業:如果您執行 make 並順利完成建構作業,再次執行建構作業時,不應重新建構任何目標。如果您執行每個建構步驟兩次或在不同系統上執行,比較檔案內容的雜湊值並取得不同的結果,則無法重現建構作業。
  • 執行步驟,從各種潛在的用戶端電腦偵錯本地快取命中,確保您能找出任何用戶端環境洩漏至動作的情況。
  • 在 Docker 容器中執行建構作業,該容器只包含已簽出的來源樹狀結構和主機工具的明確清單。建構中斷和錯誤訊息會擷取隱含的系統依附元件。
  • 使用遠端執行規則找出並修正密封性問題。
  • 在個別動作層級啟用嚴格的沙箱功能,因為建構中的動作可能具有狀態,並影響建構或輸出內容。
  • 工作區規則可讓開發人員將依附元件新增至外部工作區,但這些規則的功能相當豐富,可讓程序中執行任意處理作業。您可以將標記 --experimental_workspace_rules_log_file=PATH 新增至 Bazel 指令,取得 Bazel 工作區規則中可能不具密封性的動作記錄。

使用 Bazel 實現密封

如要進一步瞭解其他專案如何成功使用 Bazel 的密封式建構作業,請參閱以下 BazelCon 演講: