はじめに
Bazel は初めてですか?お問い合わせいただきありがとうございます。Bazel の使用方法を簡単に説明した最初のビルドのチュートリアルをご覧ください。このチュートリアルでは、Bazel のコンテキストで使用される重要な用語を定義し、Bazel ワークフローの基本について説明します。必要なツールから始めて、複雑さを増す 3 つのプロジェクトを構築して実行し、複雑になる仕組みと理由を学びます。
Bazel はマルチリンガル ビルドをサポートするビルドシステムですが、このチュートリアルでは C++ プロジェクトを例として使用し、ほとんどの言語に適用される一般的なガイドラインとフローを説明します。
所要時間: 30 分
前提条件
まず、Bazel をインストールします(まだインストールしていない場合)。このチュートリアルでは Git をソース管理に使用するため、最適な結果を得るには Git をインストールしてください。
次に、任意のコマンドライン ツールで次のコマンドを実行して、Bazel の GitHub リポジトリからサンプル プロジェクトを取得します。
git clone https://github.com/bazelbuild/examplesこのチュートリアルのサンプル プロジェクトは examples/cpp-tutorial ディレクトリにあります。
構造は次のとおりです。
examples
└── cpp-tutorial
├──stage1
│ ├── main
│ │ ├── BUILD
│ │ └── hello-world.cc
│ └── MODULE.bazel
├──stage2
│ ├── main
│ │ ├── BUILD
│ │ ├── hello-world.cc
│ │ ├── hello-greet.cc
│ │ └── hello-greet.h
│ └── MODULE.bazel
└──stage3
├── main
│ ├── BUILD
│ ├── hello-world.cc
│ ├── hello-greet.cc
│ └── hello-greet.h
├── lib
│ ├── BUILD
│ ├── hello-time.cc
│ └── hello-time.h
└── MODULE.bazel
ファイルは 3 つのセットがあり、各セットはチュートリアルのステージを表します。最初のステージでは、1 つのパッケージに存在する 1 つのターゲットを構築します。2 番目のステージでは、1 つのパッケージからバイナリとライブラリの両方をビルドします。3 つ目のステージ(最後のステージ)では、複数のパッケージを含むプロジェクトをビルドし、複数のターゲットでビルドします。
概要: 概要
Bazel(および Git)をインストールし、このチュートリアル用のリポジトリのクローンを作成することで、Bazel を使用した最初のビルドの基盤ができました。次のセクションに進んで用語を定義し、ワークスペースを設定します。
スタートガイド
プロジェクトをビルドする前に、ワークスペースを設定する必要があります。ワークスペースは、プロジェクトのソースファイルと Bazel のビルド出力を保持するディレクトリです。また、次の重要なファイルも含まれています。
MODULE.bazelファイル。ディレクトリとその内容を Bazel ワークスペースとして識別し、プロジェクトのディレクトリ構造のルートに存在します。また、外部依存関係を指定することもできます。- 1 つ以上の
BUILDファイル。これは、プロジェクトのさまざまな部分をビルドする方法を Bazel に指示します。ワークスペース内のBUILDファイルを含むディレクトリはパッケージです。(パッケージについては、このチュートリアルの後半で説明します)。
今後のプロジェクトでディレクトリを Bazel ワークスペースとして指定するには、そのディレクトリに MODULE.bazel という名前の空のファイルを作成します。このチュートリアルでは、各ステージに MODULE.bazel ファイルがすでに存在しています。
BUILD ファイルを理解する
BUILD ファイルには、Bazel 用のさまざまなタイプの指示が含まれています。各 BUILD ファイルには、命令セットとして少なくとも 1 つのルールが必要です。このルールは、実行可能バイナリやライブラリなどの目的の出力のビルド方法を Bazel に指示します。BUILD ファイル内のビルドルールの各インスタンスはターゲットと呼ばれ、特定のソースファイルと依存関係のセットを参照します。ターゲットは他のターゲットを指す場合もあります。
cpp-tutorial/stage1/main ディレクトリの BUILD ファイルを確認します。
cc_binary(
name = "hello-world",
srcs = ["hello-world.cc"],
)
この例では、hello-world ターゲットが Bazel の組み込み cc_binary ルールをインスタンス化します。このルールは、hello-world.cc> ソースファイルから依存関係のない自己完結型の実行可能バイナリをビルドするように Bazel に指示します。
概要: スタートガイド
これで、いくつかのキーワードと、このプロジェクトと一般的な Bazel のコンテキストにおけるそれらの意味を理解できました。次のセクションでは、プロジェクトのステージ 1 をビルドしてテストします。
ステージ 1: 単一ターゲット、単一パッケージ
プロジェクトの最初の部分を構築しましょう。プロジェクトの Stage 1 セクションの構造は次のとおりです。
examples
└── cpp-tutorial
└──stage1
├── main
│ ├── BUILD
│ └── hello-world.cc
└── MODULE.bazel
次のコマンドを実行して cpp-tutorial/stage1 ディレクトリに移動します。
cd cpp-tutorial/stage1続いて、次のコマンドを実行します。
bazel build //main:hello-worldターゲット ラベルの //main: 部分は、ワークスペースのルートからの BUILD ファイルの場所であり、hello-world は BUILD ファイル内のターゲット名です。
Bazel は次のような出力を生成します。
INFO: Found 1 target...
Target //main:hello-world up-to-date:
bazel-bin/main/hello-world
INFO: Elapsed time: 2.267s, Critical Path: 0.25s
これで、最初の Bazel ターゲットがビルドされました。Bazel は、ワークスペースのルートにある bazel-bin ディレクトリにビルド出力を配置します。
新しくビルドしたバイナリをテストします。バイナリは次のとおりです。
bazel-bin/main/hello-worldこれにより、「Hello world」というメッセージが印刷されます。
ステージ 1 の依存関係グラフは次のとおりです。

概要: ステージ 1
最初のビルドが完了したので、ビルドの構造について基本的な理解ができました。次のステージでは、別のターゲットを追加して複雑さを追加します。
ステージ 2: 複数のビルド ターゲット
小規模なプロジェクトでは 1 つのターゲットで十分ですが、大規模なプロジェクトは複数のターゲットとパッケージに分割することをおすすめします。これにより、増分ビルドを高速化できます。つまり、Bazel は変更された部分のみを再ビルドします。また、プロジェクトの複数の部分を一度にビルドすることで、ビルドを高速化できます。このチュートリアルのこのステージではターゲットを追加し、次のステージではパッケージを追加します。
これはステージ 2 で使用するディレクトリです。
├──stage2
│ ├── main
│ │ ├── BUILD
│ │ ├── hello-world.cc
│ │ ├── hello-greet.cc
│ │ └── hello-greet.h
│ └── MODULE.bazel
cpp-tutorial/stage2/main ディレクトリの BUILD ファイルを確認します。
cc_library(
name = "hello-greet",
srcs = ["hello-greet.cc"],
hdrs = ["hello-greet.h"],
)
cc_binary(
name = "hello-world",
srcs = ["hello-world.cc"],
deps = [
":hello-greet",
],
)
この BUILD ファイルを使用すると、Bazel はまず hello-greet ライブラリをビルドし(Bazel の組み込み cc_library ルールを使用)、次に hello-world バイナリをビルドします。hello-world ターゲットの deps 属性は、hello-world バイナリのビルドに hello-greet ライブラリが必要であることを Bazel に伝えます。
この新しいバージョンのプロジェクトをビルドする前に、ディレクトリを変更して cpp-tutorial/stage2 ディレクトリに切り替える必要があります。次のコマンドを実行します。
cd ../stage2これで、次のよく知られたコマンドを使用して新しいバイナリをビルドできます。
bazel build //main:hello-world再度、Bazel は次のような出力を生成します。
INFO: Found 1 target...
Target //main:hello-world up-to-date:
bazel-bin/main/hello-world
INFO: Elapsed time: 2.399s, Critical Path: 0.30s
これで、新しくビルドしたバイナリをテストできます。このバイナリは別の「Hello
world」を返します。
bazel-bin/main/hello-worldhello-greet.cc を変更してプロジェクトを再ビルドすると、Bazel はそのファイルのみを再コンパイルします。
依存関係グラフを見ると、hello-world は hello-greet という名前の追加入力に依存していることがわかります。

概要: ステージ 2
これで、2 つのターゲットを含むプロジェクトが作成されました。hello-world ターゲットは 1 つのソースファイルをビルドし、他の 1 つのターゲット(//main:hello-greet)に依存します。このターゲットは、さらに 2 つのソースファイルをビルドします。次のセクションでは、さらに進んで別のパッケージを追加します。
ステージ 3: 複数のパッケージ
この次のステージでは、複雑さがさらに増し、複数のパッケージを含むプロジェクトをビルドします。cpp-tutorial/stage3 ディレクトリの構造と内容を確認します。
└──stage3
├── main
│ ├── BUILD
│ ├── hello-world.cc
│ ├── hello-greet.cc
│ └── hello-greet.h
├── lib
│ ├── BUILD
│ ├── hello-time.cc
│ └── hello-time.h
└── MODULE.bazel
2 つのサブディレクトリがあり、それぞれに BUILD ファイルが含まれていることがわかります。したがって、Bazel から見ると、ワークスペースには lib と main の 2 つのパッケージが含まれています。
lib/BUILD ファイルを確認します。
cc_library(
name = "hello-time",
srcs = ["hello-time.cc"],
hdrs = ["hello-time.h"],
visibility = ["//main:__pkg__"],
)
main/BUILD ファイルで次のようにします。
cc_library(
name = "hello-greet",
srcs = ["hello-greet.cc"],
hdrs = ["hello-greet.h"],
)
cc_binary(
name = "hello-world",
srcs = ["hello-world.cc"],
deps = [
":hello-greet",
"//lib:hello-time",
],
)
メイン パッケージの hello-world ターゲットは、lib パッケージの hello-time ターゲットに依存しています(ターゲットラベル //lib:hello-time がそのことを示しています)。Bazel は deps 属性を通じてこれを認識します。これは依存関係グラフに反映されています。

ビルドを成功させるには、visibility 属性を使用して、lib/BUILD の //lib:hello-time ターゲットを main/BUILD のターゲットに明示的に表示します。これは、デフォルトではターゲットが同じ BUILD ファイル内の他のターゲットにのみ表示されるためです。Bazel は、ターゲットの公開設定を使用して、実装の詳細を含むライブラリが公開 API に漏洩するなどの問題を防ぎます。
プロジェクトの最終版をビルドします。次のコマンドを実行して、cpp-tutorial/stage3 ディレクトリに切り替えます。
cd ../stage3再度、次のコマンドを実行します。
bazel build //main:hello-worldBazel は次のような出力を生成します。
INFO: Found 1 target...
Target //main:hello-world up-to-date:
bazel-bin/main/hello-world
INFO: Elapsed time: 0.167s, Critical Path: 0.00s
最後に、このチュートリアルの最後のバイナリをテストして、最終的な Hello world メッセージを確認します。
bazel-bin/main/hello-world概要: ステージ 3
これで、3 つのターゲットを含む 2 つのパッケージとしてプロジェクトがビルドされ、それらの間の依存関係が理解されました。これにより、今後 Bazel でプロジェクトをビルドする準備が整いました。次のセクションでは、Bazel の学習を継続する方法について説明します。
次のステップ
これで、Bazel を使用した最初の基本的なビルドが完了しました。しかし、これはほんの始まりにすぎません。Bazel についてさらに学習するためのリソースを以下にご紹介します。
- C++ に焦点を当てるには、一般的な C++ ビルドのユースケースをご覧ください。
- Bazel を使用して他のアプリケーションのビルドを開始するには、Java、Android アプリケーション、iOS アプリケーションのチュートリアルをご覧ください。
- ローカル リポジトリとリモート リポジトリの操作の詳細については、外部依存関係をご覧ください。
- Bazel のその他のルールの詳細については、こちらのリファレンス ガイドをご覧ください。
Happy building!