# 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:bootclasspath.bzl", "bootclasspath") load("//build/bazel/rules/java:java_system_modules.bzl", "java_system_modules") load("//build/bazel/rules/java:import.bzl", "java_import") load("//build/bazel/rules/java:versions.bzl", "java_versions") load("//prebuilts/sdk:utils.bzl", "prebuilt_sdk_utils") load("@bazel_tools//tools/jdk:default_java_toolchain.bzl", "DEFAULT_JAVACOPTS", "default_java_toolchain") load("//build/bazel/rules/common:api.bzl", "api") load("//build/bazel/rules/common:sdk_version.bzl", "sdk_version") load("@soong_injection//java_toolchain:constants.bzl", "constants") load("//build/bazel/rules/java/sdk:config_setting_names.bzl", sdk_config_setting = "config_setting_names") load("//build/bazel/rules/java/errorprone:errorprone.bzl", "errorprone_global_flags") # //prebuilts/sdk/current is a package, but the numbered directories under //prebuilts/sdk/ are not. def _prebuilt_path_prefix(kind, api_level): common_prefix = "//prebuilts/sdk" if api_level == api.FUTURE_API_LEVEL: return "%s/current:%s" % (common_prefix, prebuilt_sdk_utils.to_kind_dir(kind)) return "%s:%s/%s" % (common_prefix, api_level, prebuilt_sdk_utils.to_kind_dir(kind)) def _core_system_module_name(kind, api_level): return "%s_%s_core_system_module" % (kind, api_level) def _android_jar_import_name(kind, api_level): return "%s_%s_android_jar" % (kind, api_level) def _android_jar_file_name(kind, api_level): return "%s/android.jar" % _prebuilt_path_prefix(kind, api_level) _SDK_PACKAGE_PREFIX = "//build/bazel/rules/java/sdk:" _JAVA_PACKAGE_PREFIX = "//build/bazel/rules/java:" def prebuilts_toolchain(java_toolchain_name, android_sdk_toolchain_name): """Creates a device java and android toolchain and their dependencies. Defines all java_import, java_system_modules, and bootclasspath targets that enable building java/android/kotlin targets against a prebuilt SDK. Defines config settings at the proper granularity (based on java version and sdk version), and the mappings between config setting and proper toolchain attributes. """ java_version_select_dict = { _JAVA_PACKAGE_PREFIX + setting: str(version) for version, setting in java_versions.VERSION_TO_CONFIG_SETTING.items() } bootclasspath_select_dict = { _SDK_PACKAGE_PREFIX + sdk_config_setting.SDK_NONE: [], } # android_jar_select_dict and framework_aidl_select_dict are only used by the android # toolchain. We should never be in a situation where sdk_version = "none" and we're trying to # build an android_* target, but: # 1. a Bazel check enforces that every toolchain attribute resolves under every # configuration, and # 2. the DexArchiveAspect can propagate to java_host_for_device dependencies, and # tries to access an android.jar from there (b/278596841). # We should map "none" to an explicitly failing target to address 1, but until 2 is resolved, # we point to the public current artifacts. android_jar_select_dict = { _SDK_PACKAGE_PREFIX + sdk_config_setting.SDK_NONE: _android_jar_file_name( sdk_version.KIND_PUBLIC, api.FUTURE_API_LEVEL, ), # ":failed_android.jar", } framework_aidl_select_dict = { _SDK_PACKAGE_PREFIX + sdk_config_setting.SDK_NONE: "%s/framework.aidl" % ( _prebuilt_path_prefix( prebuilt_sdk_utils.to_aidl_kind(sdk_version.KIND_PUBLIC, api.FUTURE_API_LEVEL), api.FUTURE_API_LEVEL, ) ), # ":failed_framework.aidl", } for api_level in prebuilt_sdk_utils.API_LEVELS: for kind in prebuilt_sdk_utils.available_core_kinds_for_api_level(api_level): java_import( name = "%s_%s_core_jar" % (kind, api_level), jars = ["%s/core-for-system-modules.jar" % _prebuilt_path_prefix(kind, api_level)], ) java_system_modules( name = _core_system_module_name(kind, api_level), deps = [":%s_%s_core_jar" % (kind, api_level)], ) for kind in prebuilt_sdk_utils.available_kinds_for_api_level(api_level): java_import( name = _android_jar_import_name(kind, api_level), jars = [_android_jar_file_name(kind, api_level)], ) config_setting = _SDK_PACKAGE_PREFIX + sdk_config_setting.kind_api(kind, api_level) android_jar_select_dict[config_setting] = _android_jar_file_name( kind, api_level, ) framework_aidl_select_dict[config_setting] = "%s/framework.aidl" % ( _prebuilt_path_prefix( prebuilt_sdk_utils.to_aidl_kind(kind, api_level), api_level, ) ) if java_versions.supports_pre_java_9(api_level): config_setting = _SDK_PACKAGE_PREFIX + sdk_config_setting.kind_api_pre_java_9(kind, api_level) bootclasspath_select_dict[config_setting] = [_gen_bootclasspath( pre_java_9 = True, kind = kind, api_level = api_level, )] if java_versions.supports_post_java_9(api_level): config_setting = _SDK_PACKAGE_PREFIX + sdk_config_setting.kind_api_post_java_9(kind, api_level) bootclasspath_select_dict[config_setting] = [_gen_bootclasspath( pre_java_9 = False, kind = kind, api_level = api_level, )] default_java_toolchain( name = java_toolchain_name, bootclasspath = select(bootclasspath_select_dict), source_version = select(java_version_select_dict), target_version = select(java_version_select_dict), # TODO(b/218720643): Support switching between multiple JDKs. java_runtime = "//prebuilts/jdk/jdk17:jdk17_runtime", toolchain_definition = False, misc = errorprone_global_flags + DEFAULT_JAVACOPTS + constants.CommonJdkFlags + select({ _SDK_PACKAGE_PREFIX + sdk_config_setting.SDK_NONE: ["--system=none"], "//conditions:default": [], }), ) native.android_sdk( name = android_sdk_toolchain_name, aapt = "//prebuilts/sdk/tools:linux/bin/aapt", aapt2 = "//prebuilts/sdk/tools:linux/bin/aapt2", adb = ":fail", # TODO: use system/core/adb ? aidl = "//prebuilts/sdk/tools:linux/bin/aidl", android_jar = select(android_jar_select_dict), apksigner = ":apksigner", dx = "//prebuilts/sdk/tools:dx", # TODO: add D8 framework_aidl = select(framework_aidl_select_dict), main_dex_classes = "//prebuilts/sdk/tools:mainDexClasses.rules", main_dex_list_creator = ":fail", proguard = ":fail", # TODO: add R8 system = select({ key: bootclasspath_select_dict[key][0] for key in bootclasspath_select_dict.keys() if "none" not in key } | {"//conditions:default": ":failed_bootclasspath"}), shrinked_android_jar = select(android_jar_select_dict), visibility = ["//visibility:public"], zipalign = "//prebuilts/sdk/tools:linux/bin/zipalign", ) def _gen_bootclasspath(pre_java_9, kind, api_level): bootclasspath_name = "toolchain_%s_java_9_android_%s_%s_bootclasspath" % ("pre" if pre_java_9 else "post", kind, api_level) auxiliary = [_android_jar_import_name(kind, api_level)] bootclasspath_attr = [_android_jar_import_name(kind, api_level), ":core_lambda_stubs"] system = None if pre_java_9: auxiliary = auxiliary + [":core_lambda_stubs"] else: system = _core_system_module_name(prebuilt_sdk_utils.to_core_kind(kind, api_level), api_level) bootclasspath( name = bootclasspath_name, auxiliary = auxiliary, bootclasspath = bootclasspath_attr, system = system, ) return bootclasspath_name