建構樣式指南

回報問題 查看來源

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.cccc_library 可以命名為 chat,或者 DirectMessage.javajava_library 可以命名為 direct_message)。

套件的匿名目標 (名稱與包含目錄相同的目標) 應提供目錄名稱所述的功能。如果沒有這類目標,請勿建立匿名目標。

在參照匿名目標時優先使用簡稱 (//x 而非 //x:x)。如果您在同一個套件中,請使用本機參照 (:x 而非 //x)。

避免使用具有特殊意義的「保留」目標名稱。包括 all__pkg____subpackages__。這些名稱具有特殊語意,可能會在使用時造成混淆和非預期的行為。

假如沒有主要的團隊慣例,以下是一些 Google 廣泛採用的非具約束力建議:

  • 一般來說,請使用 "snake_case"
    • 如果是具有 srcjava_library,則表示使用的名稱與不含副檔名的檔案名稱不同
    • 如果是 Java *_binary*_test 規則,請使用 "Upper CamelCase"。這樣一來,目標名稱就能與其中一個 src 比對。若是 java_test,這樣系統就能從目標名稱推論 test_class 屬性。
  • 如果特定目標有多個變化版本,請加入可區別的後置字串 (例如::foo_dev:foo_prod:bar_x86:bar_x64)
  • 使用 _test_unittestTestTests 後後置字串 _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。您只能為專案公用 API 的目標個別設定 //visibility:public。這些程式庫可能是設計以由外部專案或二進位檔為基礎,且可供外部專案的建構程序使用的二進位檔。

依附元件

依附元件應限制為直接依附元件 (規則中列出的來源需要的依附元件)。請勿列出遞移依附元件。

應先列出套件本機依附元件,並以與上述「目前套件中的目標參照」一節 (而非其絕對套件名稱) 相容的方式參照。

想要直接列出依附元件,為單一清單。將多個目標的「常見」依附元件放入變數中可降低維護性,將使工具無法變更目標的依附元件,進而導致未使用的依附元件。

眼鏡

使用 [] 表示「無目標」。請勿使用沒有任何符合項目的 glob,因為 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 檔案。