密封性

回報問題 查看原始碼

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

總覽

假如有相同的輸入原始碼和產品設定,密封建構系統一律會將建構與主機系統隔離,藉此傳回相同的輸出內容。

為隔離建構作業,對本機或遠端主機上安裝的程式庫和其他軟體沒有任何密封性。它們取決於特定版本的建構工具 (例如編譯器),以及依附元件 (例如程式庫)。這使得建構程序保持獨立狀態,因為它不依賴建構環境以外的服務。

外觀的兩大面向是:

  • 隔離:密封式建構系統會將工具視為原始碼。可以下載工具副本、管理儲存空間,並在代管檔案樹狀結構中使用。這會在主機機器和本機使用者 (包括已安裝的語言版本) 之間建立區隔。
  • 來源身分:密封建構系統會嘗試確保輸入的相同性。程式碼存放區 (例如 Git) 會使用一組專屬的雜湊碼識別一組變異。密封建構系統會使用此雜湊識別建構輸入的變更。

優點

外觀建構的主要優點如下:

  • 速度:可快取動作的輸出,且除非輸入內容有所變更,否則系統不會再次執行該動作。
  • 平行執行:針對指定輸入與輸出,建構系統可建構所有動作的圖表以計算有效和平行執行。建構系統會載入規則並計算動作圖表和雜湊輸入,以在快取中查詢。
  • 多個建構作業:您可以在同一部機器上建構多個密封版本,每個版本使用不同工具和版本進行建構。
  • 可重現性:密封組件非常適合疑難排解,因為您知道建構版本的確切條件。

辨識不密封

如果您準備改用 Bazel,只要預先改善現有建構的安全防護機制,就可以進行遷移作業。某些建構在非建構中的非經驗來源如下:

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

排解非密封版本的建構問題

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

  • 確保空值的依序建構:如果您執行 make 並成功執行建構作業,則再次執行建構作業不應重新建構任何目標。如果您分別執行不同的建構步驟兩次或使用不同的系統,請比較檔案內容的雜湊值以取得不同的結果,該版本就無法重現。
  • 執行各種步驟,從各種潛在的用戶端機器對本機快取命中偵錯,以確保您在遇到作業時遇到任何用戶端環境問題。
  • 在 Docker 容器內執行建構作業,而該容器僅包含已簽出的來源樹狀結構和主機工具明確列出的清單。建構中斷和錯誤訊息會捕捉隱含的系統依附元件。
  • 使用遠端執行規則找出並修正密封問題。
  • 在各動作層級啟用嚴格的沙箱,因為建構作業中的狀態可能是有狀態的,並且會影響建構或輸出內容。
  • 工作區規則可讓開發人員將依附元件新增至外部工作區,但必須有足夠的豐富程度,才能在程序中執行任意處理作業。只要在 Bazel 指令中加入 --experimental_workspace_rules_log_file=PATH 旗標,即可在 Bazel 工作區規則中取得一些可能與密封作業無關的記錄。

Bazel 的傳統

如要進一步瞭解其他專案如何搭配 Bazel 使用密封版本,請參閱以下 BazelCon 討論內容: