BUILD
檔案格式設定與 Go 相同,標準化工具會處理大部分的格式設定問題。Buildifier 是一種工具,可剖析原始碼並以標準樣式發出。因此,每個 BUILD
檔案都會以相同的方式自動格式化,在程式碼審查期間不會發生格式問題。此外,工具也能更輕鬆地瞭解、編輯及產生 BUILD
檔案。
BUILD
檔案格式必須與 buildifier
的輸出內容相符。
格式範例
# Test code implementing the Foo controller.
package(default_testonly = True)
py_test(
name = "foo_test",
srcs = glob(["*.py"]),
data = [
"//data/production/foo:startfoo",
"//foo",
"//third_party/java/jdk:jdk-k8",
],
flaky = True,
deps = [
":check_bar_lib",
":foo_data_check",
":pick_foo_port",
"//pyglib",
"//testing/pybase",
],
)
檔案結構
建議:使用下列順序 (每個元素都是選用):
套件說明 (註解)
所有
load()
對帳單package()
函式。規則和巨集的呼叫
Buildifier 會區分獨立註解和附加至元素的註解。如果註解未附加至特定元素,請在註解後使用空白行。進行自動化變更時 (例如刪除規則時保留或移除留言),這項區別非常重要。
# Standalone comment (such as to make a section in a file)
# Comment for the cc_library below
cc_library(name = "cc")
目前套件中目標的參照
檔案應以相對於套件目錄的路徑參照 (切勿使用向上參照,例如 ..
)。產生的檔案應加上「:
」前置字串,表示這些檔案並非來源。來源檔案不得以 :
為前置字串。規則應以 :
為前置字串。舉例來說,假設 x.cc
是來源檔案:
cc_library(
name = "lib",
srcs = ["x.cc"],
hdrs = [":gen_header"],
)
genrule(
name = "gen_header",
srcs = [],
outs = ["x.h"],
cmd = "echo 'int x();' > $@",
)
目標命名
目標名稱應具描述性,如果目標包含一個來源檔案,目標名稱通常應衍生自該來源 (例如,chat.cc
的 cc_library
可命名為 chat
,或 DirectMessage.java
的 java_library
可命名為 direct_message
)。
套件的同名目標 (與所含目錄同名的目標) 應提供目錄名稱所述的功能。如果沒有這類目標,請勿建立同名目標。
參照同名目標時,請盡量使用簡短名稱 (//x
,而非 //x:x
)。如果您位於相同套件中,請盡量使用本機參照 (:x
,而非 //x
)。
請避免使用具有特殊意義的「保留」目標名稱。包括 all
、__pkg__
和 __subpackages__
,這些名稱具有特殊語意,使用時可能會造成混淆和非預期行為。
如果沒有通用的團隊慣例,以下是 Google 廣泛使用的部分非約束性建議:
- 一般來說,請使用「snake_case」
- 如果特定目標有多個變體,請新增後置字元來消除歧義 (例如
:foo_dev
、:foo_prod
或:bar_x86
,:bar_x64
) - 以
_test
、_unittest
、Test
或Tests
為目標的後置字串_test
- 避免使用無意義的後置字元,例如
_lib
或_library
(除非為避免_library
目標與對應的_binary
發生衝突,否則請勿使用) - 適用於 proto 相關目標:
proto_library
目標的名稱結尾應為_proto
- 特定語言的
*_proto_library
規則應與基礎原型相符,但要將_proto
替換為特定語言的後置字串,例如:cc_proto_library
:_cc_proto
java_proto_library
:_java_proto
java_lite_proto_library
:_java_proto_lite
顯示設定
可見度應盡可能縮小範圍,同時仍允許測試和反向依附元件存取。視情況使用 __pkg__
和 __subpackages__
。
避免將套件 default_visibility
設為 //visibility:public
。
//visibility:public
只能針對專案公開 API 中的目標個別設定。這些可能是專為外部專案依附而設計的程式庫,或是可供外部專案建構程序使用的二進位檔。
依附元件
依附元件應僅限於直接依附元件 (規則中列出的來源所需依附元件)。請勿列出遞移依附元件。
套件本機的依附元件應列在最前面,並以與上方「參照目前套件中的目標」一節相容的方式參照 (而非使用絕對套件名稱)。
建議直接列出依附元件,做為單一清單。將多個目標的「通用」依附元件放入變數中,會降低可維護性,導致工具無法變更目標的依附元件,並可能導致未使用的依附元件。
Globs
使用 []
表示「沒有目標」。請勿使用不相符的 glob,因為這比空白清單更容易出錯,也較不明顯。
遞迴
請勿使用遞迴 glob 來比對來源檔案 (例如 glob(["**/*.java"])
)。
遞迴 glob 會略過含有 BUILD
檔案的子目錄,因此難以推斷 BUILD
檔案。
一般來說,遞迴 glob 的效率不如每個目錄都有 BUILD
檔案,且檔案之間定義了依附元件圖表,因為這樣可提升遠端快取和並行處理的效率。
建議您在每個目錄中撰寫 BUILD
檔案,並定義目錄之間的依附元件關係圖。
非遞迴
一般來說,非遞迴的 glob 都可以接受。
其他慣例
使用大寫和底線宣告常數 (例如
GLOBAL_CONSTANT
),使用小寫和底線宣告變數 (例如my_variable
)。即使標籤長度超過 79 個字元,也不應分割。 標籤應盡可能為字串常值。理由:方便尋找及取代。同時提升可讀性。
名稱屬性的值應為常數字串 (巨集除外)。理由:外部工具會使用名稱屬性參照規則。他們需要找出規則,而不必解讀程式碼。
設定布林值類型的屬性時,請使用布林值,而非整數值。 基於舊版原因,規則仍會視需要將整數轉換為布林值,但我們不建議這麼做。理由:
flaky = 1
可能會誤解為「重新執行一次,即可解決這個目標的問題」。flaky = True
明確指出「這項測試不穩定」。
與 Python 樣式指南的差異
雖然目標是與 Python 樣式指南相容,但仍有幾項差異:
沒有嚴格的行長度限制。長註解和長字串通常會分割成 79 欄,但這並非必要。不應在程式碼審查或預先提交指令碼中強制執行。原因:標籤可能會很長,超過這個限制。工具通常會產生或編輯
BUILD
檔案,這與行長度限制不相容。系統不支援隱含字串串連。使用
+
運算子。 理由:BUILD
檔案包含許多字串清單。很容易忘記逗號,導致結果完全不同。這在過去造成許多錯誤。另請參閱這項討論。在規則中,關鍵字引數的
=
符號前後要加上空格。理由:具名引數比 Python 更常使用,且一律位於獨立一行。空格可提升可讀性。這項慣例已存在很長一段時間,不值得修改所有現有的BUILD
檔案。根據預設,字串會使用雙引號。理由:Python 樣式指南未指定此項目,但建議保持一致。因此我們決定只使用雙引號字串。許多語言會使用雙引號標註字串常值。
在兩個頂層定義之間使用單一空白行。理由:
BUILD
檔案的結構與一般 Python 檔案不同。當中只包含頂層陳述式。使用單一空白行可縮短BUILD
檔案。