Bazel 遷移指南

上次更新時間:2025-02-21

本頁面提供重要的 Bazel 相關指南,供樹狀結構內工作的 Fuchsia 開發人員 (即使用 fuchsia.git 檢出的開發人員) 參考。由於 Bazel 遷移作業是不斷變動的目標,我們會經常更新這個頁面,反映重要的變更。

摘要

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

  • 如果您不執行產品組合作業,也不撰寫驅動程式庫套件,請不要在 Fuchsia 樹狀結構中編寫 Bazel 檔案,或開始編寫這些檔案

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

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

  • 所有新的電路板開發作業都應在 Bazel 中進行。如果您的電路板恰好依附現有的 GN 驅動程式庫套件,請使用 bazel_driver_package() 範本將其公開至 Bazel 圖表 (請參閱此處的範例)。

  • 以 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 testbotanist (我們的基礎架構 CI 測試執行元件工具) 可以瞭解這些套件,並視需要建構及執行這些套件。

  • 從 GN/Ninja 動作叫用 Bazel 會非常緩慢即使 Bazel 決定不執行任何動作,也需要幾秒鐘的時間。而且一次只能執行一個。

    這些動作是由 GN 範本定義,例如 bazel_action 或其中一個包裝函式,而這些動作的例項則是使用 //build/bazel:bazel_action_allowlist 目標進行控制。

    範本 (例如 bazel_build_group()bazel_test_package_group()) 只會呼叫 Bazel 一次,以便同時建構多個 Bazel 目標。這可提供更優異的平行處理功能。

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

    由於跨越 GN/Bazel 邊界會造成高成本,因此類似 GN -> Bazel -> GN -> Bazel -> GN 的依附元件鏈結會導致增量建構作業速度大幅降低,因此必須避免。

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

雙重 BUILD.bazelBUILD.gn 定義

在遷移作業的其餘部分中,許多目標都會在等同的 BUILD.gnBUILD.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 -> Bazel -> GN,因為整個建構作業都由 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 範本定義這些值,例如:

如果您的平台程式庫無法遵守這些限制,請與 fuchsia-build-discuss@google.com 聯絡,討論其他做法。替代方案可能包括雙圖表目標定義,需要在遷移作業的其餘部分中追蹤。

文件記錄

2025-02-21:初始版本