このページでは、Bazel を使用したプログラム、ビルドコマンド構文、ターゲット パターン構文の作成方法について説明します。
クイックスタート
Bazel を実行するには、ベースのワークスペース ディレクトリまたはそのサブディレクトリに移動して、「bazel
」と入力します。新しいワークスペースを作成する必要がある場合は、ビルドをご覧ください。
bazel help
[Bazel release bazel version]
Usage: bazel command options ...
使用可能なコマンド
analyze-profile
: ビルド プロファイル データを分析します。aquery
: 事後分析アクション グラフでクエリを実行します。build
: 指定されたターゲットをビルドします。canonicalize-flags
: Bazel フラグを正規化します。clean
: 出力ファイルを削除し、必要に応じてサーバーを停止します。cquery
: 分析後の依存関係グラフクエリを実行する。dump
: Bazel サーバー プロセスの内部状態をダンプします。help
: コマンドまたはインデックスのヘルプを出力します。info
: bazel サーバーに関するランタイム情報を表示します。fetch
: ターゲットの外部依存関係をすべて取得します。mobile-install
: モバイル デバイスにアプリをインストールします。query
: 依存関係グラフクエリを実行します。run
: 指定したターゲットを実行します。shutdown
: Bazel サーバーを停止します。test
: 指定したテスト ターゲットをビルドして実行します。version
: Bazel のバージョン情報を出力します。
参考情報
bazel help command
:command
のヘルプとオプションを出力します。bazel help
startup_options
: Bazel をホストする JVM のオプション。bazel help
target-syntax
: ターゲットを指定する構文について説明します。bazel help info-keys
: info コマンドで使用されるキーのリストを表示します。
bazel
ツールは、コマンドと呼ばれるさまざまな関数を実行します。よく使用されるのは bazel build
と bazel test
です。オンライン ヘルプ メッセージは、bazel help
で表示できます。
1 つのターゲットをビルドする
ビルドを開始するには、ワークスペースが必要です。ワークスペースは、アプリケーションの構築に必要なすべてのソースファイルを含むディレクトリ ツリーです。Bazel を使用すると、完全に読み取り専用のボリュームからビルドを実行できます。
Bazel でプログラムをビルドするには、bazel build
に続けて、ビルドするターゲットを入力します。
bazel build //foo
//foo
をビルドするコマンドを発行すると、次のような出力が表示されます。
INFO: Analyzed target //foo:foo (14 packages loaded, 48 targets configured).
INFO: Found 1 target...
Target //foo:foo up-to-date:
bazel-bin/foo/foo
INFO: Elapsed time: 9.905s, Critical Path: 3.25s
INFO: Build completed successfully, 6 total actions
まず、Bazel はターゲットの依存関係グラフ内のすべてのパッケージを読み込みます。これには、宣言された依存関係、ターゲットの BUILD
ファイルに直接リストされているファイル、ターゲットの依存関係の BUILD
ファイルにリストされているファイル、推移的な依存関係が含まれます。Bazel は、すべての依存関係を特定した後、その正確性を分析して、ビルド アクションを作成します。Bazel はビルドのコンパイラとその他のツールを実行します。
ビルドの実行フェーズ中に、Bazel が進行状況のメッセージを出力します。進行状況のメッセージには、現在のビルドステップ(コンパイラやリンカーなど)の開始時と、ビルド アクションの合計数で完了した数が含まれます。ビルドを開始すると、Bazel はアクション グラフ全体を検出すると合計アクション数が増えることが多くなりますが、数秒以内に数が安定します。
ビルドの最後に、Bazel はリクエストされたターゲット、正常にビルドされたかどうか、出力ファイルがある場所を出力します。ビルドを実行するスクリプトは、この出力を確実に解析できます。詳しくは、--show_result
をご覧ください。
同じコマンドをもう一度入力すると、ビルドがはるかに速く終了します。
bazel build //foo
INFO: Analyzed target //foo:foo (0 packages loaded, 0 targets configured).
INFO: Found 1 target...
Target //foo:foo up-to-date:
bazel-bin/foo/foo
INFO: Elapsed time: 0.144s, Critical Path: 0.00s
INFO: Build completed successfully, 1 total action
これは null ビルドです。変更がないため、再読み込みするパッケージや実行すべきビルドステップはありません。「foo」またはその依存関係に変更が加えられた場合、Bazel は一部のビルド アクションを再実行するか、増分ビルドを完了します。
複数のターゲットをビルドする
Bazel では、ビルドするターゲットをさまざまな方法で指定できます。これらを総称してターゲット パターンと呼びます。この構文は、build
、test
、query
などのコマンドで使用されます。
ラベルは、BUILD
ファイル内の依存関係を宣言するなど、個々のターゲットを指定するために使用されますが、Bazel のターゲット パターンは複数のターゲットを指定します。ターゲット パターンは、ワイルドカードを使用したターゲット セットのラベル一般を一般化したものです。最も単純なケースでは、有効なラベルは有効なターゲット パターンでもあり、ターゲットを 1 つだけ識別します。
//
で始まるすべてのターゲット パターンは、現在のワークスペースを基準として解決されます。
//foo/bar:wiz |
単一のターゲット //foo/bar:wiz のみ。 |
//foo/bar |
//foo/bar:bar と同じです。 |
//foo/bar:all |
パッケージ foo/bar 内のすべてのルール ターゲット。 |
//foo/... |
ディレクトリ foo の下にあるすべてのパッケージのすべてのルール ターゲット。 |
//foo/...:all |
ディレクトリ foo の下にあるすべてのパッケージのすべてのルール ターゲット。 |
//foo/...:* |
ディレクトリ foo 内のすべてのパッケージ内のすべてのターゲット(ルールとファイル)。 |
//foo/...:all-targets |
ディレクトリ foo 内のすべてのパッケージ内のすべてのターゲット(ルールとファイル)。 |
//... |
ワークスペース内のパッケージ内のすべてのターゲット。外部リポジトリのターゲットは含まれません。 |
//:all |
ワークスペースのルートに「BUILD」ファイルがある場合、トップレベル パッケージ内のすべてのターゲット。 |
//
で始まらないターゲット パターンは、現在の作業ディレクトリに対して解決されます。次の例では、foo
の作業ディレクトリを想定しています。
:foo |
//foo:foo と同じです。 |
bar:wiz |
//foo/bar:wiz と同じです。 |
bar/wiz |
次と同等です。
|
bar:all |
//foo/bar:all と同じです。 |
:all |
//foo:all と同じです。 |
...:all |
//foo/...:all と同じです。 |
... |
//foo/...:all と同じです。 |
bar/...:all |
//foo/bar/...:all と同じです。 |
デフォルトでは、ディレクトリ シンボリック リンクは再帰ターゲット パターンに従います(ただし、ワークスペースのルート ディレクトリで作成されたコンビニエンス シンボリック リンクなど)。
さらに、Bazel は、DONT_FOLLOW_SYMLINKS_WHEN_TRAVERSING_THIS_DIRECTORY_VIA_A_RECURSIVE_TARGET_PATTERN
という名前のファイルを含むディレクトリ内で再帰的なターゲット パターンを評価する場合、シンボリック リンクを適用しません。
foo/...
は、packages に対するワイルドカードです。パッケージ foo
の下にあるすべてのパッケージが(パッケージパスのすべてのルートに対して)再帰的に指定します。:all
は、パッケージ内のすべてのルールに一致する、target に対するワイルドカードです。foo/...:all
のようにこの 2 つを組み合わせることができます。両方のワイルドカードを使用する場合、これは foo/...
と省略される場合があります。
さらに、:*
(または :all-targets
)は、一致したパッケージのすべてのターゲットに一致するワイルドカードです。通常、java_binary
ルールに関連付けられた _deploy.jar
ファイルなど、ルールによってビルドされないファイルも含まれます。
これは、:*
が :all
のスーパーセットであることを示します。この構文を混同する可能性はありますが、_deploy.jar
のようなビルド ターゲットを必要としない一般的なビルドには、使い慣れた :all
ワイルドカードを使用できます。
Bazel では、ラベル構文で必要なコロンの代わりにスラッシュを使用できます。これは、Bash ファイル名の展開を使用するときに便利です。たとえば、foo/bar/wiz
は //foo/bar:wiz
(パッケージ foo/bar
がある場合)または //foo:bar/wiz
(パッケージ foo
がある場合)と同等です。
多くの Bazel コマンドは、ターゲット パターンのリストを引数として受け取り、すべて接頭辞否定演算子 -
に従います。これは、先行する引数で指定されたセットからターゲットのセットを減算するために使用できます。つまり、順序が重要です。次に例を示します。
bazel build foo/... bar/...
これは、「foo
の下にあるすべてのターゲットと bar
下のすべてのターゲット」を作成することを意味します。
bazel build -- foo/... -foo/bar/...
「foo
」より下位にあるすべてのターゲットをビルドします(foo/bar
を除く)。--
引数は、-
で始まる後続の引数が追加のオプションとして解釈されないようにするために必要です。
ただし、この方法で目標値を差し引いただけでは、その目標が減算されていない目標の依存関係になっている可能性があるため、保証されないことに注意する必要があります。たとえば、//foo/bar:api
に依存するターゲット //foo:all-apis
がある場合、後者は前者の構築の一部としてビルドされます。
tags = ["manual"]
を含むターゲットは、bazel build
や bazel test
などのコマンドで指定すると、ワイルドカード ターゲット パターン(...
、:*
、:all
など)には含まれません(ただし、サブカードには ブラウズに含まれます)。Bazel でビルドまたはテストする場合は、コマンドラインでテスト ターゲットを明示的に指定する必要があります。一方、bazel query
はこのようなフィルタリングを自動的には行いません(bazel query
の目的が損なわれます)。
外部依存関係の取得
デフォルトでは、Bazel はビルド時に外部依存関係をダウンロードしてシンボリック リンクします。ただしこれは、新しい外部依存関係が追加されたときや、依存関係を「プリフェッチ」したい(オフラインになるフライトの前に)ため、望ましくない場合があります。ビルド中に新しい依存関係が追加されないようにする場合は、--fetch=false
フラグを指定します。このフラグは、ローカル ファイル システムのディレクトリをポイントしないリポジトリ ルールにのみ適用されます。たとえば、local_repository
、new_local_repository
、Android SDK、NDK リポジトリ ルールの変更は、値 --fetch
に関係なく、常に有効になります。
ビルド中に取得を禁止していて、Bazel が新しい外部依存関係を検出した場合、ビルドは失敗します。
bazel fetch
を実行することで、依存関係を手動で取得できます。ビルド時の取得を禁止する場合は、bazel fetch
を実行する必要があります。
- 初めてビルドする場合。
- 新しい外部依存関係を追加した後。
一度実行したら、WORKSPACE ファイルが変更されるまで再度実行する必要はありません。
fetch
は、依存関係をフェッチするターゲットのリストを受け取ります。たとえば、//foo:bar
と //bar:baz
のビルドに必要な依存関係をフェッチします。
bazel fetch //foo:bar //bar:baz
ワークスペースのすべての外部依存関係を取得するには、次のコマンドを実行します。
bazel fetch //...
ワークスペースのルートで使用しているすべてのツール(ライブラリ jar から JDK まで)があれば、Bazel 取得を実行する必要はありません。
ただし、ワークスペース ディレクトリ以外を使用している場合、Bazel は自動的に bazel build
を実行する前に bazel fetch
を実行します。
リポジトリのキャッシュ
異なるワークスペースで同じファイルが必要な場合や、外部リポジトリの定義が変更されたものの、ダウンロードのために同じファイルが必要な場合でも、Bazel は同じファイルを複数回取得しようとしません。これを行うには、bazel はリポジトリ キャッシュに保存されたすべてのファイルをキャッシュに保存します。リポジトリ キャッシュは、デフォルトでは ~/.cache/bazel/_bazel_$USER/cache/repos/v1/
にあります。ロケーションは --repository_cache
オプションによって変更できます。キャッシュは、すべてのワークスペースとインストールされている bazel バージョン間で共有されます。Bazel は、正しいファイルのコピーがあることを確認した場合に、キャッシュからエントリを取得します。つまり、ダウンロード リクエストに SHA256 の合計ファイルが指定され、そのハッシュを含むファイルがキャッシュにある場合です。したがって、各外部ファイルのハッシュを指定することにより、セキュリティの観点から優れているだけでなく、不要なダウンロードを回避できます。
キャッシュがヒットするたびに、キャッシュ内のファイルの変更時刻が更新されます。このようにして、キャッシュ ディレクトリ内のファイルの最後の使用状況は、手動でキャッシュをクリーンアップする場合などに簡単に判断できます。アップストリームで利用できなくなったファイルのコピーが含まれる可能性があるため、キャッシュが自動的にクリーンアップされることはありません。
配布ファイル ディレクトリ
ディストリビューション ディレクトリも、不要なダウンロードを回避する Bazel のメカニズムです。Bazel は、リポジトリをキャッシュする前にディストリビューション ディレクトリを検索します。主な違いは、配布ディレクトリを手動で準備する必要があることです。
--distdir=/path/to-directory
オプションを使用すると、ファイルをフェッチする代わりに、読み取り専用のディレクトリを追加で指定できます。ファイル名が URL のベース名と同じで、さらにファイルのハッシュがダウンロード リクエストで指定されたハッシュと等しい場合、ファイルはこのディレクトリから取得されます。これは、WORKSPACE 宣言でファイル ハッシュが指定されている場合にのみ機能します。
ファイル名の条件は正確性には必要ありませんが、指定されたディレクトリごとに候補ファイルの数が 1 つに減ります。このようにして、そのようなディレクトリ内のファイル数が増えても、配布ファイルのディレクトリを指定すると効率的に機能します。
エアポート環境で Bazel を実行する
Bazel のバイナリサイズを小さくするため、Bazel の暗黙の依存関係は、初回実行時にネットワーク上で取得されます。これらの暗黙的な依存関係には、全員に必要のないツールチェーンとルールが含まれています。たとえば、Android ツールは Android プロジェクトがバンドルされている場合にのみバンドルされ、フェッチされます。
ただし、暗黙的な依存関係により、すべての WORKSPACE 依存関係をベンダー化している場合でも、エアギャップのある環境で Bazel を実行すると問題が発生する可能性があります。この問題を解決するには、これらの依存関係を含む配布ディレクトリを、ネットワークにアクセスできるマシンに準備してから、オフラインのアプローチで、エアギャップのある環境に転送します。
配布ディレクトリを準備するには、--distdir
フラグを使用します。暗黙的な依存関係はリリースごとに異なる場合があるため、新しい Bazel バイナリ バージョンごとにこれを行う必要があります。
エアギャップのある環境の外部でこれらの依存関係をビルドするには、まず適切なバージョンの Bazel ソースツリーをチェックアウトします。
git clone https://github.com/bazelbuild/bazel "$BAZEL_DIR"
cd "$BAZEL_DIR"
git checkout "$BAZEL_VERSION"
次に、その特定の Bazel バージョンの暗黙的なランタイム依存関係を含む tarball をビルドします。
bazel build @additional_distfiles//:archives.tar
この tarball を、エアギャップのある環境にコピーできるディレクトリにエクスポートします。--distdir
はディレクトリのネストレベルで非常に細かくできるため、--strip-components
フラグに注意してください。
tar xvf bazel-bin/external/additional_distfiles/archives.tar \
-C "$NEW_DIRECTORY" --strip-components=3
最後に、エアバック環境で Bazel を使用する場合は、ディレクトリを指す --distdir
フラグを渡します。便宜上、.bazelrc
エントリとして追加することもできます。
build --distdir=path/to/directory
ビルド構成とクロスコンパイル
特定のビルドの動作と結果を指定するすべての入力を 2 つのカテゴリに分けることができます。最初の種類は、プロジェクトの BUILD
ファイルに保存されている固有の情報です。ビルドルール、その属性の値、推移的な依存関係の完全なセットです。2 つ目は、ユーザーまたはビルドツールによって提供される外部データまたは環境データです。ターゲット アーキテクチャの選択、コンパイルとリンクのオプション、その他のツールチェーンの構成オプションです。Google では、環境データの完全なセットを「構成」と呼んでいます。
任意のビルドに複数の構成が存在する場合があります。クロスコンパイルについて考えてみます。このコンパイルでは、//foo:bin
実行可能ファイルは 64 ビット アーキテクチャ向けにビルドされますが、ワークステーションは 32 ビットマシンです。当然ながら、ビルドには 64 ビットの実行可能ファイルを作成できるツールチェーンを使用して //foo:bin
をビルドする必要がありますが、ビルドシステムはビルド中に使用されるさまざまなツール(ソースからビルドされたツール、その後 genrule など)をビルドする必要があります。さらに、ワークステーションで実行するようにビルドする必要があります。これにより、ビルド中に実行されるツールのビルドに使用される exec 構成と、ターゲット構成(またはリクエスト構成ですが、この単語にはすでに多くの意味がありますが、多くの場合は「ターゲット構成」と言います)の 2 つの構成を識別できます。これらは、最終的にリクエストされたバイナリをビルドするために使用されます。
通常、リクエストされたビルド ターゲット(//foo:bin
)と 1 つ以上の exec ツール(前提条件のベースライブラリ)の前提条件となるライブラリは数多くあります。このようなライブラリは、実行構成用に 1 回、ターゲット構成用に 1 回、2 回ビルドする必要があります。Bazel は、両方のバリアントがビルドされるようにします。また、干渉を避けるために派生ファイルを個別に保持します。このようなターゲットは互いに独立しているため、通常は同時にビルドできます。特定のターゲットが 2 回ビルドされていることを示す進行状況メッセージが表示された場合は、これが説明の可能性があります。
exec 構成は、次のようにターゲット構成から派生します。
--host_crosstool_top
が指定されていない限り、リクエスト構成で指定されているのと同じバージョンの Crosstool(--crosstool_top
)を使用します。--cpu
には--host_cpu
の値を使用します(デフォルト:k8
)。- リクエスト構成で指定されているオプション(
--compiler
、--use_ijars
)と同じ値を使用します。--host_crosstool_top
が使用される場合、--host_cpu
の値は、クロスツール(--compiler
を無視)で実行構成のdefault_toolchain
を検索します。 --javabase
には--host_javabase
の値を使用します。--java_toolchain
には--host_java_toolchain
の値を使用します。- C++ コード(
-c opt
)用に最適化されたビルドを使用します。 - デバッグ情報を生成しません(
--copt=-g0
)。 - 実行可能ファイルと共有ライブラリ(
--strip=always
)からデバッグ情報を削除します。 - 派生ファイルはすべて、リクエスト構成で使用する場所とは別に、特別な場所に配置します。
- ビルドデータでバイナリのスタンプを抑制します(
--embed_*
オプションを参照)。 - その他の値はすべてデフォルトのままです。
リクエスト構成から別の実行構成を選択する方が適切である理由はさまざまです。最も重要なポイント:
まず、最適化されたバイナリの最適化により、ツールのリンクと実行にかかる時間、ツールが占有するディスク容量、分散ビルドのネットワーク I/O 時間を削減できます。
次に、前述のようにすべてのビルドで exec 構成とリクエスト構成を分離することで、リクエスト構成の軽微な変更(リンカー オプションの変更など)による高額な再ビルドを回避できます。
正しい増分再ビルド
Bazel プロジェクトの主な目標の 1 つは、適切な増分再ビルドを可能にすることです。以前のビルドツール(特に Make をベースにしたツール)では、増分ビルドの実装でいくつかの想定外の仮定が行われています。
まず、ファイルのタイムスタンプが単調に増加します。これはよくあるケースですが、以前の想定どおりにファイルの変更を実行すると、ファイルの変更時間が短縮されます。Make ベースのシステムは再ビルドされません。
一般に、Make はファイルへの変更を検出しますが、コマンドの変更を検出しません。特定のビルドステップでコンパイラに渡されるオプションを変更しても、Make はコンパイラを再実行しません。make clean
を使用して以前のビルドの無効な出力を手動で破棄する必要があります。
また、あるサブプロセスが出力ファイルへの書き込みを開始した後で、そのサブプロセスの終了に失敗しても、Make は堅牢ではありません。Make の現在の実行は失敗しますが、その後の Make の呼び出しでは、切り捨てられた出力ファイルが有効(入力値よりも新しいため)とみなされ、再ビルドされません。同様に、Make プロセスが強制終了されると、同様の状況が発生する場合があります。
Bazel はこれらの前提を回避します。Bazel は、以前に完了したすべての作業のデータベースを維持し、そのビルドステップに対する入力ファイルのセット(およびそのタイムスタンプ)と、そのビルドステップのコンパイル コマンドが、データベース内の 1 つの出力ファイル(およびそのタイムスタンプ)とディスク上のファイルのタイムスタンプを正確に一致していることを認識した場合にのみ、ビルドステップを省略します。入力ファイルや出力ファイル、またはコマンド自体を変更すると、ビルドステップが再実行されます。
正しい増分ビルドを使用するメリットは、混乱による無駄な時間の短縮です。(make
clean
を使用すると、再ビルドの待機時間も短縮されます(必要かつ先制)
ビルドの整合性と増分ビルド
正式には、想定される出力ファイルがすべて存在し、その作成に必要な手順またはルールで指定されているとおりの内容が正しい場合、ビルドの状態は一貫して定義されます。ソースファイルを編集すると、ビルドの状態に整合性がないと判断され、次にビルドツールを正常に実行しないと整合性がなくなります。Google では、この状況は一時的なものであり、ビルドツールを実行することで整合性が復元されるため、不安定な整合性と表現します。
悪影響を及ぼすもう 1 つの種類の不整合は、安定版です。ビルドが安定していない状態に達した場合、ビルドツールを繰り返し呼び出しても整合性が復元されません。ビルドが「停止」し、出力が正しくないことを意味します。不整合な状態が安定しているのは、Make(および他のビルドツール)のユーザーが make clean
と入力する主な理由です。この方法でビルドツールが機能しなくなり、そこから復元したことに気づくには、多大な時間と手間がかかります。
概念的には、一貫性のあるビルドを実現する最も簡単な方法は、以前のビルド出力をすべて破棄して最初からやり直すことです。すべてのビルドをクリーンビルドにします。このアプローチは明らかに実用的でなく(リリース エンジニアを除く)、有用であるため、ビルドツールは一貫性を損なうことなく増分ビルドを実行できる必要があります。
正しい増分依存関係の分析は困難です。前述のように、他の多くのビルドツールは、増分ビルド中の安定した不整合状態を回避するという点で劣ります。一方、Bazel ではビルドの編集ツールの呼び出しに成功すると、編集は行われず、ビルドが一貫した状態になります。ビルド中にソースファイルを編集した場合、Bazel は現在のビルドの結果の整合性を保証しません。ただし、次のビルドの結果には整合性が保証されます)。
あらゆる保証と同様に、ある程度の細かいメリットがあります。Bazel で安定版と整合性がとれていない状態にする方法はいくつかあります。増分依存関係分析でバグを意図的に見つけようとすることで、そのような問題を調査する保証はありませんが、ビルドツールの通常または「妥当な」使用に起因する安定した不整合の状態をすべて調査し、最善を尽くします。
Bazel で安定状態の不整合が検出された場合は、バグを報告してください。
サンドボックス実行
Bazel はサンドボックスを使用して、アクションが密閉して正しく実行されることを保証します。Bazel はサンドボックスでスポーン(大まかに言うとアクション)を実行します。サンドボックスには、ツールがそのジョブの実行に必要となる最小限のファイルセットのみが含まれています。現在、サンドボックスは CONFIG_USER_NS
オプションが有効になっている Linux 3.12 以降と、macOS 10.11 以降で動作します。
システムがサンドボックス化をサポートしていない場合、ビルドが密閉していることは保証されておらず、不明な方法でホストシステムに影響を与える可能性があることを知らせる警告が Bazel で出力されます。この警告を無効にするには、--ignore_unsupported_sandboxing
フラグを Bazel に渡します。
Google Kubernetes Engine クラスタノードや Debian などの一部のプラットフォームでは、セキュリティ上の懸念から、ユーザーの名前空間はデフォルトで無効になっています。これは、ファイル /proc/sys/kernel/unprivileged_userns_clone
で確認できます。このファイルが存在し、0 が含まれている場合は、sudo sysctl kernel.unprivileged_userns_clone=1
を使用してユーザーの名前空間を有効化できます。
場合によっては、システム設定のため、Bazel サンドボックスでルールを実行できないことがあります。通常、この問題は、namespace-sandbox.c:633: execvp(argv[0], argv): No such file or directory
のようなメッセージを出力するエラーになります。その場合は、--strategy=Genrule=standalone
を使用する genrule と、--spawn_strategy=standalone
を使用するその他のルールのサンドボックスを無効にしてみてください。また、今後のリリースで調査と修正を行えるよう、Issue Tracker でバグを報告し、使用している Linux ディストリビューションをお知らせください。
ビルドのフェーズ
Bazel では、ビルドは 3 つの異なるフェーズで行われます。ユーザーの違いを理解することで、ビルドを制御するオプションに関する分析情報を把握できます(以下を参照)。
読み込みフェーズ
1 つ目は読み込みです。この際、最初のターゲットに必要なすべての BUILD ファイルと、依存関係の推移的なクロージングが、読み込み、解析、評価、キャッシュに保存されます。
Bazel サーバーの起動後の最初のビルドでは、ファイル システムから多くの BUILD ファイルが読み込まれるため、読み込みフェーズには通常数秒かかります。以降のビルドでは、特に BUILD ファイルが変更されていなければ、読み込みが迅速に行われます。
このフェーズで報告されたエラーには、パッケージが見つからない、ターゲットが見つからない、BUILD ファイルの語彙エラーと文法エラー、評価エラーなどがあります。
分析フェーズ
2 番目のフェーズの分析には、各ビルドルールのセマンティック分析と検証、ビルド依存関係グラフの作成、ビルドの各ステップで何が行われるかの正確な決定が含まれます。
読み込みと同様に、計算全体が完了するまで数秒かかることもあります。ただし、Bazel は依存関係グラフをあるビルドから次のビルドにキャッシュし、必要なビルドのみを再分析します。これにより、前回のビルドからパッケージが変更されていない場合、増分ビルドは非常に高速になります。
この段階で報告されるエラーには、不適切な依存関係、ルールへの無効な入力、すべてのルール固有のエラー メッセージが含まれます。
読み込みと分析のフェーズは高速です。この段階で Bazel は不要なファイル I/O を回避し、実行すべき作業を決定するために BUILD ファイルだけを読み取るようにします。これは設計によるもので、Bazel は読み込みフェーズの上に実装される Bazel の query コマンドなどの分析ツールの優れた基盤となります。
実施フェーズ
ビルドの 3 つ目の最後のフェーズは実行です。このフェーズでは、ビルドの各ステップの出力と入力を一致させ、必要に応じてコンパイル / リンクなどのツールを再実行します。このステップでは、ビルドの大部分が、大規模なビルドの場合は数秒から 1 時間以上の範囲で費やされます。このフェーズで報告されたエラーには、ソースファイルの欠落、ビルドアクションによるツールのエラー、想定される出力セットを生成するツールの失敗などがあります。