.bzl 樣式指南

回報問題 查看來源 Nightly · 8.4 · 8.3 · 8.2 · 8.1 · 8.0 · 7.6

本頁面涵蓋 Starlark 的基本樣式規範,並提供巨集和規則的相關資訊。

Starlark 是一種語言,可定義軟體的建構方式,因此既是程式設計語言,也是設定語言。

您將使用 Starlark 編寫 BUILD 檔案、巨集和建構規則。巨集和規則基本上是元語言,可定義 BUILD 檔案的寫入方式。BUILD 檔案的設計簡單且重複。

所有軟體讀取的頻率都比寫入高。對於 Starlark 來說更是如此,因為工程師會讀取 BUILD 檔案,瞭解目標的依附元件和建構詳細資料。使用者通常會匆匆一瞥,或是在忙著完成其他工作時順便閱讀。因此,簡單易讀非常重要,使用者才能快速剖析及瞭解 BUILD 檔案。

使用者開啟 BUILD 檔案時,會想快速瞭解檔案中的目標清單;或查看該 C++ 程式庫的來源清單;或從該 Java 二進位檔中移除依附元件。每新增一層抽象化,使用者就越難完成這些工作。

許多不同的工具也會分析及更新 BUILD 檔案。如果 BUILD 檔案使用抽象化,工具可能無法編輯。簡化檔案可讓你取得更優質的工具。BUILD隨著程式碼基底擴大,為了更新程式庫或進行清理,您會越來越常變更許多 BUILD 檔案。

通用建議

樣式

Python 樣式

如有疑問,請盡可能遵循 PEP 8 樣式指南。具體來說,請使用四個空格而非兩個空格來縮排,以遵循 Python 慣例。

由於 Starlark 不是 Python,因此 Python 樣式的某些方面不適用。舉例來說,PEP 8 建議使用 is 比較單例,但 Starlark 中沒有這個運算子。

Docstring

使用文件字串記錄檔案和函式。 在每個 .bzl 檔案頂端使用說明字串,並為每個公開函式提供說明字串。

文件規則和層面

規則和層面及其屬性,以及供應商和其欄位,都應使用 doc 引數記錄。

命名慣例

  • 變數和函式名稱使用小寫,並以底線 ([a-z][a-z0-9_]*) 分隔字詞,例如 cc_library
  • 頂層私有值會以一個底線開頭。Bazel 會強制執行規定,禁止從其他檔案使用私有值。區域變數不應使用底線前置字元。

文行長度

BUILD 檔案相同,標籤可以很長,因此沒有嚴格的行長度限制。 請盡可能讓每行最多 79 個字元 (遵循 Python 的樣式指南 PEP 8)。這項規範不應嚴格執行:編輯器應顯示超過 80 欄,自動變更經常會產生較長的行,而人類不應花時間分割已可讀取的行。

關鍵字引數

在關鍵字引數中,等號周圍最好加上空格:

def fct(name, srcs):
    filtered_srcs = my_filter(source = srcs)
    native.cc_library(
        name = name,
        srcs = filtered_srcs,
        testonly = True,
    )

布林值

布林值 (例如在規則中使用布林值屬性時) 建議使用 TrueFalse 值,而非 10

請勿在正式版程式碼中使用 print() 函式,因為這項函式僅供偵錯,而且會傳送大量訊息給 .bzl 檔案的所有直接和間接使用者。唯一例外是,如果使用 print() 的程式碼預設為停用,且只能透過編輯來源啟用 (例如,如果 print() 的所有用途都受到 if DEBUG: 保護,而 DEBUG 硬式編碼為 False),您就可以提交這類程式碼。請注意,這些陳述內容是否夠實用,足以抵銷對可讀性的影響。

巨集

巨集是一種函式,會在載入階段例項化一或多項規則。一般來說,請盡可能使用規則,而非巨集。使用者看到的建構圖與 Bazel 在建構期間使用的建構圖不同,因為巨集會在 Bazel 進行任何建構圖分析之前展開

因此,如果發生錯誤,使用者必須瞭解巨集實作方式,才能排解建構問題。此外,由於結果中顯示的目標來自巨集擴展,因此 bazel query 結果可能難以解讀。最後,構面不會感知巨集,因此依構面而定的工具 (IDE 等) 可能會失敗。

巨集的安全用途是定義額外的目標,以便直接在 Bazel CLI 或 BUILD 檔案中參照:在這種情況下,只有這些目標的使用者需要瞭解這些目標,而巨集造成的任何建構問題都不會離使用位置太遠。

如要定義產生的目標 (巨集實作詳細資料,不應在 CLI 中參照,也不應由該巨集未例項化的目標依附),請遵循下列最佳做法:

  • 巨集應採用 name 引數,並定義具有該名稱的目標。該目標會成為巨集的主要目標
  • 產生的目標 (即巨集定義的所有其他目標) 應符合下列條件:
    • 名稱前置字串為 <name>_<name>。例如使用 name = '%s_bar' % (name)
    • 曝光度受限 (//visibility:private),且
    • 使用 manual 標記,避免在萬用字元目標 (:all...:* 等) 中擴展。
  • name 只能用於衍生巨集定義的目標名稱,不得用於其他用途。舉例來說,請勿使用名稱衍生並非由巨集本身產生的依附元件或輸入檔案。
  • 巨集中建立的所有目標都應以某種方式與主要目標配對。
  • 按照慣例,定義巨集時,name 應為第一個引數。
  • 巨集中的參數名稱必須一致。如果參數做為屬性值傳遞至主要目標,請保持名稱不變。如果巨集參數與一般規則屬性 (例如 deps) 的用途相同,請為巨集參數命名,就像為屬性命名一樣 (請參閱下文)。
  • 呼叫巨集時,請只使用關鍵字引數。這與規則一致,且大幅提升可讀性。

如果相關規則的 Starlark API 不足以滿足特定用途,工程師通常會編寫巨集,無論規則是在 Bazel 中以原生程式碼定義,還是以 Starlark 定義,都是如此。如果遇到這個問題,請詢問規則作者是否可以擴充 API,以達成您的目標。

一般來說,巨集越符合規則,效果就越好。

另請參閱巨集

規則

  • 規則、層面及其屬性應使用小寫名稱 (「蛇形命名法」)。
  • 規則名稱是名詞,從依附元件的角度 (或從使用者角度,如果是葉節點規則),描述規則產生的主要構件類型。這不一定是檔案後置字元。舉例來說,如果規則會產生 C++ 構件,並做為 Python 擴充功能使用,則可稱為 py_extension。大多數語言的常見規則包括:
    • *_library - 編譯單元或「模組」。
    • *_binary - 目標會產生可執行檔或部署單元。
    • *_test - 測試目標。這可能包括多項測試。*_test 目標中的所有測試都應是同一主題的變化版本,例如測試單一程式庫。
    • *_import:封裝預先編譯構件的目標,例如 .jar 或編譯期間使用的 .dll
  • 屬性的名稱和類型應保持一致。一般適用的屬性包括:
    • srcslabel_list,允許的檔案:來源檔案,通常是人為撰寫。
    • depslabel_list,通常允許的檔案:編譯依附元件。
    • datalabel_list,允許的檔案:資料檔案,例如測試資料等。
    • runtime_depslabel_list:編譯不需要的執行階段依附元件。
  • 對於任何行為不明顯的屬性 (例如具有特殊替代項的字串範本,或以特定需求條件叫用的工具),請使用屬性宣告 (attr.label_list() 或類似項目) 的 doc 關鍵字引數提供文件。
  • 規則實作函式幾乎一律應為私有函式 (以底線開頭命名)。常見的做法是將 myrule 的實作函式命名為 _myrule_impl
  • 使用定義完善的提供者介面,在規則之間傳遞資訊。宣告及記錄供應商欄位。
  • 設計規則時,請考量擴充性。請考慮其他規則可能想與您的規則互動、存取您的供應商,以及重複使用您建立的動作。
  • 在規則中遵循效能指南