blob: 57243f434fa0dc3b2af02f25f9dccbd0318883c5 [file] [log] [blame]
# Copyright 2021 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.
"""
Java compile action
"""
load(":common/rule_util.bzl", "create_dep")
load(":common/java/java_semantics.bzl", "semantics")
java_common = _builtins.toplevel.java_common
ProtoInfo = _builtins.toplevel.ProtoInfo
DefaultInfo = _builtins.toplevel.DefaultInfo
CcInfo = _builtins.toplevel.CcInfo
JavaInfo = _builtins.toplevel.JavaInfo
JavaPluginInfo = _builtins.toplevel.JavaPluginInfo
def _get_attr_safe(ctx, attr, default):
return getattr(ctx.attr, attr) if hasattr(ctx.attr, attr) else default
def _filter_srcs(srcs, ext):
return [f for f in srcs if f.extension == ext]
def _filter_provider(provider, *attrs):
return [dep[provider] for attr in attrs for dep in attr if provider in dep]
def _filter_strict_deps(mode):
return "error" if mode in ["strict", "default"] else mode
# TODO(b/11285003): disallow jar files in deps, require java_import instead
def _filter_javainfo_and_legacy_jars(attr):
dep_list = []
# Native code collected data into a NestedSet, using add for legacy jars and
# addTransitive for JavaInfo. This resulted in legacy jars being first in the list.
for dep in attr:
kind = java_common.target_kind(dep)
if not JavaInfo in dep or kind == "java_binary" or kind == "java_test":
for file in dep[DefaultInfo].files.to_list():
if file.extension == "jar":
# Native doesn't construct JavaInfo
java_info = JavaInfo(output_jar = file, compile_jar = file)
dep_list.append(java_info)
for dep in attr:
if JavaInfo in dep:
dep_list.append(dep[JavaInfo])
return dep_list
def _collect_plugins(deps, plugins):
transitive_processor_jars = []
transitive_processor_data = []
for plugin in plugins:
transitive_processor_jars.append(plugin.plugins.processor_jars)
transitive_processor_data.append(plugin.plugins.processor_data)
for dep in deps:
transitive_processor_jars.append(dep.plugins.processor_jars)
transitive_processor_data.append(dep.plugins.processor_data)
return struct(
processor_jars = depset(transitive = transitive_processor_jars),
processor_data = depset(transitive = transitive_processor_data),
)
def _compile_action(ctx, extra_resources, source_files, source_jars, output_prefix):
deps = ctx.attr.deps
runtime_deps = _get_attr_safe(ctx, "runtime_deps", [])
exports = _get_attr_safe(ctx, "exports", [])
exported_plugins = _get_attr_safe(ctx, "exported_plugins", [])
srcs = ctx.files.srcs
resources = []
if semantics.COLLECT_SRCS_FROM_PROTO_LIBRARY:
for resource in ctx.attr.resources:
if ProtoInfo in resource:
resources.extend(resource[ProtoInfo].transitive_sources.to_list())
else:
resources.extend(resource[DefaultInfo].files.to_list())
else:
resources.extend(ctx.files.resources)
resources.extend(_filter_srcs(ctx.files.srcs, "properties"))
resources.extend(extra_resources)
plugins = _filter_provider(JavaPluginInfo, ctx.attr.plugins)
plugins.append(ctx.attr._java_plugins[JavaPluginInfo])
deps_javainfo = _filter_javainfo_and_legacy_jars(deps)
runtime_deps_javainfo = _filter_javainfo_and_legacy_jars(runtime_deps)
exports_javainfo = _filter_javainfo_and_legacy_jars(exports)
if semantics.EXPERIMENTAL_USE_FILEGROUPS_IN_JAVALIBRARY and not semantics.EXPERIMENTAL_USE_OUTPUTATTR_IN_JAVALIBRARY:
output = ctx.actions.declare_file(output_prefix + "%s.jar" % ctx.attr.name)
output_source_jar = ctx.actions.declare_file(output_prefix + "%s-src.jar" % ctx.attr.name)
else:
output = ctx.outputs.classjar
output_source_jar = ctx.outputs.sourcejar
java_info = java_common.compile(
ctx,
source_files = source_files,
source_jars = source_jars,
resources = resources,
plugins = plugins,
deps = deps_javainfo,
native_libraries = _filter_provider(CcInfo, deps, runtime_deps, exports),
runtime_deps = runtime_deps_javainfo,
exports = exports_javainfo,
exported_plugins = _filter_provider(JavaPluginInfo, exported_plugins),
javac_opts = [ctx.expand_location(opt) for opt in ctx.attr.javacopts],
neverlink = ctx.attr.neverlink,
java_toolchain = ctx.attr._java_toolchain[java_common.JavaToolchainInfo],
output = output,
output_source_jar = output_source_jar,
strict_deps = _filter_strict_deps(ctx.fragments.java.strict_java_deps),
)
files = [out.class_jar for out in java_info.java_outputs]
files_depset = depset(files)
if ctx.attr.neverlink:
runfiles = None
else:
has_sources = source_files or source_jars
run_files = files_depset if has_sources or resources else None
runfiles = ctx.runfiles(transitive_files = run_files, collect_default = True)
runfiles = runfiles.merge_all([dep[DefaultInfo].default_runfiles for attr in [runtime_deps, exports] for dep in attr])
default_info = DefaultInfo(
files = files_depset,
runfiles = runfiles,
)
compilation_info = struct(
plugins = _collect_plugins(deps_javainfo, plugins),
outputs = files,
)
return java_info, default_info, compilation_info
COMPILE_ACTION = create_dep(
_compile_action,
attrs = {
"srcs": attr.label_list(
allow_files = [".java", ".srcjar", ".properties"] + semantics.EXTRA_SRCS_TYPES,
flags = ["DIRECT_COMPILE_TIME_INPUT", "ORDER_INDEPENDENT"],
),
"data": attr.label_list(
allow_files = True,
flags = ["SKIP_CONSTRAINTS_OVERRIDE"],
),
"resources": attr.label_list(
allow_files = True,
flags = ["SKIP_CONSTRAINTS_OVERRIDE", "ORDER_INDEPENDENT"],
),
"plugins": attr.label_list(
providers = [JavaPluginInfo],
allow_files = True,
cfg = "exec",
),
"deps": attr.label_list(
allow_files = [".jar"],
allow_rules = semantics.ALLOWED_RULES_IN_DEPS + semantics.ALLOWED_RULES_IN_DEPS_WITH_WARNING,
providers = [
[CcInfo],
[JavaInfo],
],
flags = ["SKIP_ANALYSIS_TIME_FILETYPE_CHECK"],
),
"runtime_deps": attr.label_list(
allow_files = [".jar"],
allow_rules = semantics.ALLOWED_RULES_IN_DEPS,
providers = [[CcInfo], [JavaInfo]],
flags = ["SKIP_ANALYSIS_TIME_FILETYPE_CHECK"],
),
"exports": attr.label_list(
allow_rules = semantics.ALLOWED_RULES_IN_DEPS,
providers = [[JavaInfo], [CcInfo]],
),
"exported_plugins": attr.label_list(
providers = [JavaPluginInfo],
cfg = "exec",
),
"javacopts": attr.string_list(),
"neverlink": attr.bool(),
"_java_toolchain": attr.label(
default = semantics.JAVA_TOOLCHAIN_LABEL,
providers = [java_common.JavaToolchainInfo],
),
"_java_plugins": attr.label(
default = semantics.JAVA_PLUGINS_FLAG_ALIAS_LABEL,
providers = [JavaPluginInfo],
),
},
fragments = ["java", "cpp"],
mandatory_attrs = ["srcs", "deps", "resources", "plugins", "javacopts", "neverlink"],
)