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"
- 對於具有一個
src
的java_library
,這表示使用名稱與不含副檔名的檔案名稱不同 - 針對 Java
*_binary
和*_test
規則,請使用「大寫駝峰式命名法」。這樣一來,目標名稱就能與其中一個src
相符。對於java_test
,這可讓test_class
屬性從目標名稱推斷。
- 對於具有一個
- 如果特定目標有許多變化版本,請加上後置字元以避免混淆 (例如
:foo_dev
、:foo_prod
或:bar_x86
、:bar_x64
) - 使用
_test
、_unittest
、Test
或Tests
來指定_test
目標的後綴 - 避免使用
_lib
或_library
等無意義的後置字串 (除非有必要避免_library
目標與其對應的_binary
發生衝突) - 針對 Proto 相關目標:
proto_library
目標的名稱結尾應為_proto
- 語言專屬的
*_proto_library
規則應與基礎的 proto 相符,但將_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 個字元,也絕對不應分割。標籤應盡可能使用字串常值。Rationale:這樣就能輕鬆找出要取代的內容。也能提升可讀性。
name 屬性的值應為文字常數字串 (宏除外)。Rationale:外部工具會使用 name 屬性參照規則。他們需要在不解讀程式碼的情況下找出規則。
設定布林值類型屬性時,請使用布林值,而非整數值。基於舊版原因,規則仍會視需要將整數轉換為布林值,但不建議這麼做。Rationale:
flaky = 1
可能會被誤解為「透過重新執行一次,將這個目標設為 deflake」。flaky = True
明確指出「這項測試不穩定」。
與 Python 樣式指南的差異
雖然與 Python 樣式指南的相容性是目標,但仍有幾項差異:
沒有嚴格的行數限制。長註解和長字串通常會分成 79 個欄,但這並非必要。不應在程式碼審查或提交前指令碼中強制執行。Rationale:標籤長度可能會超過此限制。
BUILD
檔案通常是由工具產生或編輯,因此不受行程長度限制的約束。不支援隱含字串串接。使用
+
運算子。Rationale:BUILD
檔案包含許多字串清單。很容易忘記逗號,導致結果完全不同。這在過去造成許多錯誤。另請參閱這篇討論串。在規則中使用關鍵字引數時,請在
=
符號前後加上空格。Rationale:命名引數比 Python 中的引數更常見,而且一律位於不同行。空格可提升可讀性。這個慣例已存在很長一段時間,因此不建議修改所有現有的BUILD
檔案。根據預設,請使用雙引號標註字串。Rationale:Python 樣式指南並未指定此項目,但建議您保持一致性。因此,我們決定只使用雙引號字串。許多語言會使用雙引號表示字串常值。
在兩個頂層定義之間使用單一空白行。Rationale:
BUILD
檔案的結構與一般 Python 檔案不同。它只包含頂層陳述式。使用單一空白行可縮短BUILD
檔案的長度。