.bzl 樣式指南

本頁說明 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 中的運算子) 與單例模式比較。

文件串

使用 docstrings 的文件和函式。在每個 .bzl 檔案頂端使用一個文件字串,以及每個公用函式的 docstring。

文件規則與層面

規則和層面及其屬性、提供者及其欄位應以 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 只能用來衍生由巨集定義的目標名稱,不適用於任何其他內容。例如,請勿使用這個名稱,衍生非由巨集本身產生的依附元件或輸入檔案。
  • 所有透過巨集建立的目標,都應以某種方式結合至主要目標。
  • 讓巨集中的參數名稱保持一致。如果參數做為屬性值傳遞給主要目標,請保持名稱不變。如果巨集參數的用途與一般規則屬性 (例如 deps) 相同,您會使用該屬性的名稱 (詳見下文)。
  • 呼叫巨集時,只能使用關鍵字引數。這與規則一致,可大幅提升可讀性。

無論規則是在 Bazel 的原生程式碼中或 Starlark 中定義規則,當相關規則的 Starlark API 不足以因應特定用途時,工程師通常會編寫巨集。如果您遇到這個問題,請詢問規則作者是否能夠擴充 API 來完成您的目標。

原則上,巨集越符合規則,成效越好。

另請參閱巨集

規則

  • 規則、面向及其屬性應使用小寫名稱 (「貪食蛇」)。
  • 規則名稱是名詞,用於說明規則產生的主要成果種類,從依附元件的視角 (或適用於分葉規則;使用者)這不一定是檔案尾碼。舉例來說,假如規則會產生要做為 Python 擴充功能使用的 C++ 構件,則稱為 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 的實作函式。
  • 利用定義明確的 provider 介面,在規則之間傳遞資訊。宣告和文件供應器欄位。
  • 在設計規則時請考量擴充性。請考慮其他規則可能想要與規則互動、存取供應器,並重複使用您建立的動作。
  • 遵循規則中的成效指南