BUILD
檔案格式與 Go 採用的方法相同,其中標準化工具可以解決大多數格式問題。建構工具這項工具會剖析和發出標準樣式的原始碼。因此,每個 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()
函式。規則和巨集的呼叫
建構工具可區分獨立註解與附加至元素的留言。如果註解並未附加至特定元素,請在註解後方加上空白行。執行自動變更時,該差異很重要 (例如,在刪除規則時保留或移除註解)。
# 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
規則,請使用 "Upper CamelCase"。這可讓目標名稱符合其中一個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 中的目標個別設定。這些程式庫可以設計為依附於外部專案,或是可供外部專案的建構程序使用的二進位檔。
依附關係
依附元件應該限制在直接依附元件 (規則所列來源所需的依附元件)。請勿列出遞移依附元件。
套件本機依附元件應先列出,並以與上述目前套件目標的參照部分 (而非其絕對套件名稱) 相容的方式參照。
建議將依附元件直接列出為一個清單。將多個目標的「常見」依附元件放入變數中可減少維護性,導致工具無法變更目標的依附元件,進而導致未使用的依附元件。
玻璃
使用 []
表示「無目標」。請勿使用與無條件相符的 glob:它比空白清單容易出錯,且較不明顯。
遞迴
請勿使用遞迴 glob 來比對來源檔案 (例如 glob(["**/*.java"])
)。
遞迴 glob 會讓 BUILD
檔案難以理解,因為它們會略過包含 BUILD
檔案的子目錄。
遞迴 glob 的效率通常低於在每個目錄中使用 BUILD
檔案,以及在其之間定義依附元件圖表,因此能更有效地進行遠端快取和平行處理。
建議您在每個目錄中編寫 BUILD
檔案,並定義其之間的相依關係圖。
非遞迴
我們允許非遞迴的冰川。
其他慣例
請使用大寫和底線來宣告常數 (例如
GLOBAL_CONSTANT
),並使用小寫字母及底線宣告變數 (例如my_variable
)。標籤一律不得分割,即使長度超過 79 個字元也無妨。 標籤應盡可能是字串常值。Rationale:讓您輕鬆尋找與取代。這麼做也提升了可讀性。
name 屬性的值應為常值常數字串 (巨集除外)。Rationale:外部工具會使用名稱屬性來參照規則。因此,他們不必尋找程式碼就能找出規則。
設定布林類型屬性時,請使用布林值,而非整數值。基於舊版原因,規則仍會視需要將整數轉換為布林值,但不建議使用。Rationale:
flaky = 1
可能被誤認為是「用它重新執行一次來破壞這個目標」。flaky = True
無疑地表示「這項測試不穩定」。
與 Python 樣式指南的差異
雖然與 Python 樣式指南的相容性是目標,但還是有一些差異:
沒有行數限制。長註解和長字串通常可分割為 79 欄,但並非必要。請不要在程式碼審查或預先提交指令碼中強制執行。理由:標籤的長度可能超過這個上限。工具常會產生或編輯
BUILD
檔案是很常見的情形,無法達到行距限制。不支援隱式字串串連。使用
+
運算子。Rationale:BUILD
檔案包含許多字串清單。很容易忘記逗號,這會產生不同的不同的結果。這會造成許多錯誤。另請參閱這個討論。在規則中使用關鍵字引數
=
的空格。Rationale:已命名的引數比 Python 更加頻繁,而且一律會單獨輸入。聊天室可提高可讀性。這項慣例已經存在了很長一段時間,因此不建議您修改所有現有的BUILD
檔案。根據預設,字串使用雙引號。Rationale:在 Python 樣式指南中並未指定,但建議採用一致性。因此,我們決定只使用雙引號字串。許多語言都使用字串常值雙引號。
請在兩個頂層定義之間使用一個空白行。Rationale:
BUILD
檔案的結構與一般 Python 檔案不同。它只有頂層陳述式。使用單行行可以減少BUILD
個檔案。