Build スタイルガイド

問題を報告する ソースを表示

BUILD ファイルのフォーマットは、Go と同じアプローチに従います。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();' > $@",
)

ターゲットの命名

ターゲット名はわかりやすい名前にする必要があります。ターゲットにソースファイルが 1 つ含まれている場合、通常はそのソースから派生した名前になります(たとえば、chat.cccc_librarychat に、DirectMessage.javajava_librarydirect_message になります)。

パッケージの同名ターゲット(含まれるディレクトリと同じ名前のターゲット)は、ディレクトリ名で記述されている機能を提供する必要があります。このようなターゲットがない場合は、同名のターゲットを作成しないでください。

同名のターゲットを示す場合は、略称を使用することをおすすめします(//x:x ではなく //x)。同じパッケージの場合は、ローカル参照(//x ではなく :x)を使用します。

特別な意味を持つ「予約済み」のターゲット名は使用しないでください。これには all__pkg____subpackages__ が含まれます。これらには特殊なセマンティクスがあり、これらを使用すると混乱や予期しない動作が発生する可能性があります。

一般的なチームの規則がない場合、Google で広く使用される、拘束力のない推奨事項には以下のものがあります。

  • 通常は、"snake_case" を使用します。
    • src が 1 つの java_library の場合、拡張子のないファイル名とは異なる名前を使用することになります。
    • Java の *_binary ルールと *_test ルールでは、「Upper CamelCase」を使用します。これにより、ターゲット名を src のいずれかと一致させることができます。java_test の場合、これにより、test_class 属性がターゲットの名前から推測されます。
  • 特定のターゲットのバリアントが複数ある場合は、曖昧さ回避のためにサフィックスを追加します(例::foo_dev:foo_prod または :bar_x86:bar_x64
  • 末尾が _test_unittestTest、または 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 のターゲットに対してのみ個別に設定する必要があります。たとえば、外部プロジェクトに依存するように設計されたライブラリや、外部プロジェクトのビルドプロセスで使用できるバイナリなどがあります。

依存関係

依存関係は、直接的な依存関係(ルールにリストされているソースで必要な依存関係)に限定する必要があります。推移的依存関係はリストしないでください。

パッケージ ローカル依存関係は、最初に一覧表示し、上記の現在のパッケージのターゲットへの参照セクションと互換性のある方法で参照する必要があります(絶対パッケージ名ではありません)。

依存関係を 1 つのリストとして直接リストすることをおすすめします。複数のターゲットの「共通の」依存関係を変数に入れると、保守性が低下し、ツールでターゲットの依存関係を変更することができなくなり、未使用の依存関係が発生する可能性があります。

glob

「ターゲットなし」は [] とします。何も一致する glob は使用しないでください。空のリストよりもエラーが発生しやすく、明瞭ではありません。

再帰的

ソースファイル(glob(["**/*.java"]) など)を一致させるために再帰 glob を使用しないでください。

再帰 glob は、BUILD ファイルを含むサブディレクトリをスキップするため、BUILD ファイルを推論するのを難しくします。

再帰 glob は、一般的に、ディレクトリごとに BUILD ファイルが依存関係グラフで定義されると、リモート キャッシュと並列処理が改善されるため、効率性が低下します。

各ディレクトリに BUILD ファイルを作成し、それらの間の依存関係グラフを定義することをおすすめします。

再帰的でない

通常、再帰的グローブは許容されます。

その他の規則

  • 定数(GLOBAL_CONSTANT など)を宣言するには大文字とアンダースコアを使用し、変数(my_variable など)を宣言するには小文字とアンダースコアを使用します。

  • ラベルは 79 文字を超えていても分割しないでください。ラベルは、可能な限り文字列リテラルにする必要があります。理由: 検索と置換が簡単です。読みやすさも向上します。

  • name 属性の値は、リテラル定数文字列(マクロを除く)である必要があります。理論的根拠: 外部ツールは name 属性を使用してルールを参照します。コードを解釈することなく、ルールを見つける必要がある。

  • ブール値型の属性を設定するときは、整数値ではなくブール値を使用します。従来の理由から、引き続きルールは必要に応じて整数をブール値に変換しますが、おすすめしません。理論的根拠: flaky = 1 が「このターゲットを再実行してこのターゲットを一度削除する」と誤って解釈される可能性があります。「このテストは不安定です」と明確に述べています。flaky = True

Python スタイルガイドとの違い

Python スタイルガイドとの互換性は目標ですが、次のような違いがあります。

  • 行の長さに厳しい制限はありません。多くの場合、長いコメントと長い文字列は 79 列に分割されますが、必須ではありません。コードレビューや presubmit スクリプトでは適用しないでください。理論的根拠: ラベルは長くなり、この上限を超えることがあります。BUILD ファイルはツールで生成または編集されることが多く、行の長さが適切な長さではありません。

  • 暗黙の文字列の連結はサポートされていません。+ 演算子を使用します。 理論的根拠: BUILD ファイルには多数の文字列リストが含まれます。カンマは忘れがちで、それによってまったく異なる結果が生じます。これにより、過去に多くのバグが作成されました。こちらのディスカッションもご覧ください。

  • ルール内のキーワード引数には = 記号を囲むスペースを使用します。理論的根拠: 名前付き引数は Python よりも頻繁に出現し、常に別の行になります。スペースを使うと読みやすくなります。この規則はかなり前から存在しており、既存のすべての BUILD ファイルを変更する価値はありません。

  • デフォルトでは、文字列に二重引用符を使用します。理論的根拠: これは Python スタイルガイドで指定されていませんが、整合性をおすすめします。そのため、二重引用符で囲まれた文字列のみを使用することにしました。多くの言語では、文字列リテラルに二重引用符が使用されます。

  • 2 つの最上位の定義の間には空白行を 1 行入力します。理論的根拠: BUILD ファイルの構造は、一般的な Python ファイルとは異なります。最上位のステートメントのみが含まれます。空白行を使用すると、BUILD ファイルが短くなります。