Bazel 遷移指南

上次更新時間:2025 年 3 月 6 日

本頁提供重要的 Bazel 相關指南,適用於在樹狀結構內 (即使用 fuchsia.git 結帳) 工作的 Fuchsia 開發人員。由於 Bazel 遷移作業會不斷變動,這個頁面會經常更新,以反映重要異動。

摘要

自 2025 年第 1 季起,請遵守下列規範:

  • 如果您不執行產品組裝作業,也不編寫驅動程式庫套件,請勿擔心或開始在 Fuchsia 樹狀結構中編寫 Bazel 檔案。

  • 如要定義新的產品開發板或輸入套件,請使用 Bazel 目標和專屬 Bazel SDK 規則,如這個範例所示。

  • 如果您編寫的 Bazel 驅動程式庫套件僅供 Bazel 定義的開發板使用,請只在 Bazel 中定義這些套件,並使用專屬的 Bazel SDK 規則,如這個其他範例所示。

  • 所有新的開發作業都應在 Bazel 中進行。如果您的開發板剛好依附於現有的 GN 驅動程式庫套件,請先在 GN fuchsia_driver_package() 定義中設定 export_to_bazel = true 引數,將其公開至 Bazel 圖表,然後建立參照 GN 套件構件的 Bazel fuchsia_prebuilt_package() 隨附目標定義 (範例 1 和範例 2)。

  • 以 Bazel 為基礎的驅動程式庫套件只能依附於透過 @fuchsia_sdk 和 @internal_sdk 存放區公開的平台程式庫。

    @fuchsia_sdk 包含一組程式庫,這些程式庫會以 OOT 形式發布,但包含「不穩定」的平台程式庫,供驅動程式庫開發人員使用 (請在先前連結的行中尋找 (unstable) 標記)。

    舉例來說,@fuchsia_sdk//pkg:driver_power_cpp 會公開 GN //sdk/lib/driver/power/cpp 程式庫定義中的程式庫。

    @internal_sdk 包含類似的定義,但僅適用於樹狀結構內 Fuchsia 建構版本中提供的 SDK 原子,因此可能更加不穩定。不過,我們計畫移除這個函式,改為將所有不穩定的原子移至 @fuchsia_sdk,因此不應在此處新增任何原子。

  • 請勿為內部平台程式庫編寫 BUILD.bazel 檔案。

    目前應避免為相同的非 SDK 程式庫重複定義 BUILD.gn / BUILD.bazel。

    如果驅動程式需要使用尚未公開為不穩定 IDK 原子項目的平台內部程式庫,請與 fuchsia-build-discuss@google.com 聯絡,說明您的用途。

    理想情況下,新增不穩定的 IDK 原子就足夠,但可能會有例外情況,詳情請參閱下方的專屬章節。

  • 所有 Bazel 目標仍須由 GN 目標包裝,才能供建構後用戶端使用。

    具體來說,一或多個 Bazel 測試套件必須由 GN bazel_test_package_group() 目標定義包裝,確保 fx test 和 botanist (我們的基礎架構 CI 測試執行元件工具) 能夠瞭解、視需要建構及執行這些套件。

  • 從 GN/Ninja 動作叫用 Bazel 非常緩慢:即使 Bazel 決定不執行任何動作,也需要幾秒鐘。Ninja 會將這些動作分批處理,並以群組形式執行所有待處理、可執行的 Bazel 動作。

    這些動作是由 GN 範本 (例如 bazel_action) 或其中一個包裝函式定義。

  • 避免依附於 Bazel 構件的非終端 GN 目標

    由於跨越 GN/Bazel 邊界需要高昂的成本,類似 GN -> Bazel -> GN -> Bazel -> GN 的依附元件鏈會導致增量建構速度大幅變慢,因此必須避免。

    詳情請參閱下方的專屬章節。

雙重 BUILD.bazel 和 BUILD.gn 定義

在遷移作業的其餘階段,許多目標都必須在對等的 BUILD.gn 和 BUILD.bazel 檔案中定義。

如果存在這類雙重建構檔案,請務必持續保持同步。此外,追蹤兩個圖表中同時存在的雙重定義目標也很重要。

最簡單的初步做法是手動編寫,並在兩個檔案中使用相符的 LINT If-This-Then-That 區塊,在 CL 審查期間偵測偏差。

更好的做法是使用工具 (例如最近推出的 bazel2gn),將 BUILD.bazel 自動轉換為對應的 BUILD.gn。

目前 bazel2gn 僅為原型,只會處理 Go 目標。這項功能日後會持續改良,以支援更多用途,但目前僅限 Fuchsia 建構團隊使用,Fuchsia 開發人員暫時不應使用。

在這兩種情況下,系統都會導入註解標記和相關工具,追蹤兩個圖表中雙重定義的目標。

GN 和 Bazel 圖表之間的依附元件

由於跨越 GN/Bazel 邊界的成本很高,類似 GN -> Bazel -> GN -> Bazel -> GN 的依附元件鏈會導致增量建構速度大幅變慢。此外,查看實際依附元件時缺乏清晰度,也會讓開發人員感到沮喪,建構失敗的原因也可能變得更難理解和修正。

目前,由於整個建構作業是由 GN 控制,且建構後用戶端只會查看 GN 專屬目標定義,因此任何 Bazel 構件都必須透過 GN 專屬目標包裝,導致鏈結看起來像 GN -> Bazel -> GN。

建構團隊正積極努力,讓 Bazel 目標在原生環境中顯示,避免最後一個 Bazel -> GN 邊緣。

這需要修改建後工具和指令碼 (例如 fx test 和許多其他工具),才能直接查看 Bazel 輸出內容,並在不叫用 Ninja 的情況下,視需要重建這些內容。

將平台程式庫公開為 SDK 原子

如要讓目標在 @fuchsia_sdk 中顯示,必須符合下列條件:

  • 類型必須符合其中一個支援的 IDK 原子結構定義,也就是:

    • 沒有 Rust 來源程式庫。
    • 沒有 Go 來源程式庫。
  • 必須在 GN 圖表中定義 (目前不支援在 Bazel 中定義 SDK/IDK 原子)。

  • 由於 GN / Bazel 邊界設有限制,因此無法testonly = true。

  • 不得有條件式依附元件。我們的 IDK 結構定義不支援這些項目,而且有充分的理由。

  • 來源程式庫無法依附非 SDK 程式庫。所有遞移依附元件也必須是 SDK 的一部分。

  • 必須使用與 SDK 相容的 GN 範本定義,例如:

    • sdk_source_set():適用於 C++ 來源程式庫。
    • sdk_static_library():適用於預先建構的靜態 C++ 程式庫。
    • sdk_shared_library():適用於預先建構的共用 C++ 程式庫。
    • fidl()sdk_category:適用於 FIDL 定義檔。
    • zx_library(),且 sdk_publishable 設為 SDK 類別:對於也需要連結至核心、系統啟動載入程式或 userboot 程式的 C++ 來源、靜態和共用程式庫,
    • sdk_fuchsia_package():適用於預先建構的 Fuchsia 套件。

如果平台程式庫無法遵守這些限制,請透過 fuchsia-build-discuss@google.com 郵寄清單討論替代方案。替代方案可能包括雙圖目標定義,這些定義需要在其餘遷移作業中追蹤。

文件記錄

2025 年 3 月 6 日:修正將 Bazel 套件匯出至 GN 的範例。2025 年 2 月 21 日:初始版本