BUILD ファイル

前のセクションでは、パッケージ、ターゲット、ラベル、ビルド依存関係グラフを抽象的に説明しました。このセクションでは、パッケージを定義するために使用される具体的な構文について説明します。

定義上、すべてのパッケージには短いプログラムである BUILD ファイルが含まれています。BUILD ファイルは命令型言語 Starlark を使用して評価されます。

これらは、ステートメントの連続したリストとして解釈されます。

一般的に、変数は使用する前に定義する必要があります。たとえば、変数は順序が重要です。ただし、ほとんどの BUILD ファイルはビルドルールの宣言のみで構成され、これらのステートメントの相対的な順序は重要ではありません。重要なのは、パッケージ評価が完了するまでに宣言されたルールと、宣言された値だけです。

cc_library などのビルドルール関数を実行すると、グラフ内に新しいターゲットが作成されます。このターゲットは、後でラベルを使用して参照できます。

単純な BUILD ファイルでは、動作を変更せずにルール宣言を自由に並べ替えることができます。

コードとデータをわかりやすく分離するため、BUILD ファイルに関数定義、for ステートメント、if ステートメントを含めることはできません(ただし、リスト内理解と if 式は使用できます)。代わりに、.bzl ファイルで関数を宣言できます。また、BUILD ファイルでは *args 引数と **kwargs 引数を使用できません。代わりに、すべての引数を明示的にリストします。

重要な点として、Starlark のプログラムは任意の I/O を実行できません。この不変条件により、BUILD ファイルは密閉型の解釈となり、既知の入力セットのみに依存します。これはビルドの再現性を確保するために不可欠です。詳しくは、密閉性をご覧ください。

BUILD ファイルは ASCII 文字のみを使用して記述する必要がありますが、厳密には Latin-1 文字セットを使用して解釈されます。

BUILD ファイルは、基盤となるコードの依存関係が変更されるたびに更新する必要があるため、通常はチームの複数のユーザーが管理します。BUILD ファイルの作成者は、各ビルド ターゲットの役割(公開用かどうかにかかわらず)と、パッケージ自体の役割をコメントとして自由に記述する必要があります。

拡張機能の読み込み

Bazel 拡張機能は、末尾が .bzl のファイルです。load ステートメントを使用して、拡張機能からシンボルをインポートします。

load("//foo/bar:file.bzl", "some_library")

このコードは、foo/bar/file.bzl ファイルを読み込み、some_library シンボルを環境に追加します。これは、新しいルール、関数、定数(文字列やリストなど)を読み込むために使用できます。load の呼び出しに追加の引数を使用することで、複数のシンボルをインポートできます。引数は文字列リテラル(変数なし)でなければなりません。また、load ステートメントはトップレベルに配置する必要があります。関数本体に含めることはできません。

load の最初の引数は、.bzl ファイルを識別するラベルです。相対ラベルの場合は、現在の bzl ファイルを含むパッケージ(ディレクトリではない)を基準に解決されます。load ステートメントの相対ラベルには、先頭に : を使用する必要があります。

load はエイリアスもサポートしているため、インポートされたシンボルに異なる名前を割り当てることができます。

load("//foo/bar:file.bzl", library_alias = "some_library")

1 つの load ステートメント内に複数のエイリアスを定義できます。さらに、引数リストにはエイリアスと通常のシンボル名の両方を含めることができます。次の例は、完全に合法的です(引用符を使用する状況に注意してください)。

load(":my_rules.bzl", "some_rule", nice_alias = "some_other_rule")

.bzl ファイルでは、_ で始まるシンボルはエクスポートされず、別のファイルから読み込むこともできません。

読み込みの公開設定を使用すると、.bzl ファイルを読み込むことができるユーザーを制限できます。

ビルドルールの種類

ビルドルールの大半はファミリー形式になっており、言語ごとにグループ化されています。たとえば、cc_binarycc_librarycc_test は、それぞれ C++ バイナリ、ライブラリ、テスト用のビルドルールです。他の言語でも、同じ命名スキームで接頭辞が異なります(Java の場合は java_* など)。これらの関数の一部は Build Encyclopedia に記載されていますが、誰でも新しいルールを作成できます。

  • *_binary ルールは、指定された言語の実行可能プログラムを作成します。ビルド後、実行可能ファイルは、ルールのラベルに対応する名前でビルドツールのバイナリ出力ツリーに配置されます。したがって、//my:program$(BINDIR)/my/program などに表示されます。

    一部の言語では、このようなルールにより、ルールに属する data 属性で指定されたすべてのファイルを含む runfiles ディレクトリや、依存関係の推移的なクロージャ内のルールも作成されます。このファイルセットが 1 か所に集約され、本番環境へのデプロイが容易になります。

  • *_test ルールは、*_binary ルールの特殊なものであり、自動テストに使用されます。テストとは、簡単に言えば成功時にゼロを返すプログラムです。

    バイナリと同様に、テストにも runfile ツリーがあり、その下のファイルだけがテストで実行時に正しく開くことができます。たとえば、プログラム cc_test(name='x', data=['//foo:bar']) は、実行中に $TEST_SRCDIR/workspace/foo/bar を開いて読み取ることがあります。各プログラミング言語には、$TEST_SRCDIR の値にアクセスするための独自のユーティリティ関数がありますが、どれも環境変数を直接使用するのと同等です。ルールに従わないと、リモートテストホストでテストを実行したときに失敗します。

  • *_library ルールは、特定のプログラミング言語で個別にコンパイルされたモジュールを指定します。ライブラリは他のライブラリに依存できます。また、バイナリとテストはライブラリに依存し、個別のコンパイル動作が想定されます。

ラベル 依存関係