diff options
author | Romain Jobredeaux <jobredeaux@google.com> | 2023-04-13 22:32:39 +0000 |
---|---|---|
committer | Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com> | 2023-04-13 22:32:39 +0000 |
commit | e9fd6a5a795a84bf4646312a50025fe371f66850 (patch) | |
tree | e5c7021a1959668d38705068a5565a1cee602097 | |
parent | 01e228f8892bc1ddb8e2a4ce39343b5b697c5f4d (diff) | |
parent | 2501a71e551842b11347269e6fa7e5d9201765a9 (diff) | |
download | bazel-e9fd6a5a795a84bf4646312a50025fe371f66850.tar.gz |
Merge "Support sdk_version for java/android/kotlin targets." am: 85aa6aa91a am: 50fae7ed6c am: 2501a71e55
Original change: https://android-review.googlesource.com/c/platform/build/bazel/+/2517835
Change-Id: I15588b011592a8959202bd54412c20f184566231
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
30 files changed, 790 insertions, 72 deletions
diff --git a/bazel.WORKSPACE b/bazel.WORKSPACE index a07436e7..d0fe5d7b 100644 --- a/bazel.WORKSPACE +++ b/bazel.WORKSPACE @@ -65,12 +65,8 @@ local_repository( register_toolchains( "//prebuilts/build-tools:py_toolchain", - # For Starlark Android rules - "//prebuilts/sdk:android_default_toolchain", - "//prebuilts/sdk:android_sdk_tools", - - # For native android_binary - "//prebuilts/sdk:android_sdk_tools_for_native_android_binary", + # For Android rules + "//prebuilts/sdk:all", # For APEX rules "//build/bazel/rules/apex:all", @@ -138,7 +134,10 @@ local_repository( path = "build/bazel/rules/java/rules_java", ) -register_toolchains("//prebuilts/jdk/jdk17:all") +register_toolchains( + "//prebuilts/jdk/jdk17:runtime_toolchain_definition", + "//build/bazel/rules/java:jdk17_host_toolchain_java_definition", +) local_repository( name = "kotlin_maven_interface", diff --git a/ci/bp2build.sh b/ci/bp2build.sh index 0353552f..24b3d10f 100755 --- a/ci/bp2build.sh +++ b/ci/bp2build.sh @@ -43,6 +43,13 @@ host_targets+=( "${HOST_ONLY_TEST_TARGETS[@]}" ) build_for_host ${host_targets[@]} +######################################################################### +# Check that rule wrappers have the same providers as the rules they wrap +######################################################################### + +source "$(dirname $0)/../rules/java/wrapper_test.sh" +test_wrapper_providers + ################### # bp2build progress ################### diff --git a/ci/target_lists.sh b/ci/target_lists.sh index 268666d8..ecfbe6e6 100644 --- a/ci/target_lists.sh +++ b/ci/target_lists.sh @@ -29,9 +29,8 @@ BUILD_TARGETS=( -//external/e2fsprogs/resize:all -//external/e2fsprogs/debugfs:all -//external/e2fsprogs/e2fsck:all - - # TODO(b/215230098): remove after handling sdk_version for aidl - -//frameworks/av:av-types-aidl-java + # TODO(b/277616982): These modules depend on private java APIs, but maybe they don't need to. + -//external/ow2-asm:all # TODO(b/266459895): remove these after re-enabling libunwindstack -//bionic/libc/malloc_debug:libc_malloc_debug @@ -53,6 +52,7 @@ BUILD_TARGETS=( TEST_TARGETS=( //build/bazel/... //prebuilts/clang/host/linux-x86:all + //prebuilts/sdk:toolchains_have_all_prebuilts ) HOST_ONLY_TEST_TARGETS=( @@ -72,3 +72,20 @@ HOST_INCOMPATIBLE_TARGETS=( -//packages/modules/adb:all -//packages/modules/adb/pairing_connection:all ) + +# These targets are used to ensure that the aosp-specific rule wrappers forward +# all providers of the underlying rule. +EXAMPLE_WRAPPER_TARGETS=( + # java_import wrapper + //build/bazel/examples/java/com/bazel:hello_java_import + # java_library wrapper + //build/bazel/examples/java/com/bazel:hello_java_lib + # kt_jvm_library wrapper + //build/bazel/examples/java/com/bazel:some_kotlin_lib + # android_library wrapper + //build/bazel/examples/android_app/java/com/app:applib + # android_binary wrapper + //build/bazel/examples/android_app/java/com/app:app + # aar_import wrapper + //build/bazel/examples/android_app/java/com/app:import +) diff --git a/common.bazelrc b/common.bazelrc index f71c5e52..70371f5b 100644 --- a/common.bazelrc +++ b/common.bazelrc @@ -84,6 +84,7 @@ try-import %workspace%/user.bazelrc build --experimental_output_directory_naming_scheme=diff_against_baseline common --experimental_google_legacy_api build --android_sdk=//prebuilts/sdk:android_sdk +build --incompatible_enable_android_toolchain_resolution common --experimental_enable_android_migration_apis common --incompatible_java_common_parameters build --android_databinding_use_v3_4_args @@ -91,8 +92,6 @@ build --experimental_android_databinding_v2 build --define=android_incremental_dexing_tool=d8_dexbuilder build --define=android_dexmerger_tool=d8_dexmerger build --nouse_workers_with_dexbuilder -# TODO(b/240761789): This flag should be abandoned in favor of platform/toolchain resolution. -build --fat_apk_cpu=k8 # TODO(b/199038020): Use a python_toolchain when we have Starlark rules_python. # This also means all python scripts are using py3 runtime. diff --git a/examples/android_app/java/com/app/BUILD b/examples/android_app/java/com/app/BUILD index 5bb21391..8522e0cc 100644 --- a/examples/android_app/java/com/app/BUILD +++ b/examples/android_app/java/com/app/BUILD @@ -1,10 +1,27 @@ -load("//build/bazel/rules/android:rules.bzl", "android_binary", "android_library") +# Copyright (C) 2023 The Android Open Source Project +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +load("//build/bazel/rules/android:rules.bzl", "aar_import", "android_binary", "android_library") load("//build/bazel/rules/cc:cc_library_shared.bzl", "cc_library_shared") load("//build/bazel/rules/cc:cc_library_static.bzl", "cc_library_static") +package(default_applicable_licenses = ["//build/soong/licenses:Android-Apache-2.0"]) + android_binary( name = "app", manifest = "AndroidManifest.xml", + sdk_version = "current", target_compatible_with = ["//build/bazel/platforms/os:android"], deps = [ ":applib", @@ -15,6 +32,7 @@ android_binary( name = "app-cert-string", certificate_name = "platform", manifest = "AndroidManifest.xml", + sdk_version = "current", target_compatible_with = ["//build/bazel/platforms/os:android"], deps = [ ":applib", @@ -25,6 +43,7 @@ android_binary( name = "app-cert-module", certificate = "//build/make/target/product/security:aosp-testkey", manifest = "AndroidManifest.xml", + sdk_version = "current", target_compatible_with = ["//build/bazel/platforms/os:android"], deps = [ ":applib", @@ -40,6 +59,7 @@ android_library( ], manifest = "AndroidManifest.xml", resource_files = glob(["res/**"]), + sdk_version = "current", target_compatible_with = ["//build/bazel/platforms/os:android"], deps = [ # TODO(b/240555494): re-enable JNI when it is supported @@ -51,6 +71,7 @@ android_library( android_library( name = "lib", srcs = ["Lib.java"], + sdk_version = "current", target_compatible_with = ["//build/bazel/platforms/os:android"], ) @@ -66,3 +87,10 @@ cc_library_static( hdrs = ["jni_dep.h"], deps = ["//libnativehelper:jni_headers"], ) + +aar_import( + name = "import", + aar = "example_lib.aar", + sdk_version = "32", + target_compatible_with = ["//build/bazel/platforms/os:android"], +) diff --git a/examples/android_app/java/com/app/example_lib.aar b/examples/android_app/java/com/app/example_lib.aar Binary files differnew file mode 100644 index 00000000..05000e19 --- /dev/null +++ b/examples/android_app/java/com/app/example_lib.aar diff --git a/examples/java/com/bazel/BUILD.bazel b/examples/java/com/bazel/BUILD.bazel index fead57dc..5b3e2f69 100644 --- a/examples/java/com/bazel/BUILD.bazel +++ b/examples/java/com/bazel/BUILD.bazel @@ -1,11 +1,49 @@ +# Copyright (C) 2023 The Android Open Source Project +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +load("//build/bazel/rules/java:rules.bzl", "java_binary", "java_import", "java_library") +load("//build/bazel/rules/kotlin:rules.bzl", "kt_jvm_library") + +package(default_applicable_licenses = ["//build/soong/licenses:Android-Apache-2.0"]) + java_binary( name = "hello_java", srcs = ["example/HelloWorld.java"], main_class = "com.bazel.example.HelloWorld", - deps = [":hello_java_lib"], + target_compatible_with = select({ + "//build/bazel/platforms/os:android": ["@platforms//:incompatible"], + "//conditions:default": [], + }), + deps = [ + ":hello_java_lib", + ":some_kotlin_lib", + ], ) java_library( name = "hello_java_lib", srcs = ["example_lib/HelloLib.java"], + sdk_version = "current", +) + +java_import( + name = "hello_java_import", + jars = ["hello_java_import.jar"], +) + +kt_jvm_library( + name = "some_kotlin_lib", + srcs = ["example_lib/SomeKotlin.kt"], + sdk_version = "current", ) diff --git a/examples/java/com/bazel/example_lib/SomeKotlin.kt b/examples/java/com/bazel/example_lib/SomeKotlin.kt new file mode 100644 index 00000000..e7577e4b --- /dev/null +++ b/examples/java/com/bazel/example_lib/SomeKotlin.kt @@ -0,0 +1,18 @@ +/** + * Copyright (C) 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.bazel.example_lib + +class SomeKotlin diff --git a/examples/java/com/bazel/hello_java_import.jar b/examples/java/com/bazel/hello_java_import.jar Binary files differnew file mode 100755 index 00000000..5c460075 --- /dev/null +++ b/examples/java/com/bazel/hello_java_import.jar diff --git a/rules/android/aar_import.bzl b/rules/android/aar_import.bzl new file mode 100644 index 00000000..e93a821f --- /dev/null +++ b/rules/android/aar_import.bzl @@ -0,0 +1,75 @@ +# Copyright (C) 2023 The Android Open Source Project +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""Macro wrapping the aar_import for bp2build. """ + +load("@rules_android//rules:rules.bzl", _aar_import = "aar_import") +load("//build/bazel/rules/java:sdk_transition.bzl", "sdk_transition", "sdk_transition_attrs") + +# TODO(b/277801336): document these attributes. +def aar_import( + name = "", + aar = [], + sdk_version = None, + deps = [], + tags = [], + target_compatible_with = [], + visibility = None, + **kwargs): + lib_name = name + "_private" + _aar_import( + name = lib_name, + aar = aar, + deps = deps, + tags = tags + ["manual"], + target_compatible_with = target_compatible_with, + visibility = ["//visibility:private"], + **kwargs + ) + + aar_import_sdk_transition( + name = name, + sdk_version = sdk_version, + java_version = None, + exports = lib_name, + tags = tags, + target_compatible_with = target_compatible_with, + visibility = visibility, + ) + +# The list of providers to forward was determined using cquery on one +# of the example targets listed under EXAMPLE_WRAPPER_TARGETS at +# //build/bazel/ci/target_lists.sh. It may not be exhaustive. A unit +# test ensures that the wrapper's providers and the wrapped rule's do +# match. +def _aar_import_sdk_transition_impl(ctx): + return [ + ctx.attr.exports[0][AndroidLibraryResourceClassJarProvider], + ctx.attr.exports[0][JavaInfo], + ctx.attr.exports[0][AndroidNativeLibsInfo], + ctx.attr.exports[0][ProguardSpecProvider], + ctx.attr.exports[0][AndroidIdeInfo], + ctx.attr.exports[0][DefaultInfo], + ] + +aar_import_sdk_transition = rule( + implementation = _aar_import_sdk_transition_impl, + attrs = sdk_transition_attrs, + provides = [ + AndroidIdeInfo, + AndroidLibraryResourceClassJarProvider, + AndroidNativeLibsInfo, + JavaInfo, + ], +) diff --git a/rules/android/android_binary.bzl b/rules/android/android_binary.bzl index 1b30efd7..64465a15 100644 --- a/rules/android/android_binary.bzl +++ b/rules/android/android_binary.bzl @@ -20,7 +20,9 @@ load( ) load("android_app_certificate.bzl", "android_app_certificate_with_default_cert") load("android_app_keystore.bzl", "android_app_keystore") +load("//build/bazel/rules/java:sdk_transition.bzl", "sdk_transition", "sdk_transition_attrs") +# TODO(b/277801336): document these attributes. def _android_binary_helper(**attrs): """ Duplicates the logic in top-level android_binary macro in rules_android/rules/android_binary.bzl but uses @@ -51,6 +53,11 @@ def android_binary( name, certificate = None, certificate_name = None, + sdk_version = None, + java_version = None, + tags = [], + target_compatible_with = [], + visibility = None, **kwargs): """ android_binary macro wrapper that handles custom attrs needed in AOSP Bazel macro to find and create a keystore to use for debug_signing_keys @@ -91,8 +98,50 @@ def android_binary( debug_signing_keys.append(app_keystore_name) + bin_name = name + "_private" _android_binary_helper( - name = name, + name = bin_name, debug_signing_keys = debug_signing_keys, + target_compatible_with = target_compatible_with, + tags = tags + ["manual"], + visibility = ["//visibility:private"], **kwargs ) + + android_binary_sdk_transition( + name = name, + sdk_version = sdk_version, + java_version = java_version, + exports = bin_name, + tags = tags, + target_compatible_with = target_compatible_with, + visibility = visibility, + ) + +# The list of providers to forward was determined using cquery on one +# of the example targets listed under EXAMPLE_WRAPPER_TARGETS at +# //build/bazel/ci/target_lists.sh. It may not be exhaustive. A unit +# test ensures that the wrapper's providers and the wrapped rule's do +# match. +def _android_binary_sdk_transition_impl(ctx): + return struct( + android = ctx.attr.exports[0].android, + JavaGenJarsProvider = ctx.attr.exports[0][JavaInfo].annotation_processing, + providers = [ + ctx.attr.exports[0][AndroidIdlInfo], + ctx.attr.exports[0][InstrumentedFilesInfo], + ctx.attr.exports[0][DataBindingV2Info], + ctx.attr.exports[0][JavaInfo], + ctx.attr.exports[0][AndroidIdeInfo], + ctx.attr.exports[0][ApkInfo], + ctx.attr.exports[0][AndroidPreDexJarInfo], + ctx.attr.exports[0][AndroidFeatureFlagSet], + ctx.attr.exports[0][OutputGroupInfo], + ctx.attr.exports[0][DefaultInfo], + ], + ) + +android_binary_sdk_transition = rule( + implementation = _android_binary_sdk_transition_impl, + attrs = sdk_transition_attrs, +) diff --git a/rules/android/android_library.bzl b/rules/android/android_library.bzl index 99f4f0f3..514cc4df 100644 --- a/rules/android/android_library.bzl +++ b/rules/android/android_library.bzl @@ -1,14 +1,110 @@ +# Copyright (C) 2023 The Android Open Source Project +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + """android_library rule.""" +load("//build/bazel/rules/java:sdk_transition.bzl", "sdk_transition", "sdk_transition_attrs") load( "//build/bazel/rules/android/android_library_aosp_internal:rule.bzl", "android_library_aosp_internal_macro", ) +load("@rules_android//rules:providers.bzl", "StarlarkAndroidResourcesInfo") -def android_library(**attrs): +# TODO(b/277801336): document these attributes. +def android_library( + name, + sdk_version = None, + java_version = None, + tags = [], + target_compatible_with = [], + visibility = None, + **attrs): """ android_library macro wrapper that handles custom attrs needed in AOSP Args: + name: the wrapper rule name. + sdk_version: string representing which sdk_version to build against. See + //build/bazel/rules/common/sdk_version.bzl for formatting and semantics. + java_version: string representing which version of java the java code in this rule should be + built with. + tags, target_compatible_with and visibility have Bazel's traditional semantics. **attrs: Rule attributes """ - android_library_aosp_internal_macro(**attrs) + lib_name = name + "_private" + android_library_aosp_internal_macro( + name = lib_name, + tags = tags + ["manual"], + target_compatible_with = target_compatible_with, + visibility = ["//visibility:private"], + **attrs + ) + + android_library_sdk_transition( + aar = name + ".aar", + name = name, + sdk_version = sdk_version, + java_version = java_version, + exports = lib_name, + tags = tags, + target_compatible_with = target_compatible_with, + visibility = visibility, + ) + +# The list of providers to forward was determined using cquery on one +# of the example targets listed under EXAMPLE_WRAPPER_TARGETS at +# //build/bazel/ci/target_lists.sh. It may not be exhaustive. A unit +# test ensures that the wrapper's providers and the wrapped rule's do +# match. +def _android_library_sdk_transition_impl(ctx): + ctx.actions.symlink( + output = ctx.outputs.aar, + target_file = ctx.attr.exports[0][AndroidIdeInfo].aar, + ) + + providers = [] + if AndroidLibraryAarInfo in ctx.attr.exports[0]: + providers.append(ctx.attr.exports[0][AndroidLibraryAarInfo]) + return struct( + android = ctx.attr.exports[0].android, + java = ctx.attr.exports[0].java, + providers = providers + [ + ctx.attr.exports[0][StarlarkAndroidResourcesInfo], + ctx.attr.exports[0][AndroidLibraryResourceClassJarProvider], + ctx.attr.exports[0][AndroidIdlInfo], + ctx.attr.exports[0][DataBindingV2Info], + ctx.attr.exports[0][JavaInfo], + ctx.attr.exports[0][ProguardSpecProvider], + ctx.attr.exports[0][AndroidProguardInfo], + ctx.attr.exports[0][AndroidNativeLibsInfo], + ctx.attr.exports[0][AndroidCcLinkParamsInfo], + ctx.attr.exports[0][AndroidIdeInfo], + ctx.attr.exports[0][InstrumentedFilesInfo], + ctx.attr.exports[0][Actions], + ctx.attr.exports[0][OutputGroupInfo], + ctx.attr.exports[0][DefaultInfo], + ], + ) + +android_library_sdk_transition = rule( + implementation = _android_library_sdk_transition_impl, + attrs = sdk_transition_attrs | {"aar": attr.output()}, + provides = [ + AndroidCcLinkParamsInfo, + AndroidIdeInfo, + AndroidIdlInfo, + AndroidLibraryResourceClassJarProvider, + AndroidNativeLibsInfo, + JavaInfo, + ], +) diff --git a/rules/android/rules.bzl b/rules/android/rules.bzl index 23c37074..43b794d5 100644 --- a/rules/android/rules.bzl +++ b/rules/android/rules.bzl @@ -15,7 +15,7 @@ """Starlark rules for building Android apps.""" load( - "@rules_android//rules:rules.bzl", + ":aar_import.bzl", _aar_import = "aar_import", ) load( diff --git a/rules/common/sdk_version.bzl b/rules/common/sdk_version.bzl index 7b853762..33f2f61c 100644 --- a/rules/common/sdk_version.bzl +++ b/rules/common/sdk_version.bzl @@ -17,18 +17,25 @@ load("//build/bazel/rules/common:api.bzl", "api") # Only scopes that are available in prebuilts (and "none") are listed # here for now, but the list should eventually match Soong's SdkKind # enum. -ALL_KINDS = [ - "public", - "system", - "test", - "system_server", - "module", - "core", - "none", +_KIND_PUBLIC = "public" +_KIND_SYSTEM = "system" +_KIND_TEST = "test" +_KIND_SYSTEM_SERVER = "system_server" +_KIND_MODULE = "module" +_KIND_CORE = "core" +_KIND_NONE = "none" +_ALL_KINDS = [ + _KIND_PUBLIC, + _KIND_SYSTEM, + _KIND_TEST, + _KIND_SYSTEM_SERVER, + _KIND_MODULE, + _KIND_CORE, + _KIND_NONE, ] # Starlark implementation of SdkSpecFrom at https://cs.android.com/android/platform/build/soong/+/master:android/sdk_version.go;l=248-299;drc=69f4218c4feaeca953237cd9e76a9a8cc423d3e3. -def sdk_spec_from(sdk_version): +def _sdk_spec_from(sdk_version): """Parses an sdk_version string into kind and api_level. Args: @@ -49,17 +56,29 @@ def sdk_spec_from(sdk_version): if sdk_version == "core_platform": fail("Only prebuilt SDK versions are available, sdk_version core_platform is not yet supported.") if sdk_version == "none": - return struct(kind = "none", api_level = api.NONE_API_LEVEL) + return struct(kind = _KIND_NONE, api_level = api.NONE_API_LEVEL) if type(sdk_version) != type(""): fail("sdk_version must be a string") sep_index = sdk_version.rfind("_") api_level_string = sdk_version if sep_index < 0 else sdk_version[sep_index + 1:] api_level = api.parse_api_level_from_version(api_level_string) - kind = "public" if sep_index == -1 else sdk_version[:sep_index] - if kind not in ALL_KINDS: + kind = _KIND_PUBLIC if sep_index == -1 else sdk_version[:sep_index] + if kind not in _ALL_KINDS: fail("kind %s parsed from sdk_version %s must be one of %s" % ( kind, sdk_version, - ",".join(ALL_KINDS), + ",".join(_ALL_KINDS), )) return struct(kind = kind, api_level = api_level) + +sdk_version = struct( + KIND_PUBLIC = _KIND_PUBLIC, + KIND_SYSTEM = _KIND_SYSTEM, + KIND_TEST = _KIND_TEST, + KIND_SYSTEM_SERVER = _KIND_SYSTEM_SERVER, + KIND_MODULE = _KIND_MODULE, + KIND_CORE = _KIND_CORE, + KIND_NONE = _KIND_NONE, + ALL_KINDS = _ALL_KINDS, + sdk_spec_from = _sdk_spec_from, +) diff --git a/rules/common/sdk_version_test.bzl b/rules/common/sdk_version_test.bzl index f751fe2a..b22c63d4 100644 --- a/rules/common/sdk_version_test.bzl +++ b/rules/common/sdk_version_test.bzl @@ -13,7 +13,7 @@ # limitations under the License. load("@bazel_skylib//lib:unittest.bzl", "analysistest", "asserts") -load("//build/bazel/rules/common:sdk_version.bzl", "sdk_spec_from") +load("//build/bazel/rules/common:sdk_version.bzl", "sdk_version") load("//build/bazel/rules/common:api.bzl", "api") # Warning: this is a *lot* of boilerplate to test just one function. @@ -22,7 +22,7 @@ load("//build/bazel/rules/common:api.bzl", "api") SdkSpec = provider() def _sdk_spec_from_tester_impl(ctx): - sdk_spec = sdk_spec_from(ctx.attr.sdk_version) + sdk_spec = sdk_version.sdk_spec_from(ctx.attr.sdk_version) return [SdkSpec(kind = sdk_spec.kind, api_level = sdk_spec.api_level)] sdk_spec_from_tester = rule( diff --git a/rules/java/BUILD b/rules/java/BUILD index edfc9f19..763713c9 100644 --- a/rules/java/BUILD +++ b/rules/java/BUILD @@ -23,6 +23,8 @@ load(":versions.bzl", "java_versions") load(":sdk_transition_test.bzl", "sdk_transition_test_suite") load(":host_for_device_test.bzl", "host_for_device_test_suite") load("@bazel_skylib//rules:common_settings.bzl", "string_setting") +load("@bazel_tools//tools/jdk:default_java_toolchain.bzl", "DEFAULT_JAVACOPTS", "default_java_toolchain") +load("@soong_injection//java_toolchain:constants.bzl", "constants") package( default_visibility = ["//visibility:public"], @@ -50,12 +52,12 @@ string_setting( [ config_setting( - name = java_versions.VERSION_TO_CONFIG_SETTING[java_version], + name = setting, flag_values = { "//build/bazel/rules/java:version": str(java_version), }, ) - for java_version in java_versions.VERSION_TO_CONFIG_SETTING.keys() + for java_version, setting in java_versions.VERSION_TO_CONFIG_SETTING.items() ] # There is no need for both host and device java version build settings in a @@ -75,10 +77,36 @@ string_setting( [ config_setting( - name = "host_" + java_versions.VERSION_TO_CONFIG_SETTING[java_version], + name = "host_" + setting, flag_values = { "//build/bazel/rules/java:host_version": str(java_version), }, ) - for java_version in java_versions.VERSION_TO_CONFIG_SETTING.keys() + for java_version, setting in java_versions.VERSION_TO_CONFIG_SETTING.items() ] + +java_version_select_dict = { + "host_" + setting: str(version) + for version, setting in java_versions.VERSION_TO_CONFIG_SETTING.items() +} | { + "//conditions:default": str(java_versions.get_version()), +} + +default_java_toolchain( + name = "jdk17_host_toolchain_java", + # TODO(b/218720643): Support switching between multiple JDKs. + java_runtime = "//prebuilts/jdk/jdk17:jdk17_runtime", + misc = DEFAULT_JAVACOPTS + constants.CommonJdkFlags, + source_version = select(java_version_select_dict), + target_version = select(java_version_select_dict), + toolchain_definition = False, +) + +toolchain( + name = "jdk17_host_toolchain_java_definition", + exec_compatible_with = ["//build/bazel/platforms/os:linux"], + target_compatible_with = ["//build/bazel/platforms/os:linux"], + target_settings = [], + toolchain = ":jdk17_host_toolchain_java", + toolchain_type = "@bazel_tools//tools/jdk:toolchain_type", +) diff --git a/rules/java/host_for_device.bzl b/rules/java/host_for_device.bzl index a5fea20c..9d7990a1 100644 --- a/rules/java/host_for_device.bzl +++ b/rules/java/host_for_device.bzl @@ -20,7 +20,7 @@ visibility([ ]) def _host_for_device_impl(ctx): - return [java_common.merge([d[JavaInfo] for d in ctx.attr.deps])] + return [java_common.merge([d[JavaInfo] for d in ctx.attr.exports])] java_host_for_device = rule( doc = """Rule to provide java libraries built with a host classpath in a device configuration. @@ -28,7 +28,9 @@ This is rarely necessary and restricted to a few allowed projects. """, implementation = _host_for_device_impl, attrs = { - "deps": attr.label_list( + # This attribute must have a specific name to let the DexArchiveAspect propagate + # through it. + "exports": attr.label_list( cfg = "exec", providers = [JavaInfo], doc = "List of targets whose contents will be visible to targets that depend on this target.", diff --git a/rules/java/host_for_device_test.bzl b/rules/java/host_for_device_test.bzl index cfc8812f..5585bad9 100644 --- a/rules/java/host_for_device_test.bzl +++ b/rules/java/host_for_device_test.bzl @@ -26,8 +26,8 @@ Platform = provider( ) def _host_for_device_tester_aspect_impl(target, ctx): - if ctx.rule.attr.deps and len(ctx.rule.attr.deps) > 0 and Platform in ctx.rule.attr.deps[0]: - return ctx.rule.attr.deps[0][Platform] + if ctx.rule.attr.exports and len(ctx.rule.attr.exports) > 0 and Platform in ctx.rule.attr.exports[0]: + return ctx.rule.attr.exports[0][Platform] return Platform( platform = ctx.fragments.platform.platform, host_platform = ctx.fragments.platform.host_platform, @@ -35,7 +35,7 @@ def _host_for_device_tester_aspect_impl(target, ctx): host_for_device_tester_aspect = aspect( implementation = _host_for_device_tester_aspect_impl, - attr_aspects = ["deps"], + attr_aspects = ["exports"], fragments = ["platform"], provides = [Platform], ) @@ -57,7 +57,7 @@ host_for_device_dep_runs_in_exec_config_test = analysistest.make( def test_host_for_device(name): java_host_for_device( name = name + "_parent", - deps = [name + "_child"], + exports = [name + "_child"], tags = ["manual"], ) java_import( diff --git a/rules/java/import.bzl b/rules/java/import.bzl new file mode 100644 index 00000000..6770c5f0 --- /dev/null +++ b/rules/java/import.bzl @@ -0,0 +1,67 @@ +# Copyright (C) 2023 The Android Open Source Project +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""Macro wrapping the java_import for bp2build. """ + +load("@rules_java//java:defs.bzl", _java_import = "java_import") +load("//build/bazel/rules/java:sdk_transition.bzl", "sdk_transition", "sdk_transition_attrs") + +# TODO(b/277801336): document these attributes. +def java_import( + name = "", + jars = [], + deps = [], + tags = [], + target_compatible_with = [], + visibility = None, + **kwargs): + lib_name = name + "_private" + _java_import( + name = lib_name, + jars = jars, + deps = deps, + tags = tags + ["manual"], + target_compatible_with = target_compatible_with, + visibility = ["//visibility:private"], + **kwargs + ) + + java_import_sdk_transition( + name = name, + sdk_version = "none", + java_version = None, + exports = lib_name, + tags = tags, + target_compatible_with = target_compatible_with, + visibility = visibility, + ) + +# The list of providers to forward was determined using cquery on one +# of the example targets listed under EXAMPLE_WRAPPER_TARGETS at +# //build/bazel/ci/target_lists.sh. It may not be exhaustive. A unit +# test ensures that the wrapper's providers and the wrapped rule's do +# match. +def _java_import_sdk_transition_impl(ctx): + return [ + ctx.attr.exports[0][JavaInfo], + ctx.attr.exports[0][ProguardSpecProvider], + ctx.attr.exports[0][OutputGroupInfo], + ctx.attr.exports[0][DefaultInfo], + ] + +java_import_sdk_transition = rule( + implementation = _java_import_sdk_transition_impl, + attrs = sdk_transition_attrs, + provides = [JavaInfo], +) diff --git a/rules/java/java_aidl_library.bzl b/rules/java/java_aidl_library.bzl index d2dbfac0..94fd8c5c 100644 --- a/rules/java/java_aidl_library.bzl +++ b/rules/java/java_aidl_library.bzl @@ -13,6 +13,7 @@ # limitations under the License. load("//build/bazel/rules/aidl:aidl_library.bzl", "AidlGenInfo", "aidl_file_utils") +load("//build/bazel/rules/java:sdk_transition.bzl", "sdk_transition") JavaAidlAspectInfo = provider("JavaAidlAspectInfo", fields = ["jars"]) @@ -20,7 +21,7 @@ def _java_aidl_gen_aspect_impl(target, ctx): aidl_gen_java_files = aidl_file_utils.generate_aidl_bindings(ctx, "java", target[AidlGenInfo]) java_deps = [ d[JavaInfo] - for d in ctx.rule.attr.deps + ctx.attr._sdk_dependency + for d in ctx.rule.attr.deps ] out_jar = ctx.actions.declare_file(target.label.name + "-aidl-gen.jar") java_info = java_common.compile( @@ -48,15 +49,6 @@ _java_aidl_gen_aspect = aspect( cfg = "exec", default = Label("//prebuilts/build-tools:linux-x86/bin/aidl"), ), - "_sdk_dependency": attr.label_list( - default = [ - # TODO(b/215230098) remove forced dependency on current public android.jar - "//prebuilts/sdk:system_current_android_sdk_java_import", - # TODO(b/229251008) remove hard-coded dependency on framework-connectivity - "//prebuilts/sdk:current_module_lib_framework_connectivity", - ], - providers = [JavaInfo], - ), }, toolchains = ["@bazel_tools//tools/jdk:toolchain_type"], fragments = ["java"], @@ -80,9 +72,19 @@ def _java_aidl_library_rule_impl(ctx): java_aidl_library = rule( implementation = _java_aidl_library_rule_impl, attrs = { + # This attribute's name lets the DexArchiveAspect propagate + # through it. It should be changed carefully. "deps": attr.label_list( providers = [AidlGenInfo], aspects = [_java_aidl_gen_aspect], + cfg = sdk_transition, + ), + "java_version": attr.string(), + "sdk_version": attr.string( + default = "system_current", + ), + "_allowlist_function_transition": attr.label( + default = "@bazel_tools//tools/allowlists/function_transition_allowlist", ), }, provides = [JavaInfo], diff --git a/rules/java/library.bzl b/rules/java/library.bzl index b273464d..f381b1c2 100644 --- a/rules/java/library.bzl +++ b/rules/java/library.bzl @@ -18,10 +18,63 @@ load( "@rules_java//java:defs.bzl", _java_library = "java_library", ) +load("//build/bazel/rules/java:sdk_transition.bzl", "sdk_transition", "sdk_transition_attrs") -def java_library(name = "", srcs = [], deps = [], javacopts = [], **kwargs): - # Disable the error prone check of HashtableContains by default. See https://errorprone.info/bugpattern/HashtableContains - # HashtableContains error is reported when compiling //external/bouncycastle:bouncycastle-bcpkix-unbundled +# TODO(b/277801336): document these attributes. +def java_library( + name = "", + srcs = [], + deps = [], + javacopts = [], + sdk_version = None, + java_version = None, + tags = [], + target_compatible_with = [], + visibility = None, + **kwargs): + lib_name = name + "_private" + + # Disable the error prone check of HashtableContains by default. See https://errorprone.info/bugpattern/HashtableContains + # HashtableContains error is reported when compiling //external/bouncycastle:bouncycastle-bcpkix-unbundled opts = ["-Xep:HashtableContains:OFF"] + javacopts - _java_library(name = name, srcs = srcs, deps = deps, javacopts = opts, **kwargs) + _java_library( + name = lib_name, + srcs = srcs, + deps = deps, + javacopts = opts, + tags = tags + ["manual"], + target_compatible_with = target_compatible_with, + visibility = ["//visibility:private"], + **kwargs + ) + + java_library_sdk_transition( + name = name, + sdk_version = sdk_version, + java_version = java_version, + exports = lib_name, + tags = tags, + target_compatible_with = target_compatible_with, + visibility = ["//visibility:public"], + ) + +# The list of providers to forward was determined using cquery on one +# of the example targets listed under EXAMPLE_WRAPPER_TARGETS at +# //build/bazel/ci/target_lists.sh. It may not be exhaustive. A unit +# test ensures that the wrapper's providers and the wrapped rule's do +# match. +def _java_library_sdk_transition_impl(ctx): + return [ + ctx.attr.exports[0][JavaInfo], + ctx.attr.exports[0][InstrumentedFilesInfo], + ctx.attr.exports[0][ProguardSpecProvider], + ctx.attr.exports[0][OutputGroupInfo], + ctx.attr.exports[0][DefaultInfo], + ] + +java_library_sdk_transition = rule( + implementation = _java_library_sdk_transition_impl, + attrs = sdk_transition_attrs, + provides = [JavaInfo], +) diff --git a/rules/java/proto.bzl b/rules/java/proto.bzl index 16bb379c..68533d20 100644 --- a/rules/java/proto.bzl +++ b/rules/java/proto.bzl @@ -13,7 +13,7 @@ # limitations under the License. load("//build/bazel/rules:proto_file_utils.bzl", "proto_file_utils") -load(":library.bzl", "java_library") +load(":rules.bzl", "java_library") def _java_proto_sources_gen_rule_impl(ctx): out_flags = [] @@ -98,6 +98,7 @@ def _java_proto_library( plugin = None, out_format = None, proto_dep = None, + sdk_version = "core_current", **kwargs): proto_sources_name = name + "_proto_gen" @@ -118,6 +119,7 @@ def _java_proto_library( name = name, srcs = [proto_sources_name], deps = deps, + sdk_version = sdk_version, **kwargs ) diff --git a/rules/java/rules.bzl b/rules/java/rules.bzl index 881d44df..575321b2 100644 --- a/rules/java/rules.bzl +++ b/rules/java/rules.bzl @@ -17,7 +17,7 @@ load( _java_binary = "java_binary", ) load( - "@rules_java//java:defs.bzl", + "//build/bazel/rules/java:import.bzl", _java_import = "java_import", ) load( diff --git a/rules/java/sdk/BUILD.bazel b/rules/java/sdk/BUILD.bazel index f04685bd..b00ba819 100644 --- a/rules/java/sdk/BUILD.bazel +++ b/rules/java/sdk/BUILD.bazel @@ -17,16 +17,96 @@ package( ) load("@bazel_skylib//rules:common_settings.bzl", "int_setting", "string_setting") -load("//build/bazel/rules/common:sdk_version.bzl", "ALL_KINDS") +load("//build/bazel/rules/common:sdk_version.bzl", "sdk_version") load("//build/bazel/rules/common:api.bzl", "api") +load("//build/bazel/rules/java:versions.bzl", "java_versions") +load(":config_setting_names.bzl", "config_setting_names") +load("@bazel_skylib//lib:selects.bzl", "selects") +load("//prebuilts/sdk:utils.bzl", "prebuilt_sdk_utils") string_setting( name = "kind", - build_setting_default = "public", - values = ALL_KINDS, + build_setting_default = sdk_version.KIND_PUBLIC, + values = sdk_version.ALL_KINDS, ) int_setting( name = "api_level", build_setting_default = api.FUTURE_API_LEVEL, ) + +# The settings below are used to properly define a device java and android toolchain. + +# The SDK_NONE config setting maps to sdk_version = "none". In this configuration the java toolchain +# will provide nothing on the bootclasspath, not even the standard java.* libraries. +# The android toolchain is undefined in this configuration. +config_setting( + name = config_setting_names.SDK_NONE, + flag_values = { + "//build/bazel/rules/java/sdk:kind": sdk_version.KIND_NONE, + }, +) + +# Pre and Post Java 9 configs differ in how the bootclasspath is constructed and what arguments must +# be passed to javac. Pre Java 9, the SDK is passed as a whole to the --bootclasspath argument of +# javac. Post Java 9, the SDK is split between core libraries, passed using system modules and the +# --system javac argument, and the rest, added at the beginning of the classpath. +selects.config_setting_group( + name = config_setting_names.PRE_JAVA_9, + match_any = [ + "//build/bazel/rules/java:" + java_versions.VERSION_TO_CONFIG_SETTING[version] + for version in java_versions.VERSION_TO_CONFIG_SETTING.keys() + if version < 9 + ], +) + +selects.config_setting_group( + name = config_setting_names.POST_JAVA_9, + match_any = [ + "//build/bazel/rules/java:" + java_versions.VERSION_TO_CONFIG_SETTING[version] + for version in java_versions.VERSION_TO_CONFIG_SETTING.keys() + if version >= 9 + ], +) + +# Specific configuration at a given kind and api level will have the java and android toolchains +# pointed to the proper android.jar and framework.aidl files. +[ + config_setting( + name = config_setting_names.kind_api(kind, api_level), + flag_values = { + "//build/bazel/rules/java/sdk:kind": kind, + "//build/bazel/rules/java/sdk:api_level": str(api_level), + }, + ) + for api_level in prebuilt_sdk_utils.API_LEVELS + for kind in prebuilt_sdk_utils.available_kinds_for_api_level(api_level) +] + +# The bootclasspath is a function of sdk kind, api level, and whether building for pre or post java +# 9 sources. +[ + selects.config_setting_group( + name = config_setting_names.kind_api_pre_java_9(kind, api_level), + match_all = [ + config_setting_names.kind_api(kind, api_level), + config_setting_names.PRE_JAVA_9, + ], + ) + for api_level in prebuilt_sdk_utils.API_LEVELS + for kind in prebuilt_sdk_utils.available_kinds_for_api_level(api_level) + if java_versions.supports_pre_java_9(api_level) +] + +[ + selects.config_setting_group( + name = config_setting_names.kind_api_post_java_9(kind, api_level), + match_all = [ + config_setting_names.kind_api(kind, api_level), + config_setting_names.POST_JAVA_9, + ], + ) + for api_level in prebuilt_sdk_utils.API_LEVELS + for kind in prebuilt_sdk_utils.available_kinds_for_api_level(api_level) + if java_versions.supports_post_java_9(api_level) +] diff --git a/rules/java/sdk/config_setting_names.bzl b/rules/java/sdk/config_setting_names.bzl new file mode 100644 index 00000000..2150465f --- /dev/null +++ b/rules/java/sdk/config_setting_names.bzl @@ -0,0 +1,35 @@ +# Copyright (C) 2023 The Android Open Source Project +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +def _kind_api(kind, api_level): + return "config_setting_android_%s_%s" % (kind, api_level) + +def _kind_api_pre_java_9(kind, api_level): + return _kind_api(kind, api_level) + "_pre_java_9" + +def _kind_api_post_java_9(kind, api_level): + return _kind_api(kind, api_level) + "_post_java_9" + +_CONFIG_SETTING_SDK_NONE = "config_setting_sdk_none" +_CONFIG_SETTING_PRE_JAVA_9 = "config_setting_pre_java_9" +_CONFIG_SETTING_POST_JAVA_9 = "config_setting_post_java_9" + +config_setting_names = struct( + SDK_NONE = _CONFIG_SETTING_SDK_NONE, + PRE_JAVA_9 = _CONFIG_SETTING_PRE_JAVA_9, + POST_JAVA_9 = _CONFIG_SETTING_POST_JAVA_9, + kind_api = _kind_api, + kind_api_pre_java_9 = _kind_api_pre_java_9, + kind_api_post_java_9 = _kind_api_post_java_9, +) diff --git a/rules/java/sdk_transition.bzl b/rules/java/sdk_transition.bzl index efe41265..7f69d09d 100644 --- a/rules/java/sdk_transition.bzl +++ b/rules/java/sdk_transition.bzl @@ -13,7 +13,7 @@ # limitations under the License. load("//build/bazel/rules/java:versions.bzl", "java_versions") -load("//build/bazel/rules/common:sdk_version.bzl", "sdk_spec_from") +load("//build/bazel/rules/common:sdk_version.bzl", "sdk_version") load("//build/bazel/rules/common:api.bzl", "api") def _sdk_transition_impl(settings, attr): @@ -27,10 +27,10 @@ def _sdk_transition_impl(settings, attr): return { "//build/bazel/rules/java:version": default_java_version, "//build/bazel/rules/java:host_version": str(java_versions.get_version(attr.java_version)), - "//build/bazel/rules/java/sdk:kind": "none", + "//build/bazel/rules/java/sdk:kind": sdk_version.KIND_NONE, "//build/bazel/rules/java/sdk:api_level": api.NONE_API_LEVEL, } - sdk_spec = sdk_spec_from(attr.sdk_version) + sdk_spec = sdk_version.sdk_spec_from(attr.sdk_version) java_version = str(java_versions.get_version(attr.java_version, sdk_spec.api_level)) return { @@ -53,3 +53,16 @@ sdk_transition = transition( "//build/bazel/rules/java/sdk:api_level", ], ) + +sdk_transition_attrs = { + # This attribute must have a specific name to let the DexArchiveAspect propagate + # through it. + "exports": attr.label( + cfg = sdk_transition, + ), + "java_version": attr.string(), + "sdk_version": attr.string(), + "_allowlist_function_transition": attr.label( + default = "@bazel_tools//tools/allowlists/function_transition_allowlist", + ), +} diff --git a/rules/java/sdk_transition_test.bzl b/rules/java/sdk_transition_test.bzl index 5c36ea45..6dd90441 100644 --- a/rules/java/sdk_transition_test.bzl +++ b/rules/java/sdk_transition_test.bzl @@ -27,8 +27,8 @@ SdkConfig = provider( ) def _sdk_transition_tester_impl(ctx): - if ctx.attr.deps and len(ctx.attr.deps) > 0 and SdkConfig in ctx.attr.deps[0]: - return ctx.attr.deps[0][SdkConfig] + if ctx.attr.exports and len(ctx.attr.exports) > 0 and SdkConfig in ctx.attr.exports[0]: + return ctx.attr.exports[0][SdkConfig] return SdkConfig( java_version = ctx.attr._java_version_config_setting[BuildSettingInfo].value, host_java_version = ctx.attr._host_java_version_config_setting[BuildSettingInfo].value, @@ -39,7 +39,7 @@ def _sdk_transition_tester_impl(ctx): sdk_transition_tester = rule( implementation = _sdk_transition_tester_impl, attrs = { - "deps": attr.label( + "exports": attr.label( cfg = sdk_transition, providers = [SdkConfig], ), @@ -126,7 +126,7 @@ def set_up_targets_under_test(name, java_version, sdk_version): name = name + "_parent", java_version = java_version, sdk_version = sdk_version, - deps = name + "_child", + exports = name + "_child", tags = ["manual"], ) sdk_transition_tester( diff --git a/rules/java/versions.bzl b/rules/java/versions.bzl index a449bfc4..acee980e 100644 --- a/rules/java/versions.bzl +++ b/rules/java/versions.bzl @@ -59,6 +59,18 @@ def _compatible_versions_for_api_level(api_level): ] return _ALL_VERSIONS +def _supports_pre_java_9(api_level): + return any([ + version < 9 + for version in _compatible_versions_for_api_level(api_level) + ]) + +def _supports_post_java_9(api_level): + return any([ + version >= 9 + for version in _compatible_versions_for_api_level(api_level) + ]) + _NORMALIZED_VERSIONS = { "1.7": 7, "7": 7, @@ -87,5 +99,6 @@ java_versions = struct( VERSION_TO_CONFIG_SETTING = _VERSION_TO_CONFIG_SETTING, compatible_versions_for_api_level = _compatible_versions_for_api_level, get_version = _get_version, - default_version = _default_version, + supports_pre_java_9 = _supports_pre_java_9, + supports_post_java_9 = _supports_post_java_9, ) diff --git a/rules/java/wrapper_test.sh b/rules/java/wrapper_test.sh new file mode 100644 index 00000000..abab4214 --- /dev/null +++ b/rules/java/wrapper_test.sh @@ -0,0 +1,38 @@ +#!/bin/bash -eux + +# Copyright (C) 2023 The Android Open Source Project +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +if [[ ! -d "build/bazel/ci" ]]; then + echo "Please run this script from TOP". + exit 1 +fi + +source "build/bazel/ci/build_with_bazel.sh" +source "build/bazel/ci/target_lists.sh" + +function test_wrapper_providers() { + for target in ${EXAMPLE_WRAPPER_TARGETS[@]}; do + private_providers="$(build/bazel/bin/bazel ${STARTUP_FLAGS[@]} \ + cquery ${FLAGS[@]} --config=android "${target}_private" \ + --starlark:expr="sorted(providers(target).keys())" --output=starlark|uniq)" + wrapper_providers="$(build/bazel/bin/bazel ${STARTUP_FLAGS[@]} \ + cquery ${FLAGS[@]} --config=android "${target}" \ + --starlark:expr="sorted(providers(target).keys())" --output=starlark|uniq)" + if [[ ! $(cmp -s <(echo "${private_providers}") <(echo "${wrapper_providers}")) ]]; then + echo "${target} and ${target}_private should have the same providers. Diff:" + diff <(echo "${private_providers}") <(echo "${wrapper_providers}") + fi + done +} diff --git a/rules/kotlin/kt_jvm_library.bzl b/rules/kotlin/kt_jvm_library.bzl index 84f4431f..c181fa9d 100644 --- a/rules/kotlin/kt_jvm_library.bzl +++ b/rules/kotlin/kt_jvm_library.bzl @@ -17,6 +17,7 @@ limitations under the License. load("@rules_kotlin//kotlin:compiler_opt.bzl", "kt_compiler_opt") load("@rules_kotlin//kotlin:jvm_library.bzl", _kt_jvm_library = "kt_jvm_library") load("//build/bazel/rules/java:rules.bzl", "java_import") +load("//build/bazel/rules/java:sdk_transition.bzl", "sdk_transition", "sdk_transition_attrs") def _kotlin_resources_impl(ctx): output_file = ctx.actions.declare_file("kt_resources.jar") @@ -58,15 +59,20 @@ kotlin_resources = rule( }, ) +# TODO(b/277801336): document these attributes. def kt_jvm_library( name, deps = None, resources = None, resource_strip_prefix = None, kotlincflags = None, + java_version = None, + sdk_version = None, + tags = [], + target_compatible_with = [], + visibility = None, **kwargs): "Bazel macro wrapping for kt_jvm_library" - if resource_strip_prefix != None: java_import_name = name + "resources" kt_res_jar_name = name + "resources_jar" @@ -92,9 +98,43 @@ def kt_jvm_library( ) custom_kotlincopts = [":" + ktcopts_name] + lib_name = name + "_private" _kt_jvm_library( - name = name, + name = lib_name, deps = deps, custom_kotlincopts = custom_kotlincopts, + tags = tags + ["manual"], + target_compatible_with = target_compatible_with, + visibility = ["//visibility:private"], **kwargs ) + + kt_jvm_library_sdk_transition( + name = name, + sdk_version = sdk_version, + java_version = java_version, + exports = lib_name, + tags = tags, + target_compatible_with = target_compatible_with, + visibility = visibility, + ) + +# The list of providers to forward was determined using cquery on one +# of the example targets listed under EXAMPLE_WRAPPER_TARGETS at +# //build/bazel/ci/target_lists.sh. It may not be exhaustive. A unit +# test ensures that the wrapper's providers and the wrapped rule's do +# match. +def _kt_jvm_library_sdk_transition_impl(ctx): + return [ + ctx.attr.exports[0][JavaInfo], + ctx.attr.exports[0][InstrumentedFilesInfo], + ctx.attr.exports[0][ProguardSpecProvider], + ctx.attr.exports[0][OutputGroupInfo], + ctx.attr.exports[0][DefaultInfo], + ] + +kt_jvm_library_sdk_transition = rule( + implementation = _kt_jvm_library_sdk_transition_impl, + attrs = sdk_transition_attrs, + provides = [JavaInfo], +) |