245 lines
9.2 KiB
Python
245 lines
9.2 KiB
Python
# Copyright 2020 The Bazel Authors. All rights reserved.
|
|
#
|
|
# 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.
|
|
|
|
"""Implementation."""
|
|
|
|
load("//rules:acls.bzl", "acls")
|
|
load("//rules:common.bzl", "common")
|
|
load("//rules:data_binding.bzl", "data_binding")
|
|
load("//rules:java.bzl", "java")
|
|
load(
|
|
"//rules:processing_pipeline.bzl",
|
|
"ProviderInfo",
|
|
"processing_pipeline",
|
|
)
|
|
load("//rules:resources.bzl", _resources = "resources")
|
|
load("//rules:utils.bzl", "compilation_mode", "get_android_toolchain", "utils")
|
|
load(
|
|
"//rules:native_deps.bzl",
|
|
_process_native_deps = "process",
|
|
)
|
|
|
|
def _process_manifest(ctx, **unused_ctxs):
|
|
manifest_ctx = _resources.bump_min_sdk(
|
|
ctx,
|
|
manifest = ctx.file.manifest,
|
|
floor = _resources.DEPOT_MIN_SDK_FLOOR if (_is_test_binary(ctx) and acls.in_enforce_min_sdk_floor_rollout(str(ctx.label))) else 0,
|
|
enforce_min_sdk_floor_tool = get_android_toolchain(ctx).enforce_min_sdk_floor_tool.files_to_run,
|
|
)
|
|
|
|
return ProviderInfo(
|
|
name = "manifest_ctx",
|
|
value = manifest_ctx,
|
|
)
|
|
|
|
def _process_resources(ctx, manifest_ctx, java_package, **unused_ctxs):
|
|
packaged_resources_ctx = _resources.package(
|
|
ctx,
|
|
assets = ctx.files.assets,
|
|
assets_dir = ctx.attr.assets_dir,
|
|
resource_files = ctx.files.resource_files,
|
|
manifest = manifest_ctx.processed_manifest,
|
|
manifest_values = utils.expand_make_vars(ctx, ctx.attr.manifest_values),
|
|
resource_configs = ctx.attr.resource_configuration_filters,
|
|
densities = ctx.attr.densities,
|
|
nocompress_extensions = ctx.attr.nocompress_extensions,
|
|
java_package = java_package,
|
|
compilation_mode = compilation_mode.get(ctx),
|
|
shrink_resources = ctx.attr.shrink_resources,
|
|
use_android_resource_shrinking = ctx.fragments.android.use_android_resource_shrinking,
|
|
use_android_resource_cycle_shrinking = ctx.fragments.android.use_android_resource_cycle_shrinking,
|
|
use_legacy_manifest_merger = use_legacy_manifest_merger(ctx),
|
|
should_throw_on_conflict = not acls.in_allow_resource_conflicts(str(ctx.label)),
|
|
enable_data_binding = ctx.attr.enable_data_binding,
|
|
enable_manifest_merging = ctx.attr._enable_manifest_merging,
|
|
deps = utils.dedupe_split_attr(ctx.split_attr.deps),
|
|
instruments = ctx.attr.instruments,
|
|
aapt = get_android_toolchain(ctx).aapt2.files_to_run,
|
|
android_jar = ctx.attr._android_sdk[AndroidSdkInfo].android_jar,
|
|
legacy_merger = ctx.attr._android_manifest_merge_tool.files_to_run,
|
|
xsltproc = ctx.attr._xsltproc_tool.files_to_run,
|
|
instrument_xslt = ctx.file._add_g3itr_xslt,
|
|
busybox = get_android_toolchain(ctx).android_resources_busybox.files_to_run,
|
|
host_javabase = ctx.attr._host_javabase,
|
|
)
|
|
return ProviderInfo(
|
|
name = "packaged_resources_ctx",
|
|
value = packaged_resources_ctx,
|
|
)
|
|
|
|
def _validate_manifest(ctx, packaged_resources_ctx, **unused_ctxs):
|
|
manifest_validation_ctx = _resources.validate_min_sdk(
|
|
ctx,
|
|
manifest = packaged_resources_ctx.processed_manifest,
|
|
floor = _resources.DEPOT_MIN_SDK_FLOOR if acls.in_enforce_min_sdk_floor_rollout(str(ctx.label)) else 0,
|
|
enforce_min_sdk_floor_tool = get_android_toolchain(ctx).enforce_min_sdk_floor_tool.files_to_run,
|
|
)
|
|
|
|
return ProviderInfo(
|
|
name = "manifest_validation_ctx",
|
|
value = manifest_validation_ctx,
|
|
)
|
|
|
|
def _process_native_libs(ctx, **_unusued_ctxs):
|
|
providers = []
|
|
if acls.in_android_binary_starlark_split_transition(str(ctx.label)):
|
|
providers.append(_process_native_deps(
|
|
ctx,
|
|
filename = "nativedeps",
|
|
))
|
|
return ProviderInfo(
|
|
name = "native_libs_ctx",
|
|
value = struct(providers = providers),
|
|
)
|
|
|
|
def _process_build_stamp(_unused_ctx, **_unused_ctxs):
|
|
return ProviderInfo(
|
|
name = "stamp_ctx",
|
|
value = struct(
|
|
resource_files = [],
|
|
deps = [],
|
|
java_info = None,
|
|
providers = [],
|
|
),
|
|
)
|
|
|
|
def _process_data_binding(ctx, java_package, packaged_resources_ctx, **_unused_ctxs):
|
|
if ctx.attr.enable_data_binding and not acls.in_databinding_allowed(str(ctx.label)):
|
|
fail("This target is not allowed to use databinding and enable_data_binding is True.")
|
|
return ProviderInfo(
|
|
name = "db_ctx",
|
|
value = data_binding.process(
|
|
ctx,
|
|
defines_resources = True,
|
|
enable_data_binding = ctx.attr.enable_data_binding,
|
|
java_package = java_package,
|
|
layout_info = packaged_resources_ctx.data_binding_layout_info,
|
|
artifact_type = "APPLICATION",
|
|
deps = utils.collect_providers(DataBindingV2Info, utils.dedupe_split_attr(ctx.split_attr.deps)),
|
|
data_binding_exec = get_android_toolchain(ctx).data_binding_exec.files_to_run,
|
|
data_binding_annotation_processor =
|
|
get_android_toolchain(ctx).data_binding_annotation_processor[JavaPluginInfo],
|
|
data_binding_annotation_template =
|
|
utils.only(get_android_toolchain(ctx).data_binding_annotation_template.files.to_list()),
|
|
),
|
|
)
|
|
|
|
def _process_jvm(ctx, db_ctx, packaged_resources_ctx, stamp_ctx, **_unused_ctxs):
|
|
native_name = ctx.label.name.removesuffix(common.PACKAGED_RESOURCES_SUFFIX)
|
|
java_info = java.compile_android(
|
|
ctx,
|
|
# Use the same format as the class jar from native android_binary.
|
|
# Some macros expect the class jar to be named like this.
|
|
ctx.actions.declare_file("%s/lib%s.jar" % (ctx.label.name, native_name)),
|
|
ctx.actions.declare_file(ctx.label.name + "-src.jar"),
|
|
srcs = ctx.files.srcs + db_ctx.java_srcs,
|
|
javac_opts = ctx.attr.javacopts + db_ctx.javac_opts,
|
|
r_java = packaged_resources_ctx.r_java,
|
|
enable_deps_without_srcs = True,
|
|
deps = utils.collect_providers(JavaInfo, utils.dedupe_split_attr(ctx.split_attr.deps) + stamp_ctx.deps),
|
|
plugins =
|
|
utils.collect_providers(JavaPluginInfo, ctx.attr.plugins) +
|
|
db_ctx.java_plugins,
|
|
annotation_processor_additional_outputs =
|
|
db_ctx.java_annotation_processor_additional_outputs,
|
|
annotation_processor_additional_inputs =
|
|
db_ctx.java_annotation_processor_additional_inputs,
|
|
strict_deps = "DEFAULT",
|
|
java_toolchain = common.get_java_toolchain(ctx),
|
|
)
|
|
java_info = java_common.add_constraints(
|
|
java_info,
|
|
constraints = ["android"],
|
|
)
|
|
|
|
providers = []
|
|
if acls.in_android_binary_starlark_javac(str(ctx.label)):
|
|
providers.append(java_info)
|
|
|
|
return ProviderInfo(
|
|
name = "jvm_ctx",
|
|
value = struct(
|
|
java_info = java_info,
|
|
providers = providers,
|
|
),
|
|
)
|
|
|
|
def use_legacy_manifest_merger(ctx):
|
|
"""Whether legacy manifest merging is enabled.
|
|
|
|
Args:
|
|
ctx: The context.
|
|
|
|
Returns:
|
|
Boolean indicating whether legacy manifest merging is enabled.
|
|
"""
|
|
manifest_merger = ctx.attr.manifest_merger
|
|
android_manifest_merger = ctx.fragments.android.manifest_merger
|
|
|
|
if android_manifest_merger == "force_android":
|
|
return False
|
|
if manifest_merger == "auto":
|
|
manifest_merger = android_manifest_merger
|
|
|
|
return manifest_merger == "legacy"
|
|
|
|
def finalize(ctx, providers, validation_outputs, **unused_ctxs):
|
|
providers.append(
|
|
OutputGroupInfo(
|
|
_validation = depset(validation_outputs),
|
|
),
|
|
)
|
|
return providers
|
|
|
|
def _is_test_binary(ctx):
|
|
"""Whether this android_binary target is a test binary.
|
|
|
|
Args:
|
|
ctx: The context.
|
|
|
|
Returns:
|
|
Boolean indicating whether the target is a test target.
|
|
"""
|
|
return ctx.attr.testonly or ctx.attr.instruments or str(ctx.label).find("/javatests/") >= 0
|
|
|
|
# Order dependent, as providers will not be available to downstream processors
|
|
# that may depend on the provider. Iteration order for a dictionary is based on
|
|
# insertion.
|
|
PROCESSORS = dict(
|
|
ManifestProcessor = _process_manifest,
|
|
StampProcessor = _process_build_stamp,
|
|
ResourceProcessor = _process_resources,
|
|
ValidateManifestProcessor = _validate_manifest,
|
|
NativeLibsProcessor = _process_native_libs,
|
|
DataBindingProcessor = _process_data_binding,
|
|
JvmProcessor = _process_jvm,
|
|
)
|
|
|
|
_PROCESSING_PIPELINE = processing_pipeline.make_processing_pipeline(
|
|
processors = PROCESSORS,
|
|
finalize = finalize,
|
|
)
|
|
|
|
def impl(ctx):
|
|
"""The rule implementation.
|
|
|
|
Args:
|
|
ctx: The context.
|
|
|
|
Returns:
|
|
A list of providers.
|
|
"""
|
|
java_package = java.resolve_package_from_label(ctx.label, ctx.attr.custom_package)
|
|
return processing_pipeline.run(ctx, java_package, _PROCESSING_PIPELINE)
|