From 5635bd26a514de4de7f076cc63493184bdc86b69 Mon Sep 17 00:00:00 2001 From: Ming-Chuan Lin Date: Mon, 11 Mar 2024 15:18:11 -0700 Subject: [PATCH] [Build] Migrate Android NDK, android rules and platforms This commit does the following 3 things for Android bazel rules, which depends on each other 1. Update NDK to 26.2.11394342 (and a few other Android things) 2. Use rules_android_ndk instead of builtin `native.android_ndk_repository` * `third_party/android/android_configure.bzl` was a workaround for users who don't set `$ANDROID_NDK_HOME` env var. Now with rules_android_ndk, we can declare repo without registering the toolchain. Instead users who need NDK toolchain should use `--extra_toolchains` to manually register the toolchain, as shown in README.md. 3. Migrate to platforms. See https://bazel.build/concepts/platforms * Currently we declares android platforms that is needed for binder transport APK. Later gRPC repo can gradually migrate to platforms for other platforms. * The value of `crosstool_top` will still be `//external:android/crosstool` (which is the default value), so existings android `config_settings` will still work. We should migrate them to match with `@platforms//os:android` constraint later. The platforms migration needs Bazel 7.0 to work so we also override bazel version in testing scripts. --- BUILD | 26 ++++++++ WORKSPACE | 31 +++++++--- .../binder/java/io/grpc/binder/cpp/README.md | 25 ++++---- .../io/grpc/binder/cpp/exampleclient/BUILD | 2 - .../io/grpc/binder/cpp/exampleserver/BUILD | 2 - .../binder/java/io/grpc/binder/cpp/BUILD | 2 - .../binder_transport_apk/Dockerfile.template | 33 +++++----- third_party/android/BUILD | 3 - third_party/android/android_configure.bzl | 62 ------------------- third_party/cares/cares.BUILD | 6 +- .../dockerimage_current_versions.bzl | 2 +- .../test/binder_transport_apk.current_version | 2 +- .../test/binder_transport_apk/Dockerfile | 23 ++++--- ...pc_binder_transport_apk_build_in_docker.sh | 14 ++--- 14 files changed, 108 insertions(+), 125 deletions(-) delete mode 100644 third_party/android/BUILD delete mode 100644 third_party/android/android_configure.bzl diff --git a/BUILD b/BUILD index 617bc1cf533750..f38f7c20e480da 100644 --- a/BUILD +++ b/BUILD @@ -65,6 +65,30 @@ bool_flag( build_setting_default = False, ) +platform( + name = "android_x86_64", + constraint_values = [ + "@platforms//os:android", + "@platforms//cpu:x86_64", + ], +) + +platform( + name = "android_arm64", + constraint_values = [ + "@platforms//os:android", + "@platforms//cpu:arm64", + ], +) + +platform( + name = "android_armv7", + constraint_values = [ + "@platforms//os:android", + "@platforms//cpu:armv7", + ], +) + config_setting( name = "grpc_no_rls_flag", flag_values = {":disable_grpc_rls": "true"}, @@ -84,6 +108,8 @@ config_setting( config_setting( name = "android", values = {"crosstool_top": "//external:android/crosstool"}, + # TODO: Use constraint_values to detect android after Bazel 7.0 platforms migration is finished + # constraint_values = [ "@platforms//os:android" ], ) config_setting( diff --git a/WORKSPACE b/WORKSPACE index 162e9a4e73bda8..b919672f3a295f 100644 --- a/WORKSPACE +++ b/WORKSPACE @@ -27,19 +27,34 @@ custom_exec_properties( load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive") http_archive( - name = "build_bazel_rules_android", - sha256 = "cd06d15dd8bb59926e4d65f9003bfc20f9da4b2519985c27e190cddc8b7a7806", - strip_prefix = "rules_android-0.1.1", - urls = ["https://github.com/bazelbuild/rules_android/archive/v0.1.1.zip"], + name = "platforms", + sha256 = "8150406605389ececb6da07cbcb509d5637a3ab9a24bc69b1101531367d89d74", + urls = ["https://github.com/bazelbuild/platforms/releases/download/0.0.8/platforms-0.0.8.tar.gz"], ) -load("//third_party/android:android_configure.bzl", "android_configure") +RULES_ANDROID_NDK_COMMIT = "010f4f17dd13a8baaaacc28ba6c8c2c75f54c68b" -android_configure(name = "local_config_android") +RULES_ANDROID_NDK_SHA = "2ab6a97748772f289331d75caaaee0593825935d1d9d982231a437fb8ab5a14d" -load("@local_config_android//:android_configure.bzl", "android_workspace") +http_archive( + name = "rules_android_ndk", + sha256 = RULES_ANDROID_NDK_SHA, + strip_prefix = "rules_android_ndk-%s" % RULES_ANDROID_NDK_COMMIT, + url = "https://github.com/bazelbuild/rules_android_ndk/archive/%s.zip" % RULES_ANDROID_NDK_COMMIT, +) + +android_sdk_repository( + name = "androidsdk", + build_tools_version = "34.0.0", +) + +load("@rules_android_ndk//:rules.bzl", "android_ndk_repository") + +android_ndk_repository(name = "androidndk") -android_workspace() +# Note that we intentionally avoid calling `register_toolchains("@androidndk//:all")` +# here, because the toolchain rule fails when $ANDROID_NDK_HOME is not set. +# Use `--extra_toolchains=@androidndk//:all` to manually register it when building for Android. # Prevents bazel's '...' expansion from including the following folder. # This is required because the BUILD file in the following folder diff --git a/examples/android/binder/java/io/grpc/binder/cpp/README.md b/examples/android/binder/java/io/grpc/binder/cpp/README.md index d0817c07d5e01c..dcbd97aa144709 100644 --- a/examples/android/binder/java/io/grpc/binder/cpp/README.md +++ b/examples/android/binder/java/io/grpc/binder/cpp/README.md @@ -1,20 +1,23 @@ # gRPC-core BinderTransport example apps -WIP. - ## Build Instruction -1. Install Android SDK and NDK. Currently we only support SDK version 30.0.3 and - NDK version 21.4.7075529 . Make sure you get these exact versions otherwise - Bazel might complain. - -2. Point environment variables to install locations of SDK and NDK +1. Install Android SDK and NDK. Only NDK version >= 25 is supported. We tested against SDK Platform `33` and NDK `26.2.11394342`. +2. Make sure Bazel is at least `7.0`. Use `export OVERRIDE_BAZEL_VERSION=7.0.0` to selected a supported version listed in `bazel/supported_versions.txt` if necessary. +3. Point environment variables to install locations of SDK and NDK + ``` + export ANDROID_HOME=$HOME/android-sdk + export ANDROID_NDK_HOME=$HOME/android-sdk/ndk/26.2.11394342 + ``` +4. To build a fat APK that supports `x86_64`, `armv7`, and `arm64`: ``` - export ANDROID_HOME=$HOME/Android/Sdk/ - export ANDROID_NDK_HOME=$HOME/Android/Sdk/ndk/21.4.7075529 + bazel build \ + --extra_toolchains=@androidndk//:all \ + --android_platforms=//:android_x86_64,//:android_armv7,//:android_arm64 \ + --copt=-Wno-unknown-warning-option \ + //examples/android/binder/java/io/grpc/binder/cpp/exampleserver:app \ + //examples/android/binder/java/io/grpc/binder/cpp/exampleclient:app ``` -3. `bazel build //examples/android/binder/java/io/grpc/binder/cpp/exampleclient:app` -4. `bazel build //examples/android/binder/java/io/grpc/binder/cpp/exampleserver:app` 5. `adb install bazel-bin/examples/android/binder/java/io/grpc/binder/cpp/exampleclient/app.apk` 6. `adb install diff --git a/examples/android/binder/java/io/grpc/binder/cpp/exampleclient/BUILD b/examples/android/binder/java/io/grpc/binder/cpp/exampleclient/BUILD index c21ea99f7c185e..8b11ebb383a4b0 100644 --- a/examples/android/binder/java/io/grpc/binder/cpp/exampleclient/BUILD +++ b/examples/android/binder/java/io/grpc/binder/cpp/exampleclient/BUILD @@ -12,8 +12,6 @@ # See the License for the specific language governing permissions and # limitations under the License. -load("@build_bazel_rules_android//android:rules.bzl", "android_binary", "android_library") - cc_library( name = "jni_lib", srcs = ["native.cc"], diff --git a/examples/android/binder/java/io/grpc/binder/cpp/exampleserver/BUILD b/examples/android/binder/java/io/grpc/binder/cpp/exampleserver/BUILD index 3c11762ab1aa23..b4e88ebc90ac19 100644 --- a/examples/android/binder/java/io/grpc/binder/cpp/exampleserver/BUILD +++ b/examples/android/binder/java/io/grpc/binder/cpp/exampleserver/BUILD @@ -12,8 +12,6 @@ # See the License for the specific language governing permissions and # limitations under the License. -load("@build_bazel_rules_android//android:rules.bzl", "android_binary", "android_library") - cc_library( name = "jni_lib", srcs = ["native.cc"], diff --git a/src/core/ext/transport/binder/java/io/grpc/binder/cpp/BUILD b/src/core/ext/transport/binder/java/io/grpc/binder/cpp/BUILD index cfdd74e4050923..4470e3de1d53c9 100644 --- a/src/core/ext/transport/binder/java/io/grpc/binder/cpp/BUILD +++ b/src/core/ext/transport/binder/java/io/grpc/binder/cpp/BUILD @@ -12,8 +12,6 @@ # See the License for the specific language governing permissions and # limitations under the License. -load("@build_bazel_rules_android//android:rules.bzl", "android_library") - licenses(["notice"]) android_library( diff --git a/templates/tools/dockerfile/test/binder_transport_apk/Dockerfile.template b/templates/tools/dockerfile/test/binder_transport_apk/Dockerfile.template index d7058936c8c484..5601967cd7ce09 100644 --- a/templates/tools/dockerfile/test/binder_transport_apk/Dockerfile.template +++ b/templates/tools/dockerfile/test/binder_transport_apk/Dockerfile.template @@ -19,26 +19,31 @@ #======================== # Java - RUN apt-get install -y openjdk-8-jdk + RUN apt-get install -y openjdk-21-jdk #======================== # Android SDK/NDK installation - ENV SDK_ROOT=/opt/android-sdk + ENV ANDROID_SDK_VERSION 11076708 + ENV ANDROID_NDK_VERSION 26.2.11394342 + + ENV SDK_ROOT /opt/android-sdk + RUN mkdir -p $SDK_ROOT - RUN wget -O cmd.zip dl.google.com/android/repository/commandlinetools-linux-7302050_latest.zip && \ - unzip cmd.zip && rm cmd.zip && \ - yes | ./cmdline-tools/bin/sdkmanager --sdk_root=$SDK_ROOT 'tools' && \ - yes | ./cmdline-tools/bin/sdkmanager --sdk_root=$SDK_ROOT 'platform-tools' && \ - yes | ./cmdline-tools/bin/sdkmanager --sdk_root=$SDK_ROOT 'build-tools;30.0.3' && \ - yes | ./cmdline-tools/bin/sdkmanager --sdk_root=$SDK_ROOT 'platforms;android-29' && \ - yes | ./cmdline-tools/bin/sdkmanager --sdk_root=$SDK_ROOT 'ndk-bundle' && \ - yes | ./cmdline-tools/bin/sdkmanager --sdk_root=$SDK_ROOT 'ndk;21.4.7075529' + RUN cd $SDK_ROOT && \ + wget -O cmd.zip https://dl.google.com/android/repository/commandlinetools-linux-${'${ANDROID_SDK_VERSION}'}_latest.zip && \ + unzip -q cmd.zip && \ + rm cmd.zip + + RUN yes | $SDK_ROOT/cmdline-tools/bin/sdkmanager --sdk_root=$SDK_ROOT --licenses # accept all licenses + + # This is not required but desirable to reduce the time to download and the chance of download failure. + RUN mkdir -p ~/.android && touch ~/.android/repositories.cfg + + RUN $SDK_ROOT/cmdline-tools/bin/sdkmanager --sdk_root=$SDK_ROOT "ndk;$ANDROID_NDK_VERSION" "platforms;android-33" "build-tools;34.0.0" # Set environment variables for Bazel rules - ENV ANDROID_HOME=/opt/android-sdk - ENV ANDROID_NDK_HOME=/opt/android-sdk/ndk/21.4.7075529 - - RUN mkdir -p /var/local/jenkins + ENV ANDROID_HOME $SDK_ROOT + ENV ANDROID_NDK_HOME $SDK_ROOT/ndk/$ANDROID_NDK_VERSION # Define the default command. CMD ["bash"] diff --git a/third_party/android/BUILD b/third_party/android/BUILD deleted file mode 100644 index 12a7f707152d39..00000000000000 --- a/third_party/android/BUILD +++ /dev/null @@ -1,3 +0,0 @@ -exports_files([ - "android_configure.bzl", -]) diff --git a/third_party/android/android_configure.bzl b/third_party/android/android_configure.bzl deleted file mode 100644 index 40e7f105deb049..00000000000000 --- a/third_party/android/android_configure.bzl +++ /dev/null @@ -1,62 +0,0 @@ -"""Repository rule for Android SDK and NDK autoconfiguration. - -This rule is a no-op unless the required android environment variables are set. -""" - -# Based on https://github.com/tensorflow/tensorflow/tree/34c03ed67692eb76cb3399cebca50ea8bcde064c/third_party/android -# Workaround for https://github.com/bazelbuild/bazel/issues/14260 - -_ANDROID_NDK_HOME = "ANDROID_NDK_HOME" -_ANDROID_SDK_HOME = "ANDROID_HOME" - -def _escape_for_windows(path): - """Properly escape backslashes for Windows. - - Ideally, we would do this conditionally, but there is seemingly no way to - determine whether or not this is being called from Windows. - """ - return path.replace("\\", "\\\\") - -def _android_autoconf_impl(repository_ctx): - sdk_home = repository_ctx.os.environ.get(_ANDROID_SDK_HOME) - ndk_home = repository_ctx.os.environ.get(_ANDROID_NDK_HOME) - - # version 31.0.0 won't work https://stackoverflow.com/a/68036845 - sdk_rule = "" - if sdk_home: - sdk_rule = """ - native.android_sdk_repository( - name="androidsdk", - path="{}", - build_tools_version="30.0.3", - ) -""".format(_escape_for_windows(sdk_home)) - - # Note that Bazel does not support NDK 22 yet, and Bazel 3.7.1 only - # supports up to API level 29 for NDK 21 - ndk_rule = "" - if ndk_home: - ndk_rule = """ - native.android_ndk_repository( - name="androidndk", - path="{}", - ) -""".format(_escape_for_windows(ndk_home)) - - if ndk_rule == "" and sdk_rule == "": - sdk_rule = "pass" - - repository_ctx.file("BUILD.bazel", "") - repository_ctx.file("android_configure.bzl", """ -def android_workspace(): - {} - {} - """.format(sdk_rule, ndk_rule)) - -android_configure = repository_rule( - implementation = _android_autoconf_impl, - environ = [ - _ANDROID_NDK_HOME, - _ANDROID_SDK_HOME, - ], -) diff --git a/third_party/cares/cares.BUILD b/third_party/cares/cares.BUILD index 5a008ed5ae8102..784daed1b6f77c 100644 --- a/third_party/cares/cares.BUILD +++ b/third_party/cares/cares.BUILD @@ -29,9 +29,9 @@ config_setting( # This just helps with the build for now. config_setting( name = "android", - values = { - "crosstool_top": "//external:android/crosstool", - }, + values = {"crosstool_top": "//external:android/crosstool"}, + # TODO: Use constraint_values to detect android after Bazel 7.0 platforms migration is finished + # constraint_values = [ "@platforms//os:android" ], ) # iOS is not officially supported through C++. diff --git a/tools/bazelify_tests/dockerimage_current_versions.bzl b/tools/bazelify_tests/dockerimage_current_versions.bzl index 70dcfc40ae5842..cb494fe0b7664a 100644 --- a/tools/bazelify_tests/dockerimage_current_versions.bzl +++ b/tools/bazelify_tests/dockerimage_current_versions.bzl @@ -90,7 +90,7 @@ DOCKERIMAGE_CURRENT_VERSIONS = { "tools/dockerfile/test/android_ndk.current_version": "docker://us-docker.pkg.dev/grpc-testing/testing-images-public/android_ndk@sha256:ab154ecb062af2111d2d3550c4d3da3384201d9893bbd37d49e8160fc34bc137", "tools/dockerfile/test/bazel.current_version": "docker://us-docker.pkg.dev/grpc-testing/testing-images-public/bazel@sha256:32bde2dcb2087f2a32afab59e4dfedf7e8c76a52c69881f63a239d311f0e5ecf", "tools/dockerfile/test/bazel_arm64.current_version": "docker://us-docker.pkg.dev/grpc-testing/testing-images-public/bazel_arm64@sha256:3b087387c44dee405c1b80d6ff50994e6d8e90a4ef67cc94b4291f1a29c0ef41", - "tools/dockerfile/test/binder_transport_apk.current_version": "docker://us-docker.pkg.dev/grpc-testing/testing-images-public/binder_transport_apk@sha256:bf60a187cd2ce1abe8b4f32ae6479040a72ca6aa789cd5ab509f60ceb37a41f9", + "tools/dockerfile/test/binder_transport_apk.current_version": "docker://us-docker.pkg.dev/grpc-testing/testing-images-public/binder_transport_apk@sha256:f89c50fcc991e98bc7a0a57cbf3712c642687235f1d7c8d29b91982103addc87", "tools/dockerfile/test/csharp_debian11_arm64.current_version": "docker://us-docker.pkg.dev/grpc-testing/testing-images-public/csharp_debian11_arm64@sha256:4d4bc5f15e03f3d3d8fd889670ecde2c66a2e4d2dd9db80733c05c1d90c8a248", "tools/dockerfile/test/csharp_debian11_x64.current_version": "docker://us-docker.pkg.dev/grpc-testing/testing-images-public/csharp_debian11_x64@sha256:b2e5c47d986312ea0850e2f2e696b45d23ee0aabceea161d31e28559e19ec4a5", "tools/dockerfile/test/cxx_alpine_x64.current_version": "docker://us-docker.pkg.dev/grpc-testing/testing-images-public/cxx_alpine_x64@sha256:f2019edf9f2afd5042567f11afb1aa78a789fc9acdcce5ee0c14cc11f6830ed7", diff --git a/tools/dockerfile/test/binder_transport_apk.current_version b/tools/dockerfile/test/binder_transport_apk.current_version index 439b81ec9dd5f0..f496f62ed5fc2d 100644 --- a/tools/dockerfile/test/binder_transport_apk.current_version +++ b/tools/dockerfile/test/binder_transport_apk.current_version @@ -1 +1 @@ -us-docker.pkg.dev/grpc-testing/testing-images-public/binder_transport_apk:783671f597502a2dc3ebf190d52d55be70836a33@sha256:bf60a187cd2ce1abe8b4f32ae6479040a72ca6aa789cd5ab509f60ceb37a41f9 \ No newline at end of file +us-docker.pkg.dev/grpc-testing/testing-images-public/binder_transport_apk:a91cd5248c83769f64075aa611cda58ed794f7e4@sha256:f89c50fcc991e98bc7a0a57cbf3712c642687235f1d7c8d29b91982103addc87 diff --git a/tools/dockerfile/test/binder_transport_apk/Dockerfile b/tools/dockerfile/test/binder_transport_apk/Dockerfile index c0644d3285b817..6e1bb5af9b8b19 100644 --- a/tools/dockerfile/test/binder_transport_apk/Dockerfile +++ b/tools/dockerfile/test/binder_transport_apk/Dockerfile @@ -60,19 +60,28 @@ RUN BAZEL_ARCH_SUFFIX="$(uname -m | sed s/aarch64/arm64/)" \ #======================== # Java -RUN apt-get install -y openjdk-8-jdk +RUN apt-get install -y openjdk-21-jdk #======================== # Android SDK/NDK installation -ENV SDK_ROOT=/opt/android-sdk +ENV ANDROID_SDK_VERSION 11076708 +ENV ANDROID_NDK_VERSION 26.2.11394342 + +ENV SDK_ROOT /opt/android-sdk + RUN mkdir -p $SDK_ROOT -RUN wget -O cmd.zip dl.google.com/android/repository/commandlinetools-linux-7302050_latest.zip && unzip cmd.zip && rm cmd.zip && yes | ./cmdline-tools/bin/sdkmanager --sdk_root=$SDK_ROOT 'tools' && yes | ./cmdline-tools/bin/sdkmanager --sdk_root=$SDK_ROOT 'platform-tools' && yes | ./cmdline-tools/bin/sdkmanager --sdk_root=$SDK_ROOT 'build-tools;30.0.3' && yes | ./cmdline-tools/bin/sdkmanager --sdk_root=$SDK_ROOT 'platforms;android-29' && yes | ./cmdline-tools/bin/sdkmanager --sdk_root=$SDK_ROOT 'ndk-bundle' && yes | ./cmdline-tools/bin/sdkmanager --sdk_root=$SDK_ROOT 'ndk;21.4.7075529' +RUN cd $SDK_ROOT && wget -O cmd.zip https://dl.google.com/android/repository/commandlinetools-linux-${ANDROID_SDK_VERSION}_latest.zip && unzip -q cmd.zip && rm cmd.zip -# Set environment variables for Bazel rules -ENV ANDROID_HOME=/opt/android-sdk -ENV ANDROID_NDK_HOME=/opt/android-sdk/ndk/21.4.7075529 +RUN yes | $SDK_ROOT/cmdline-tools/bin/sdkmanager --sdk_root=$SDK_ROOT --licenses # accept all licenses -RUN mkdir -p /var/local/jenkins +# This is not required but desirable to reduce the time to download and the chance of download failure. +RUN mkdir -p ~/.android && touch ~/.android/repositories.cfg + +RUN $SDK_ROOT/cmdline-tools/bin/sdkmanager --sdk_root=$SDK_ROOT "ndk;$ANDROID_NDK_VERSION" "platforms;android-33" "build-tools;34.0.0" + +# Set environment variables for Bazel rules +ENV ANDROID_HOME $SDK_ROOT +ENV ANDROID_NDK_HOME $SDK_ROOT/ndk/$ANDROID_NDK_VERSION # Define the default command. CMD ["bash"] diff --git a/tools/internal_ci/linux/grpc_binder_transport_apk_build_in_docker.sh b/tools/internal_ci/linux/grpc_binder_transport_apk_build_in_docker.sh index b92259cf4529ed..43e7be9c4695ac 100755 --- a/tools/internal_ci/linux/grpc_binder_transport_apk_build_in_docker.sh +++ b/tools/internal_ci/linux/grpc_binder_transport_apk_build_in_docker.sh @@ -18,19 +18,15 @@ set -ex echo $ANDROID_HOME echo $ANDROID_NDK_HOME -# Build all targets using the strict warning option which leverages the -# clang compiler to check if sources can pass a set of warning options. -# CPU are specified because gRPC does not build with 32bit NDK (which has socklen_t -# defined as int due to an accident). -# The python option is for disabling python2 enforcement when packing APK +# Android platforms only works with Bazel >= 7.0 +export OVERRIDE_BAZEL_VERSION=7.0.0 + python3 tools/run_tests/python_utils/bazel_report_helper.py --report_path bazel_binder_example_app bazel_binder_example_app/bazel_wrapper \ --bazelrc=tools/remote_build/include/test_locally_with_resultstore_results.bazelrc \ build \ - --define=use_strict_warning=true \ - --copt=-Wno-unknown-warning-option \ - --fat_apk_cpu=x86_64,arm64-v8a \ - --extra_toolchains=@rules_python//python:autodetecting_toolchain_nonstrict \ + --extra_toolchains=@androidndk//:all \ + --android_platforms=//:android_x86_64,//:android_armv7,//:android_arm64 \ //examples/android/binder/java/io/grpc/binder/cpp/exampleclient:app \ //examples/android/binder/java/io/grpc/binder/cpp/exampleserver:app