From 94c6595843afd62c0f548f5122b7a5d62b79ec77 Mon Sep 17 00:00:00 2001 From: John Cormie Date: Mon, 18 May 2026 12:32:01 -0700 Subject: [PATCH 1/2] Centralize the officially supported bazel version Add .bazelversion files so that workflows and contributors can automatically use the same supported/tested version of bazel. `examples/.bazelversion` could have been a symlink but decided against this to avoid causing problems on Windows. --- .bazelversion | 1 + COMPILING.md | 16 ++++++++++++++++ examples/.bazelversion | 1 + 3 files changed, 18 insertions(+) create mode 100644 .bazelversion create mode 100644 examples/.bazelversion diff --git a/.bazelversion b/.bazelversion new file mode 100644 index 00000000000..df5119ec64e --- /dev/null +++ b/.bazelversion @@ -0,0 +1 @@ +8.7.0 diff --git a/COMPILING.md b/COMPILING.md index b7df1319beb..e39ee252972 100644 --- a/COMPILING.md +++ b/COMPILING.md @@ -150,3 +150,19 @@ $ANDROID_HOME/cmdline-tools/latest/bin/sdkmanager --licenses # Add 'export ANDROID_HOME=$HOME/Android/Sdk' to your .bashrc or equivalent ``` + +Building with Bazel +=================== + +grpc-java can also be built using [Bazel](https://bazel.build/). + +First [install bazelisk](https://github.com/bazelbuild/bazelisk#installation) +(unlike Gradle, Bazel's wrapper isn't checked-in to the grpc-java repository). + +To build the grpc-java library: +``` +$ bazelisk build //... +``` + +You cannot run the tests from Bazel at this time. + diff --git a/examples/.bazelversion b/examples/.bazelversion new file mode 100644 index 00000000000..df5119ec64e --- /dev/null +++ b/examples/.bazelversion @@ -0,0 +1 @@ +8.7.0 From 25cb32f7a80d469bd35f7dcbc99f32274f1b1f1f Mon Sep 17 00:00:00 2001 From: John Cormie Date: Thu, 14 May 2026 16:34:56 -0700 Subject: [PATCH 2/2] binder: bazel build support (bzlmod mode only) --- .bazelrc | 2 ++ .github/workflows/testing.yml | 6 ++-- COMPILING.md | 9 ++++++ MODULE.bazel | 50 +++++++++++++++++++++++++++++++++- binder/BUILD.bazel | 27 ++++++++++++++++++ buildscripts/kokoro/android.sh | 15 ++++++++++ 6 files changed, 104 insertions(+), 5 deletions(-) create mode 100644 binder/BUILD.bazel diff --git a/.bazelrc b/.bazelrc index 53485cb9743..4d371cf3512 100644 --- a/.bazelrc +++ b/.bazelrc @@ -1 +1,3 @@ build --cxxopt=-std=c++17 --host_cxxopt=-std=c++17 + +common:skip_android --deleted_packages=binder diff --git a/.github/workflows/testing.yml b/.github/workflows/testing.yml index 8793cfb82fe..ab110ef58c5 100644 --- a/.github/workflows/testing.yml +++ b/.github/workflows/testing.yml @@ -80,8 +80,6 @@ jobs: strategy: matrix: bzlmod: [true, false] - env: - USE_BAZEL_VERSION: 8.7.0 steps: - uses: actions/checkout@v4 @@ -100,10 +98,10 @@ jobs: key: ${{ runner.os }}-bazel-${{ env.USE_BAZEL_VERSION }}-${{ hashFiles('WORKSPACE', 'repositories.bzl') }} - name: Run bazel build - run: bazelisk build //... --enable_bzlmod=${{ matrix.bzlmod }} --enable_workspace=${{ !matrix.bzlmod }} + run: bazelisk build //... --config=skip_android --enable_bzlmod=${{ matrix.bzlmod }} --enable_workspace=${{ !matrix.bzlmod }} - name: Run bazel test - run: bazelisk test //... --enable_bzlmod=${{ matrix.bzlmod }} --enable_workspace=${{ !matrix.bzlmod }} + run: bazelisk test //... --config=skip_android --enable_bzlmod=${{ matrix.bzlmod }} --enable_workspace=${{ !matrix.bzlmod }} - name: Run example bazel build run: bazelisk build //... --enable_bzlmod=${{ matrix.bzlmod }} --enable_workspace=${{ !matrix.bzlmod }} diff --git a/COMPILING.md b/COMPILING.md index e39ee252972..fed597d14aa 100644 --- a/COMPILING.md +++ b/COMPILING.md @@ -164,5 +164,14 @@ To build the grpc-java library: $ bazelisk build //... ``` +Some parts of grpc-java depend on Android. Bazel can build these parts too but, +for size, licensing and maintenance reasons, it requires a locally installed +Android SDK. If you don't have the SDK and/or don't care about Android, use the +`skip_android` configuration to skip building the Android parts: + +```sh +$ bazelisk build //... --config=skip_android +``` + You cannot run the tests from Bazel at this time. diff --git a/MODULE.bazel b/MODULE.bazel index 50fd1f95d34..e1089bb9daf 100644 --- a/MODULE.bazel +++ b/MODULE.bazel @@ -46,16 +46,31 @@ IO_GRPC_GRPC_JAVA_ARTIFACTS = [ ] # GRPC_DEPS_END +ANDROID_ARTIFACTS = [ + "androidx.annotation:annotation:1.6.0", + "androidx.annotation:annotation-jvm:1.6.0", + "androidx.core:core:1.13.1", + "androidx.lifecycle:lifecycle-common:2.6.2", +] + bazel_dep(name = "abseil-cpp", version = "20250512.1") bazel_dep(name = "bazel_jar_jar", version = "0.1.11.bcr.1") bazel_dep(name = "bazel_skylib", version = "1.7.1") bazel_dep(name = "googleapis", version = "0.0.0-20240326-1c8d509c5", repo_name = "com_google_googleapis") bazel_dep(name = "grpc-proto", version = "0.0.0-20240627-ec30f58.bcr.1", repo_name = "io_grpc_grpc_proto") bazel_dep(name = "protobuf", version = "33.4", repo_name = "com_google_protobuf") +bazel_dep(name = "rules_android", version = "0.7.2") bazel_dep(name = "rules_cc", version = "0.0.9") bazel_dep(name = "rules_java", version = "9.1.0") bazel_dep(name = "rules_jvm_external", version = "6.0") +android_sdk_repository_extension = use_extension( + "@rules_android//rules/android_sdk_repository:rule.bzl", + "android_sdk_repository_extension", +) +use_repo(android_sdk_repository_extension, "androidsdk") +register_toolchains("@androidsdk//:sdk-toolchain", "@androidsdk//:all") + maven = use_extension("@rules_jvm_external//:extensions.bzl", "maven") maven.install( artifacts = IO_GRPC_GRPC_JAVA_ARTIFACTS, @@ -64,7 +79,36 @@ maven.install( ], strict_visibility = True, ) -use_repo(maven, "maven") + +# We isolate Android-specific deps in this separate repo ('grpc_android_maven') instead of the one +# above (having default name 'maven'). +# +# Under bzlmod, rules_jvm_external merges all contributions to the same named repository (like the +# default 'maven' repo) across the entire dependency graph. If we put Android dependencies there, +# then *every* downstream consumer's merged 'maven' repository would include these Android +# artifacts. +# +# Because merged repositories are resolved using only the root module's (the consumer's) +# repository list, any consumer without 'maven.google.com' configured in their root module +# would fail to resolve these artifacts, breaking their build even if they don't use Android. +# +# By using a distinct name ('grpc_android_maven'), we prevent merging. This repository is resolved +# independently, allowing it to use grpc-java's own repository config (which includes +# maven.google.com) without affecting downstream consumers' default 'maven' repo. +maven.install( + name = "grpc_android_maven", + artifacts = ANDROID_ARTIFACTS, + repositories = [ + "https://repo.maven.apache.org/maven2/", + "https://maven.google.com", # for androidx.* + ], + strict_visibility = True, + # Enable Starlark Android rules in rules_jvm_external for Bazel 8+ compatibility. + use_starlark_android_rules = True, + # Explicitly set the label for aar_import since the default guess is incorrect under Bzlmod. + aar_import_bzl_label = "@rules_android//rules:rules.bzl", +) +use_repo(maven, "maven", "grpc_android_maven") maven.override( coordinates = "com.google.protobuf:protobuf-java", @@ -158,3 +202,7 @@ maven.override( coordinates = "io.grpc:grpc-util", target = "@io_grpc_grpc_java//util", ) +maven.override( + coordinates = "io.grpc:grpc-binder", + target = "@io_grpc_grpc_java//binder", +) diff --git a/binder/BUILD.bazel b/binder/BUILD.bazel new file mode 100644 index 00000000000..2f2872f9ac2 --- /dev/null +++ b/binder/BUILD.bazel @@ -0,0 +1,27 @@ +load("@rules_android//rules:rules.bzl", "android_library") +load("@rules_jvm_external//:defs.bzl", "artifact") + +licenses(["notice"]) + +android_library( + name = "binder", + srcs = glob([ + "src/main/java/**/*.java", + ]), + manifest = "src/main/AndroidManifest.xml", + custom_package = "io.grpc.binder", + visibility = ["//visibility:public"], + exports = ["@grpc_android_maven//:androidx_annotation_annotation"], + deps = [ + "//api", + "//core:internal", + # Resolve android deps from the isolated grpc_android_maven repository. + "@grpc_android_maven//:androidx_annotation_annotation", + "@grpc_android_maven//:androidx_annotation_annotation_jvm", + "@grpc_android_maven//:androidx_core_core", + "@grpc_android_maven//:androidx_lifecycle_lifecycle_common", + artifact("com.google.code.findbugs:jsr305"), + artifact("com.google.errorprone:error_prone_annotations"), + artifact("com.google.guava:guava"), + ], +) diff --git a/buildscripts/kokoro/android.sh b/buildscripts/kokoro/android.sh index 677825ae66b..c46c3873276 100755 --- a/buildscripts/kokoro/android.sh +++ b/buildscripts/kokoro/android.sh @@ -27,9 +27,21 @@ unzip -qd "${ANDROID_HOME}/cmdline-tools" cmdline.zip rm cmdline.zip mv "${ANDROID_HOME}/cmdline-tools/cmdline-tools" "${ANDROID_HOME}/cmdline-tools/latest" (yes || true) | "${ANDROID_HOME}/cmdline-tools/latest/bin/sdkmanager" --licenses + +# Bazel requires build-tools at least version 35.0.0 and, unlike gradle, can't +# download it for itself. TODO(jdcormie): Keep this version in sync with AGP's +# default and/or any `buildToolsVersion` gradle config. +"${ANDROID_HOME}/cmdline-tools/latest/bin/sdkmanager" --install "build-tools;35.0.1" + curl -Ls https://github.com/Kitware/CMake/releases/download/v3.26.3/cmake-3.26.3-linux-x86_64.tar.gz | \ tar xz -C /tmp export PATH=/tmp/cmake-3.26.3-linux-x86_64/bin:$PATH + +# Install bazelisk to take care of installing the proper version(s) of bazel. +mkdir /tmp/bazelisk +curl -Ls -o /tmp/bazelisk/bazelisk https://github.com/bazelbuild/bazelisk/releases/download/v1.19.0/bazelisk-linux-amd64 +chmod +x /tmp/bazelisk/bazelisk +export PATH=/tmp/bazelisk:$PATH # Proto deps buildscripts/make_dependencies.sh @@ -44,6 +56,9 @@ sudo update-java-alternatives --set java-1.11.0-openjdk-amd64 # Unset any existing JAVA_HOME env var to stop Gradle from using it unset JAVA_HOME +# TODO(jdcormie): Use the same SDK version as build.gradle's compileSdkVersion. +bazelisk build --android_sdk=@androidsdk//:sdk-34 //binder:binder + GRADLE_FLAGS="-Pandroid.useAndroidX=true" ./gradlew \