定義 Bazel 規則、巨集和函式

總覽

本頁面提供撰寫規則、巨集和函式的 Fuchsia 專屬樣式和最佳做法。這些一律在 .bzl 檔案中定義,相關指南也適用於此。此外,BUILD.bazel 檔案中與目標相關的指引,也適用於規則和巨集定義的目標。

本頁面是 Bazel 樣式指南和最佳做法的一部分。

判斷是否適合使用新的巨集和函式

如同 Bazel 樣式指南,Fuchsia 偏好 DAMP (描述性和有意義的詞組) BUILD 檔案,而非 DRY (不要重複)。

具體來說,Fuchsia 建構作業在 Bazel 中使用特定區域的巨集和函式,遠比在 GN 中使用這類範本的頻率低。

如果必須同步處理某些項目 (例如常見依附元件),請使用共用的靜態清單,不要編寫區域專屬巨集。

雖然區域專屬範本可在初始建立目標時減少輸入內容,但會造成維護和遷移問題,尤其是自動化工具,因為個別目標會由區域專屬巨集隱藏。如果您認為使用特定區域的巨集和函式會帶來極大好處,請諮詢建構團隊 (根據過往經驗,門檻很高)。

盡可能使用現有的巨集和規則

這類巨集或規則的潛在用途越廣,這項工作就越重要。

特別是如果您的需求僅限於下列情況,請考慮是否可以使用現有的巨集和/或規則來完成:

  • 生成中繼資料

  • 強制執行屬性值

  • 例如,盡量減少呼叫端必須指定的屬性數量

特別是在前兩種情況下,請考量 Bazel 查詢、SHAC 規則、測試或其他機制是否能滿足您的需求。Bazel 查詢可在依附元件樹狀結構或目錄樹狀結構中定義的所有目標上執行。您可以編寫測試,執行查詢並檢查結果嗎?如果您的用途需要額外屬性,請考慮使用標記。

使用現有規則和巨集的原因包括:

  • 開發人員更容易理解,縮短適應期

    • 熟悉 Bazel 的開發人員可以立即瞭解目標。

    • 團隊中某部分的開發人員可以瞭解程式碼集其他部分的目標。

  • AI 較有可能瞭解及產生使用常見規則和巨集的 Bazel 檔案

  • load() 陳述式數量過多

    • 內建 ID 不需要任何載入陳述式。

    • 其他目標可能已載入其他目標。

  • 減少錯誤

    • 舉例來說,只有在遍歷所有相關目標時,層面才能正常運作。自訂巨集或規則可能會引入不會遵循的路徑。請參閱「使用標準屬性名稱」。

建議使用符號巨集,而非舊版巨集

建議您編寫符號巨集,這類巨集是使用 macro() 定義,而非舊版巨集 (以 def 定義的 Python 類函式,會建立目標)。符號巨集可提供更清楚的屬性及其類型說明文件、對屬性執行類型檢查,並確保在呼叫端評估標籤。此外,也支援屬性繼承 (透過 inherit_attrs)。如需進一步瞭解,請參閱「為什麼不應使用舊版巨集」。

請勿在符號巨集的實作函式中指定引數的預設值,因為預設值是由 attrs 項目定義,且每個屬性都會提供值。

在某些情況下,您必須在符號巨集周圍使用舊版巨集包裝函式,但對大多數開發人員來說,這種情況應該非常罕見。

檢查巨集內定義目標的瀏覽權限和存取權

總覽

為了方便查看,您可以將舊版巨集視為在例項化的位置展開。在 BUILD.bazel 檔案中使用時,舊版巨集定義的目標實際上是在該檔案中定義。因此:

  • 定義目標的預設 visibility 與例項化套件相同,包括套件 default_visibility (如有指定)。

  • 巨集可以使用 (例如新增至 deps) 例項化套件可見的任何目標。

    • 定義舊版巨集的 .bzl 檔案位置無關緊要。

不過,為了提高瀏覽權限,請將符號巨集定義的目標,視為定義在與定義巨集的 .bzl 檔案相同套件 (目錄) 的 BUILD.bazel 檔案中。因此:

  • 定義目標的預設 visibility 是包含 .bzl 檔案的套件 (目錄)。

  • 巨集可以使用 (例如新增至 deps) 包含 .bzl 檔案的套件 (目錄) 可見的任何目標。

    • 舉例來說,這項功能適用於 fidl_library() 新增的 FIDL 繫結支援程式庫。

    • 但對於 HLCPP 支援程式庫允許清單等項目而言,這會造成問題。

    • 詳情請參閱問題 446911800。

指定巨集定義目標的曝光率

公開目標

將傳遞至巨集的 visibility 屬性轉送至巨集定義的主要目標,也就是 name 傳遞的目標。visibility 屬性也可能視情況轉送至巨集 doc 字串中提及的其他已定義公開目標。

私人目標

在符號巨集中,所有其他定義目標的顯示狀態預設為 ["//visibility:private"]。不過,如果是舊版巨集,您必須為舊版巨集定義的所有目標指定瀏覽權限。

為舊版巨集定義的所有目標指定瀏覽權限

針對所有未使用傳遞至巨集的 visibility 屬性的目標,指定 visibility = ["//visibility:private"]。這是必要步驟,可避免這些值預設為套件的 default_visibility (如有指定)。

使用標準屬性名稱

在巨集和規則中使用標準屬性名稱。例如,使用 "deps"、"data",甚至是 "tools",而不是 "images" 或 "scripts"。請參閱一些普遍適用的屬性。

可能原因如下:

  • 為了提高可讀性,以及其他類似於「盡可能使用現有的巨集和規則」中的原因。

  • 切面只有在周遊所有相關目標時才能正常運作,而巨集通常會設定為套用至 "deps" 和其他常見屬性 (視情況而定)。不過,他們可能不瞭解 "rust_deps" 等屬性,如果無法套用至該屬性,可能會排除與該方面相關的目標。

需要具名引數

公開函式和舊版巨集 (一種特殊類別的函式) 通常應宣告僅限關鍵字的引數 (所有引數都在 *, 之後宣告)。如果函式最多只有幾個引數,且引數可從符號名稱中清楚辨識,且引數不會在錯誤的位置誤用 (包括因重構/重新排序),則可例外。布林引數和具有預設值的引數應一律顯示在 * 之後。

雖然這對要由程式碼集其他部分使用的符號最重要,但也適用於所有 .bzl 檔案中的公開符號。

這有助於強制執行 Bazel .bzl 樣式指南的指引,即「呼叫巨集時,請只使用關鍵字引數。這與規則一致,且大幅提升可讀性。

宣告巨集使用的所有引數

如果巨集 (選擇性) 使用引數,請在巨集實作的參數清單中明確宣告該引數,而不是從 kwargs 擷取。舉例來說,請避免以下做法:

# Do NOT do this:
testonly = kwargs.get("testonly", False),

宣告引數可清楚指出哪些引數與巨集實作相關 (例如,與巨集呼叫的巨集相關),並提供單一位置來查看預設值。如果是舊版巨集,這項規則也會確保引數有記錄。(這主要與 Fuchsia Bazel SDK 相關)。

與任何其他引數一樣,但特別是所有建構規則通用的屬性和所有測試規則通用的屬性 (_test),您必須確保將引數傳遞至所有支援該引數的巨集和規則,因為這些引數不會位於 **kwargs 中。

留言

  • 為所有公開函式 (開頭不是底線的函式) 提供函式層級的註解。

  • 為所有規則和巨集提供 doc 字串。

  • 為所有規則和巨集屬性提供 doc 字串。

    • 如果私有屬性 (開頭為底線的屬性) 的意義可從 default 值中明顯看出,則可省略 doc 字串。

文件字串

  • 在 Fuchsia 平台中,doc 字串應在來源檔案中讀取,而非在產生的說明文件中讀取。因此,請優先最佳化這項功能,而非某些產生的文件外觀。

  • 長 doc 字串:

    • 如合理,建議在同一行撰寫頂層單一句子說明,與 doc= 位於同一行。

    • Bazel 沒有嚴格的行長度限制。

    • 如需多行,請使用三引號撰寫多行字串。

    • 避免附加一般字串。

  • 多行 doc 字串

    • 在與 doc 引數 (doc = """Begin the comment...) 相同的行上開始多行字串。

    • 後續各行則從 doc 中 d 的下方開始,類似於 Python 註解從第一個 " 下方開始下一行的方式。

    • 這項設定會盡量確保一致性和可讀性,但生成文字可能不盡理想。

    • 多行字串結尾應使用三引號 ("""),並單獨成行,與 doc 對齊。

規則和巨集實作函式名稱

為 rule() 和 macro() 執行個體的 implementation 函式命名時,請在開頭加上底線,接著輸入規則或函式的名稱,並以 _impl 結尾。

在巨集中參照目標名稱時使用變數

如果巨集定義目標,然後在另一個目標中依附該目標,請使用前一個目標的名稱定義變數,並將該變數用於後一個目標的 name 屬性和 deps。

這可明確連結兩個目標,尤其是在複雜的情況下,有多個層級的目標名稱是以其他目標名稱為基礎,且更容易醒目顯示及搜尋。

除非能提高可讀性 (例如在同一處定義所有目標名稱),否則請勿為非內部使用的目標使用變數。

包裝內建和常見規則、巨集和函式

在 Fuchsia 平台程式碼集 中編寫巨集,以取代常見的 Bazel 規則、巨集或函式時,請在包裝的名稱加上 fx_ 前置字元。例如,應使用 fx_cc_library(),而非 cc_library()。「常見」包括 Bazel 內建的符號 (包括 native.*),以及常見存放區 (例如 rules_cc) 中的符號。此外,如果發生其他衝突 (例如與 package 無關的 fx_package()),也請使用這個前置字元。請勿使用 fuchsia_ 前置字元,因為 fuchsia_... 檔案和符號位於 Fuchsia Bazel SDK。

避免設定轉換

Fuchsia 平台目標應已在正確的設定中建構。如果您認為需要轉場效果,很可能並非如此。請與 Build 團隊聯絡,只有該團隊可以新增轉場效果或平台。

將工具做為可執行的標籤屬性傳遞

執行工具的規則應將工具視為 attr.label(executable = True, cfg = "exec"),並使用 ctx.executable 讀取工具。

反面模式

  • 透過 PATH 查詢工具。Infra 沙箱不會設定這項功能,而 Bazel 無法追蹤未知的工具。請改為將工具當做可執行的標籤屬性傳遞。

  • 傳遞將標籤嵌入規則或巨集的 JSON 或 dict BLOB。Bazel 只會查看標籤類型屬性中的標籤,因此不會建構或追蹤這些依附元件。請改用標籤屬性和供應器。

  • 透過 bazel-bin 符號連結尋找建構輸出內容。它會指向一個設定,而轉換作業可將所需輸出內容放在不同的 bazel-out 目錄中。透過供應商傳遞輸出內容,或明確回報其路徑。

  • 依賴上游規則集的實作詳細資料,例如 rules_cc 使用的 _solib_ 目錄前置字元。規則集更新時,這些值會變更,恕不另行通知。

避免快取或遠端處理大型構件

請參閱「避免大型構件的快取」。