You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
287 lines
10 KiB
287 lines
10 KiB
# Copyright 2018 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.
|
|
|
|
"""Bazel Android Data Binding."""
|
|
|
|
load(":utils.bzl", _utils = "utils")
|
|
|
|
# Data Binding context attributes.
|
|
_JAVA_ANNOTATION_PROCESSOR_ADDITIONAL_INPUTS = \
|
|
"java_annotation_processor_additional_inputs"
|
|
_JAVA_ANNOTATION_PROCESSOR_ADDITIONAL_OUTPUTS = \
|
|
"java_annotation_processor_additional_outputs"
|
|
_JAVA_PLUGINS = "java_plugins"
|
|
_JAVA_SRCS = "java_srcs"
|
|
_JAVAC_OPTS = "javac_opts"
|
|
_PROVIDERS = "providers"
|
|
|
|
DataBindingContextInfo = provider(
|
|
doc = "Contains data from processing Android Data Binding.",
|
|
fields = {
|
|
_JAVA_ANNOTATION_PROCESSOR_ADDITIONAL_INPUTS: (
|
|
"Additional inputs required by the Java annotation processor."
|
|
),
|
|
_JAVA_ANNOTATION_PROCESSOR_ADDITIONAL_OUTPUTS: (
|
|
"Additional outputs produced by the Java annotation processor."
|
|
),
|
|
_JAVA_PLUGINS: "Data Binding Java annotation processor",
|
|
_JAVA_SRCS: "Java sources required by the Java annotation processor.",
|
|
_JAVAC_OPTS: (
|
|
"Additional Javac opts required by the Java annotation processor."
|
|
),
|
|
_PROVIDERS: "The list of all providers to propagate.",
|
|
},
|
|
)
|
|
|
|
# Path used when resources have not been defined.
|
|
_NO_RESOURCES_PATH = "/tmp/no_resources"
|
|
|
|
def _copy_annotation_file(ctx, output_dir, annotation_template):
|
|
annotation_out = ctx.actions.declare_file(
|
|
output_dir + "/android/databinding/layouts/DataBindingInfo.java",
|
|
)
|
|
_utils.copy_file(ctx, annotation_template, annotation_out)
|
|
return annotation_out
|
|
|
|
def _gen_sources(ctx, output_dir, java_package, deps, data_binding_exec):
|
|
layout_info = ctx.actions.declare_file(output_dir + "layout-info.zip")
|
|
class_info = ctx.actions.declare_file(output_dir + "class-info.zip")
|
|
srcjar = ctx.actions.declare_file(output_dir + "baseClassSrc.srcjar")
|
|
|
|
args = ctx.actions.args()
|
|
args.add("-layoutInfoFiles", layout_info)
|
|
args.add("-package", java_package)
|
|
args.add("-classInfoOut", class_info)
|
|
args.add("-sourceOut", srcjar)
|
|
args.add("-zipSourceOutput", "true")
|
|
args.add("-useAndroidX", "false")
|
|
|
|
class_infos = []
|
|
for info in deps:
|
|
class_infos.extend(info.class_infos)
|
|
args.add_all(class_infos, before_each = "-dependencyClassInfoList")
|
|
|
|
ctx.actions.run(
|
|
executable = data_binding_exec,
|
|
arguments = ["GEN_BASE_CLASSES", args],
|
|
inputs = class_infos + [layout_info],
|
|
outputs = [class_info, srcjar],
|
|
mnemonic = "GenerateDataBindingBaseClasses",
|
|
progress_message = (
|
|
"GenerateDataBindingBaseClasses %s" % class_info.short_path
|
|
),
|
|
)
|
|
return srcjar, class_info, layout_info
|
|
|
|
def _setup_dependent_lib_artifacts(ctx, output_dir, deps):
|
|
# DataBinding requires files in very specific locations.
|
|
# The following expand_template (copy actions) are moving the files
|
|
# to the correct locations.
|
|
dep_lib_artifacts = []
|
|
for info in deps:
|
|
# Yes, DataBinding requires depsets iterations.
|
|
for artifact in (info.transitive_br_files.to_list() +
|
|
info.setter_stores +
|
|
info.class_infos):
|
|
# short_path might contain a parent directory reference if the
|
|
# databinding artifact is from an external repository (e.g. an aar
|
|
# from Maven). If that's the case, just remove the parent directory
|
|
# reference, otherwise the "dependent-lib-artifacts" directory will
|
|
# get removed by the "..".
|
|
path = artifact.short_path
|
|
if path.startswith("../"):
|
|
path = path[3:]
|
|
dep_lib_artifact = ctx.actions.declare_file(
|
|
output_dir + "dependent-lib-artifacts/" + path,
|
|
)
|
|
|
|
# Copy file to a location required by the DataBinding annotation
|
|
# processor.
|
|
# TODO(djwhang): Look into SymlinkAction.
|
|
if artifact.is_directory:
|
|
_utils.copy_dir(ctx, artifact, dep_lib_artifact)
|
|
else:
|
|
_utils.copy_file(ctx, artifact, dep_lib_artifact)
|
|
dep_lib_artifacts.append(dep_lib_artifact)
|
|
return dep_lib_artifacts
|
|
|
|
def _get_javac_opts(
|
|
ctx,
|
|
java_package,
|
|
dependency_artifacts_dir,
|
|
aar_out_dir,
|
|
class_info_path,
|
|
layout_info_path,
|
|
deps):
|
|
java_packages = []
|
|
for info in deps:
|
|
for label_and_java_package in info.label_and_java_packages:
|
|
java_packages.append(label_and_java_package.java_package)
|
|
|
|
javac_opts = []
|
|
javac_opts.append("-Aandroid.databinding.dependencyArtifactsDir=" +
|
|
dependency_artifacts_dir)
|
|
javac_opts.append("-Aandroid.databinding.aarOutDir=" + aar_out_dir)
|
|
javac_opts.append("-Aandroid.databinding.sdkDir=/not/used")
|
|
javac_opts.append("-Aandroid.databinding.artifactType=LIBRARY")
|
|
javac_opts.append("-Aandroid.databinding.exportClassListOutFile=" +
|
|
"/tmp/exported_classes")
|
|
javac_opts.append("-Aandroid.databinding.modulePackage=" + java_package)
|
|
javac_opts.append("-Aandroid.databinding.directDependencyPkgs=[%s]" %
|
|
",".join(java_packages))
|
|
|
|
# The minimum Android SDK compatible with this rule.
|
|
# TODO(djwhang): This probably should be based on the actual min-sdk from
|
|
# the manifest, or an appropriate rule attribute.
|
|
javac_opts.append("-Aandroid.databinding.minApi=14")
|
|
javac_opts.append("-Aandroid.databinding.enableV2=1")
|
|
|
|
javac_opts.append("-Aandroid.databinding.classLogDir=" + class_info_path)
|
|
javac_opts.append("-Aandroid.databinding.layoutInfoDir=" + layout_info_path)
|
|
return javac_opts
|
|
|
|
def _process(
|
|
ctx,
|
|
resources_ctx = None,
|
|
defines_resources = False,
|
|
enable_data_binding = False,
|
|
java_package = None,
|
|
deps = [],
|
|
exports = [],
|
|
data_binding_exec = None,
|
|
data_binding_annotation_processor = None,
|
|
data_binding_annotation_template = None):
|
|
"""Processes Android Data Binding.
|
|
|
|
Args:
|
|
ctx: The context.
|
|
resources_ctx: The Android Resources context.
|
|
defines_resources: boolean. Determines whether resources were defined.
|
|
enable_data_binding: boolean. Determines whether Data Binding should be
|
|
enabled.
|
|
java_package: String. The Java package.
|
|
deps: sequence of DataBindingV2Info providers. A list of deps. Optional.
|
|
exports: sequence of DataBindingV2Info providers. A list of exports.
|
|
Optional.
|
|
data_binding_exec: The DataBinding executable.
|
|
data_binding_annotation_processor: JavaInfo. The JavaInfo for the
|
|
annotation processor.
|
|
data_binding_annotation_template: A file. Used to generate data binding
|
|
classes.
|
|
|
|
Returns:
|
|
A DataBindingContextInfo provider.
|
|
"""
|
|
|
|
# TODO(b/154513292): Clean up bad usages of context objects.
|
|
if resources_ctx:
|
|
defines_resources = resources_ctx.defines_resources
|
|
|
|
# The Android Data Binding context object.
|
|
db_info = {
|
|
_JAVA_ANNOTATION_PROCESSOR_ADDITIONAL_INPUTS: [],
|
|
_JAVA_ANNOTATION_PROCESSOR_ADDITIONAL_OUTPUTS: [],
|
|
_JAVA_PLUGINS: [],
|
|
_JAVA_SRCS: [],
|
|
_JAVAC_OPTS: [],
|
|
_PROVIDERS: [],
|
|
}
|
|
|
|
if not enable_data_binding:
|
|
db_info[_PROVIDERS] = [
|
|
DataBindingV2Info(
|
|
databinding_v2_providers_in_deps = deps,
|
|
databinding_v2_providers_in_exports = exports,
|
|
),
|
|
]
|
|
return struct(**db_info)
|
|
|
|
output_dir = "_migrated/databinding/%s/" % ctx.label.name
|
|
|
|
db_info[_JAVA_SRCS].append(_copy_annotation_file(
|
|
ctx,
|
|
output_dir,
|
|
data_binding_annotation_template,
|
|
))
|
|
db_info[_JAVA_PLUGINS].append(data_binding_annotation_processor)
|
|
|
|
br_out = None
|
|
setter_store_out = None
|
|
class_info = None
|
|
layout_info = None
|
|
if defines_resources:
|
|
# Outputs of the Data Binding annotation processor.
|
|
br_out = ctx.actions.declare_file(
|
|
output_dir + "bin-files/%s-br.bin" % java_package,
|
|
)
|
|
db_info[_JAVA_ANNOTATION_PROCESSOR_ADDITIONAL_OUTPUTS].append(br_out)
|
|
setter_store_out = ctx.actions.declare_file(
|
|
output_dir + "bin-files/%s-setter_store.json" % java_package,
|
|
)
|
|
db_info[_JAVA_ANNOTATION_PROCESSOR_ADDITIONAL_OUTPUTS].append(
|
|
setter_store_out,
|
|
)
|
|
|
|
srcjar, class_info, layout_info = _gen_sources(
|
|
ctx,
|
|
output_dir,
|
|
java_package,
|
|
deps,
|
|
data_binding_exec,
|
|
)
|
|
db_info[_JAVA_SRCS].append(srcjar)
|
|
db_info[_JAVA_ANNOTATION_PROCESSOR_ADDITIONAL_INPUTS].append(class_info)
|
|
db_info[_JAVA_ANNOTATION_PROCESSOR_ADDITIONAL_INPUTS].append(
|
|
layout_info,
|
|
)
|
|
|
|
dep_lib_artifacts = _setup_dependent_lib_artifacts(ctx, output_dir, deps)
|
|
db_info[_JAVA_ANNOTATION_PROCESSOR_ADDITIONAL_INPUTS].extend(
|
|
dep_lib_artifacts,
|
|
)
|
|
|
|
db_info[_JAVAC_OPTS] = _get_javac_opts(
|
|
ctx,
|
|
java_package,
|
|
(
|
|
br_out.path.rpartition(br_out.short_path)[0] +
|
|
ctx.label.package +
|
|
"/" +
|
|
output_dir +
|
|
"dependent-lib-artifacts"
|
|
),
|
|
br_out.dirname,
|
|
class_info.path if class_info else _NO_RESOURCES_PATH,
|
|
layout_info.path if layout_info else _NO_RESOURCES_PATH,
|
|
deps,
|
|
)
|
|
|
|
db_info[_PROVIDERS] = [
|
|
DataBindingV2Info(
|
|
setter_store_file = setter_store_out,
|
|
class_info_file = class_info,
|
|
br_file = br_out,
|
|
label = str(ctx.label),
|
|
java_package = java_package,
|
|
databinding_v2_providers_in_deps = deps,
|
|
databinding_v2_providers_in_exports = exports,
|
|
),
|
|
]
|
|
|
|
return DataBindingContextInfo(**db_info)
|
|
|
|
data_binding = struct(
|
|
process = _process,
|
|
)
|