このページでは、 前提条件とインストール手順を含め、Maven から Bazel への移行方法について説明します。Maven と Bazel の違いについて説明し、Guava プロジェクトを使用した移行の例を示します。
ビルドツールから Bazel に移行する場合は、開発チーム、CI システム、その他の関連システムを完全に移行するまで、両方のビルドツール を並行して実行することをおすすめします。Maven と Bazel は同じ リポジトリで実行できます。
始める前に
- Bazel がまだインストールされていない場合は、インストールします。
- Bazel を初めて使用する場合は、移行を開始する前にチュートリアル Bazel の概要: Java をビルドするをご覧ください。このチュートリアルでは、 Bazel のコンセプト、構造、ラベル構文について説明します。
Maven と Bazel の違い
- Maven はトップレベルの
pom.xmlファイルを使用します。Bazel は複数のビルドファイル とBUILDファイルごとに複数のターゲットをサポートしているため、Maven よりも 増分ビルドが可能です。 - Maven はデプロイ プロセスの手順を担当します。Bazel はデプロイを自動化しません。
- Bazel を使用すると、言語間の依存関係を表現できます。
- プロジェクトに新しいセクションを追加する場合は、Bazel で新しい
BUILDファイルを追加する必要があります。新しい Java パッケージごとにBUILDファイルを追加することをおすすめします。
Maven から Bazel に移行する
次の手順では、プロジェクトを Bazel に移行する方法について説明します。
以下の例は、Guava
プロジェクトを Maven から Bazel に移行したものです。使用した
Guava プロジェクトはリリース v31.1 です。Guava を使用する例では、移行の各ステップについて説明していませんが、移行用に生成または手動で追加されたファイルとコンテンツを示しています。
$ git clone https://github.com/google/guava.git && cd guava
$ git checkout v31.1
1. MODULE.bazel ファイルを作成する
プロジェクトのルートに MODULE.bazel という名前のファイルを作成します。プロジェクトに外部依存関係がない場合、このファイルは空にできます。
プロジェクトがプロジェクトのディレクトリにないファイルまたはパッケージに依存している場合は、MODULE.bazel
ファイルでこれらの外部依存関係を指定します。rules_jvm_external を使用して Maven からの依存関係を管理できます。このルールセットの使用方法については、READMEをご覧ください。
Guava プロジェクトの例: 外部依存関係
Guava
プロジェクトの外部依存関係は、
rules_jvm_external
ルールセットで一覧表示できます。
次のスニペットを MODULE.bazel ファイルに追加します。
bazel_dep(name = "rules_jvm_external", version = "6.2")
maven = use_extension("@rules_jvm_external//:extensions.bzl", "maven")
maven.install(
artifacts = [
"com.google.code.findbugs:jsr305:3.0.2",
"com.google.errorprone:error_prone_annotations:2.11.0",
"com.google.j2objc:j2objc-annotations:1.3",
"org.codehaus.mojo:animal-sniffer-annotations:1.20",
"org.checkerframework:checker-qual:3.12.0",
],
repositories = [
"https://repo1.maven.org/maven2",
],
)
use_repo(maven, "maven")
2. BUILD ファイルを 1 つ作成する
ワークスペースを定義し、外部依存関係(該当する場合)を一覧表示したら、プロジェクトのビルド方法を記述する BUILD ファイルを作成する必要があります。1 つの pom.xml ファイルを使用する Maven とは異なり、Bazel は
多くの BUILD ファイルを使用してプロジェクトをビルドできます。これらのファイルは複数のビルド
ターゲットを指定するため、Bazel は増分ビルドを生成できます。
BUILD ファイルを段階的に追加します。まず、プロジェクトのルートに BUILD ファイルを 1 つ追加し、
それを使用して Bazel で初期ビルドを行います。次に、より詳細なターゲットを含む BUILD ファイルを追加して
ビルドを絞り込みます。
MODULE.bazelファイルと同じディレクトリにテキスト ファイルを作成し、BUILDという名前を付けます。この
BUILDファイルで、適切なルールを使用して、プロジェクトをビルドするターゲットを 1 つ作成します 。次のヒントを参考にしてください。適切なルールを使用します。
単一の Maven モジュールでプロジェクトをビルドするには、次のように
java_libraryルールを使用します。java_library( name = "everything", srcs = glob(["src/main/java/**/*.java"]), resources = glob(["src/main/resources/**"]), deps = ["//:all-external-targets"], )複数の Maven モジュールでプロジェクトをビルドするには、次のように
java_libraryルールを使用します。java_library( name = "everything", srcs = glob([ "Module1/src/main/java/**/*.java", "Module2/src/main/java/**/*.java", ... ]), resources = glob([ "Module1/src/main/resources/**", "Module2/src/main/resources/**", ... ]), deps = ["//:all-external-targets"], )バイナリをビルドするには、
java_binaryルールを使用します。java_binary( name = "everything", srcs = glob(["src/main/java/**/*.java"]), resources = glob(["src/main/resources/**"]), deps = ["//:all-external-targets"], main_class = "com.example.Main" )属性を指定します。
name: ターゲットにわかりやすい名前を付けます。上記の例 では、ターゲットは「everything」と呼ばれます。srcs: glob を使用して、プロジェクト内のすべての .java ファイルを一覧表示します。resources: glob を使用して、プロジェクト内のすべてのリソースを一覧表示します。deps: プロジェクトに必要な外部依存関係を特定する必要があります。
Guava プロジェクトの移行からのこのトップレベルの BUILD ファイルの例を以下に示します。
プロジェクトのルートに
BUILDファイルを作成したら、 プロジェクトをビルドして動作することを確認します。コマンドラインで、ワークスペース ディレクトリからbazel build //:everythingを使用して、Bazel でプロジェクトをビルドします。これで、Bazel でプロジェクトが正常にビルドされました。プロジェクトの増分ビルドを可能にするには、 ファイルを追加する必要があります。
BUILD
Guava プロジェクトの例: 1 つの BUILD ファイルから始める
Guava プロジェクトを Bazel に移行する場合、最初は 1 つの BUILD ファイルを使用して
プロジェクト全体をビルドします。ワークスペース ディレクトリにあるこの初期 BUILD ファイルの内容は次のとおりです。
java_library(
name = "everything",
srcs = glob([
"guava/src/**/*.java",
"futures/failureaccess/src/**/*.java",
]),
javacopts = ["-XepDisableAllChecks"],
deps = [
"@maven//:com_google_code_findbugs_jsr305",
"@maven//:com_google_errorprone_error_prone_annotations",
"@maven//:com_google_j2objc_j2objc_annotations",
"@maven//:org_checkerframework_checker_qual",
"@maven//:org_codehaus_mojo_animal_sniffer_annotations",
],
)
3. BUILD ファイルをさらに作成する(省略可)
最初のビルドが完了した後に確認したように、Bazel は 1 つの BUILD file で動作します。それでも、詳細なターゲットを含む BUILD ファイルを追加して、ビルドを小さなチャンクに分割することを
検討する必要があります。
複数の BUILD ファイルを使用すると、複数のターゲットを含むビルドの粒度が向上し、次のことが可能になります。
- プロジェクトの増分ビルドの増加
- ビルドの並列実行の増加
- 将来のユーザー向けのビルドの保守性の向上
- パッケージ間のターゲットの可視性の制御。これにより、実装の詳細を含むライブラリが 公開 API に漏洩するなどの 問題を回避できます。
追加の BUILD ファイルを追加する際のヒント:
- まず、Java パッケージごとに
BUILDファイルを追加します。依存関係が最も少ない Java パッケージから始め、依存関係が最も多いパッケージ まで順に処理します。 BUILDファイルを追加してターゲットを指定したら、これらの新しいターゲットを、それらに依存するターゲットのdepsセクションに追加します。`glob()` 関数はパッケージ境界を越えないため、パッケージ数が増えるにつれて、`glob()` で一致するファイルは減少します。glob()glob()mainディレクトリにBUILDファイルを追加する場合は、対応するtestディレクトリにBUILDファイルを追加してください。- パッケージ間の可視性を適切に制限するようにしてください。
BUILDファイルの設定でエラーのトラブルシューティングを簡単にするには、 各ビルドファイルを追加するときに、プロジェクトが Bazel でビルドされるようにします。bazel build //...を実行して、すべてのターゲットがビルドされることを確認します。
4. Bazel を使用してビルドする
ビルドの設定を検証するときに、Bazel を使用して BUILD ファイルを追加してビルドしています。
必要な粒度で BUILD ファイルを作成したら、Bazel を使用して
すべてのビルドを生成できます。