建構樣式指南

回報問題 查看原始碼

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//visibility:public 只應針對專案公開 API 中的目標個別設定。這些程式庫可以設計為依附於外部專案,或是可供外部專案的建構程序使用的二進位檔。

依附關係

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

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

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

玻璃

使用 [] 表示「無目標」。請勿使用與無條件相符的 glob:它比空白清單容易出錯,且較不明顯。

遞迴

請勿使用遞迴 glob 來比對來源檔案 (例如 glob(["**/*.java"]))。

遞迴 glob 會讓 BUILD 檔案難以理解,因為它們會略過包含 BUILD 檔案的子目錄。

遞迴 glob 的效率通常低於在每個目錄中使用 BUILD 檔案,以及在其之間定義依附元件圖表,因此能更有效地進行遠端快取和平行處理。

建議您在每個目錄中編寫 BUILD 檔案,並定義其之間的相依關係圖。

非遞迴

我們允許非遞迴的冰川。

其他慣例

  • 請使用大寫和底線來宣告常數 (例如 GLOBAL_CONSTANT),並使用小寫字母及底線宣告變數 (例如 my_variable)。

  • 標籤一律不得分割,即使長度超過 79 個字元也無妨。 標籤應盡可能是字串常值。Rationale:讓您輕鬆尋找與取代。這麼做也提升了可讀性。

  • name 屬性的值應為常值常數字串 (巨集除外)。Rationale:外部工具會使用名稱屬性來參照規則。因此,他們不必尋找程式碼就能找出規則。

  • 設定布林類型屬性時,請使用布林值,而非整數值。基於舊版原因,規則仍會視需要將整數轉換為布林值,但不建議使用。Rationaleflaky = 1 可能被誤認為是「用它重新執行一次來破壞這個目標」。flaky = True 無疑地表示「這項測試不穩定」。

與 Python 樣式指南的差異

雖然與 Python 樣式指南的相容性是目標,但還是有一些差異:

  • 沒有行數限制。長註解和長字串通常可分割為 79 欄,但並非必要。請不要在程式碼審查或預先提交指令碼中強制執行。理由:標籤的長度可能超過這個上限。工具常會產生或編輯 BUILD 檔案是很常見的情形,無法達到行距限制。

  • 不支援隱式字串串連。使用 + 運算子。RationaleBUILD 檔案包含許多字串清單。很容易忘記逗號,這會產生不同的不同的結果。這會造成許多錯誤。另請參閱這個討論。

  • 在規則中使用關鍵字引數 = 的空格。Rationale:已命名的引數比 Python 更加頻繁,而且一律會單獨輸入。聊天室可提高可讀性。這項慣例已經存在了很長一段時間,因此不建議您修改所有現有的 BUILD 檔案。

  • 根據預設,字串使用雙引號。Rationale:在 Python 樣式指南中並未指定,但建議採用一致性。因此,我們決定只使用雙引號字串。許多語言都使用字串常值雙引號。

  • 請在兩個頂層定義之間使用一個空白行。RationaleBUILD 檔案的結構與一般 Python 檔案不同。它只有頂層陳述式。使用單行行可以減少 BUILD 個檔案。