.bzl 樣式指南

7.3 · 7.2 · 7.1 · 7.0 · 6.5

本頁面將介紹 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 比較單例,但 is 並非 Starlark 中的運算子。

Docstring

使用docstring記錄檔案和函式。在每個 .bzl 檔案的頂端使用 docstring,並為每個公開函式使用 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() 的程式碼。舉例來說,如果 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),請使用屬性名稱 (請見下方說明)。
  • 呼叫巨集時,請只使用關鍵字引數。這與規則一致,可大幅改善可讀性。

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

原則上,與規則相似的巨集越多越好。

另請參閱「巨集」。

規則

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