Build スタイルガイド

問題を報告 ソースを表示

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();' > $@",
)

ターゲットの命名

ターゲット名はわかりやすいものにする必要があります。ターゲットに 1 つのソースファイルが含まれている場合、通常、ターゲットにはそのソースから派生した名前が付けられます(たとえば、chat.cccc_library には chat という名前、DirectMessage.javajava_library には direct_message という名前を付けることができます)。

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

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

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

以下は、代表的なチーム規則が定められていない場合に、Google で広く使用されている、拘束力のない推奨事項です。

  • 通常は "snake_case" を使用します。
    • java_librarysrc が 1 つある場合は、ファイル名と拡張子のない名前を使用します。
    • Java の *_binary ルールと *_test ルールの場合は、「Upper CamelCase」を使用します。これにより、ターゲット名を src の 1 つに一致させることができます。java_test の場合、これにより、test_class 属性をターゲットの名前から推測できます。
  • 特定のターゲットに複数のバリアントがある場合は、曖昧さを取り除くために接尾辞を追加します(例::foo_dev:foo_prod、または :bar_x86:bar_x64
  • _test ターゲットの末尾に _test_unittestTest、または Tests を追加する
  • _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 は使用しないでください。空のリストよりもエラーが発生しやすく、わかりにくいものです。

Recursive

ソースファイルの照合に再帰 glob を使用しないでください(例: glob(["**/*.java"]))。

再帰 glob を使用すると、BUILD ファイルを含むサブディレクトリがスキップされるため、BUILD ファイルは判断が難しくなります。

一般に、再帰 glob は、依存関係グラフをディレクトリ間で定義してディレクトリごとに BUILD ファイルを使用する場合よりも効率が低くなります。これにより、リモート キャッシュと並列処理が改善されます。

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

非再帰

非再帰 glob は一般的に許容されます。

その他の規則

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

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

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

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

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

Python スタイルガイドとの互換性が目標ですが、いくつか違いがあります。

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

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

  • ルール内のキーワード引数では、= 記号の前後にスペースを使用します。理論的根拠: 名前付き引数は Python よりも頻繁に使用され、常に別の行に配置されます。スペースを使用すると読みやすくなります。この規則は以前から存在しているため、既存の BUILD ファイルをすべて変更する必要はありません。

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

  • 2 つのトップレベルの定義の間には 1 行の空白行を使用します。理由: BUILD ファイルの構造は、一般的な Python ファイルとは異なります。トップレベルのステートメントのみがあります。1 行を空白にすると、BUILD ファイルが短くなります。