本頁面說明 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
使用 docstrings 記錄檔案和函式。
請在每個 .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,
)
布林值
針對布林值 (例如在規則中使用布林值屬性時),優先使用 True
和 False
值,而非 1
和 0
。
僅將列印功能用於偵錯
請勿在實際工作環境的程式碼中使用 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 來達成您的目標。
原則上,與規則相似的巨集越多越好。
另請參閱巨集。
規則
- 規則、切面及其屬性應使用小寫名稱 (「蛇形」)。
- 規則名稱以名詞,用來說明規則從依附元件的角度 (對於分葉規則,則為使用者) 產生的主要成果類型。不一定是檔案後置字串。舉例來說,如果規則會產生 C++ 構件,藉此做為 Python 擴充功能使用,則可命名為
py_extension
。以大部分語言來說,一般規則包括:*_library
- 編譯單位或「模組」。*_binary
:產生執行檔或部署單元的目標。*_test
:測試目標。這可包含多個測試。預期*_test
目標中的所有測試都是相同主題的變化版本,例如測試單一程式庫。*_import
:這個目標會封裝預先編譯的構件 (例如.jar
),或是編譯期間使用的.dll
。
- 為屬性使用一致的名稱和類型。部分一般適用的屬性包括:
srcs
:label_list
,允許檔案:來源檔案 (通常為人撰寫)。deps
:label_list
,通常「不允許」檔案:編譯依附元件。data
:label_list
,允許檔案:資料檔案,例如測試資料等。runtime_deps
:label_list
:編譯不需要的執行階段依附元件。
- 針對具有非明顯行為的屬性 (例如具有特殊替代行為的字串範本,或是依特定要求叫用的工具),請在屬性的宣告 (
attr.label_list()
或類似) 中使用doc
關鍵字引數來提供說明文件。 - 規則實作函式在絕大部分都是私人函式 (以底線命名)。常見的樣式是將
myrule
的實作函式命名為_myrule_impl
。 - 使用明確定義的 provider 介面,在規則之間傳遞資訊。宣告和文件提供者欄位。
- 設計規則時,請務必將擴充性納入考量。請考慮其他規則可能會想與您的規則互動、存取提供者,並重複使用您建立的動作。
- 請遵循規則中的效能指南。