はじめに
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
│ └── WORKSPACE
├──stage2
│ ├── main
│ │ ├── BUILD
│ │ ├── hello-world.cc
│ │ ├── hello-greet.cc
│ │ └── hello-greet.h
│ └── WORKSPACE
└──stage3
├── main
│ ├── BUILD
│ ├── hello-world.cc
│ ├── hello-greet.cc
│ └── hello-greet.h
├── lib
│ ├── BUILD
│ ├── hello-time.cc
│ └── hello-time.h
└── WORKSPACE
3 つのファイルセットがあり、各セットはこのチュートリアルの 1 つのステージを表します。最初のステージでは、1 つのパッケージ内に単一のターゲットをビルドします。第 2 ステージでは、1 つのパッケージからバイナリとライブラリの両方をビルドします。3 番目の最終ステージでは、複数のパッケージを含むプロジェクトをビルドし、複数のターゲットを使用してビルドします。
まとめ: はじめに
Bazel(および Git)をインストールし、このチュートリアルのリポジトリのクローンを作成することで、Bazel を使用した最初のビルドの基礎を固めることができました。次のセクションに進んで用語を定義し、ワークスペースを設定します。
ご利用にあたって
ワークスペースをセットアップする
プロジェクトをビルドするには、その前にワークスペースを設定する必要があります。ワークスペースは、プロジェクトのソースファイルと Bazel のビルド出力を格納するディレクトリです。また、次の重要なファイルも含まれます。
。ディレクトリとその内容を Bazel ワークスペースとして識別し、プロジェクトのディレクトリ構造のルートに存在します。WORKSPACE
file- 1 つ以上の
。プロジェクトのさまざまな部分をビルドする方法を Bazel に指示します。BUILD
filesBUILD
ファイルを含むワークスペース内のディレクトリはパッケージです。(パッケージの詳細については、このチュートリアルの後半で説明します)。
今後のプロジェクトで、ディレクトリを Bazel ワークスペースとして指定するには、そのディレクトリに WORKSPACE
という名前の空のファイルを作成します。このチュートリアルでは、各ステージに WORKSPACE
ファイルがすでに存在します。
注: 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 rule
をインスタンス化します。このルールは、依存関係のない hello-world.cc
ソースファイルから自己完結型の実行可能バイナリをビルドするよう Bazel に指示します。
概要: スタートガイド
これで、いくつかの重要な用語と、このプロジェクトと Bazel 全般における意味を理解できました。次のセクションではプロジェクトのステージ 1 をビルドしてテストします。
ステージ 1: 単一のターゲット、単一のパッケージ
それでは、プロジェクトの最初の部分を構築します。参考までに、プロジェクトのステージ 1 セクションの構造は次のとおりです。
examples
└── cpp-tutorial
└──stage1
├── main
│ ├── BUILD
│ └── hello-world.cc
└── WORKSPACE
次のコマンドを実行して 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: 複数のビルド ターゲット
小規模なプロジェクトには単一のターゲットで十分ですが、大規模なプロジェクトは複数のターゲットとパッケージに分割することをおすすめします。これにより、高速な増分ビルド(つまり、Bazel は変更された部分のみを再ビルドする)が可能になります。また、プロジェクトの複数の部分を一度にビルドすることで、ビルドを高速化できます。チュートリアルのこのステージではターゲットを追加し、次のステージではパッケージを追加します。
これは、ステージ 2 で作業するディレクトリです。
├──stage2
│ ├── main
│ │ ├── BUILD
│ │ ├── hello-world.cc
│ │ ├── hello-greet.cc
│ │ └── hello-greet.h
│ └── WORKSPACE
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 rule
を使用して)ビルドし、次に 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-world
ここで hello-greet.cc
を変更してプロジェクトを再ビルドすると、Bazel はそのファイルのみを再コンパイルします。
依存関係グラフを見ると、hello-world が以前と同じ入力に依存していることがわかりますが、ビルドの構造が異なります。
まとめ: ステージ 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
└── WORKSPACE
サブディレクトリが 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-world
Bazel により、次のような結果が生成されます。
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 のその他のルールについて詳しくは、こちらのリファレンス ガイドをご覧ください。
ご利用をお待ちしております。