Skip to content

Commit

Permalink
Restructure Starlark java_library to internal and Bazel parts.
Browse files Browse the repository at this point in the history
PiperOrigin-RevId: 386209364
  • Loading branch information
comius authored and copybara-github committed Jul 22, 2021
1 parent 5e352af commit de45065
Show file tree
Hide file tree
Showing 5 changed files with 478 additions and 0 deletions.
120 changes: 120 additions & 0 deletions src/main/starlark/builtins_bzl/common/java/android_lint.bzl
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
# 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.

"""Creates the android lint action for java rules"""

load(":common/rule_util.bzl", "create_dep")

java_common = _builtins.toplevel.java_common

def _impl(ctx, java_info, source_files, source_jars):
# assuming that linting is enabled for all java rules i.e.
# --experimental_run_android_lint_on_java_rules=true and
# --experimental_limit_android_lint_to_android_constrained_java=false
if (ctx.configuration == ctx.host_configuration or
ctx.bin_dir.path.find("-exec-") >= 0):
return None

srcs = ctx.files.srcs
if not srcs or (hasattr(ctx.attr, "neverlink") and ctx.attr.neverlink):
return None

toolchain = ctx.attr._java_toolchain[java_common.JavaToolchainInfo]
java_runtime = toolchain.java_runtime
linter = toolchain.android_linter()
if not linter:
# TODO(hvd): enable after enabling in tests
# fail("android linter not set in java_toolchain")
return None

args = ctx.actions.args()

tool = linter.tool
executable = linter.tool.executable
transitive_inputs = [linter.data]
if executable.extension == "jar":
args.add_all(toolchain.jvm_opt)
args.add("-jar", executable)
executable = java_runtime.java_executable_exec_path
transitive_inputs.append(java_runtime.files)

for output in java_info.java_outputs:
if output.generated_source_jar != None:
source_jars.append(output.generated_source_jar)

# TODO(ilist): collect compile_jars from JavaInfo in deps & exports
classpath = java_info.compilation_info.compilation_classpath

# TODO(hvd): get from toolchain if we need this - probably android only
bootclasspath_aux = []
if bootclasspath_aux:
classpath = depset(transitive = [classpath, bootclasspath_aux])

bootclasspath = toolchain.bootclasspath
plugin_info = java_info.plugins

args.add_all("--sources", source_files)
args.add_all("--source_jars", source_jars)
args.add_all("--bootclasspath", bootclasspath)
args.add_all("--classpath", classpath)
args.add_all("--plugins", plugin_info.processor_jars)
args.add("--target_label", ctx.label)

javac_opts = java_info.compilation_info.javac_options
if (javac_opts):
args.add_all("--javacopts", javac_opts)
args.add("--")

args.add("--lintopts")
args.add_all(linter.lint_opts)

for package_config in linter.package_config:
if package_config.matches(ctx.label):
args.add_all(package_config.javac_opts())
transitive_inputs.append(package_config.data())

android_lint_out = ctx.actions.declare_file("%s_android_lint_output.xml" % ctx.label.name)
args.add("--xml", android_lint_out)

args.set_param_file_format(format = "multiline")
args.use_param_file(param_file_arg = "@%s", use_always = True)
ctx.actions.run(
mnemonic = "AndroidLint",
progress_message = "Running Android Lint for: %{label}",
executable = executable,
inputs = depset(
source_files + source_jars,
transitive = transitive_inputs + [
classpath,
bootclasspath,
plugin_info.processor_jars,
plugin_info.processor_data,
],
),
outputs = [android_lint_out],
tools = [tool],
arguments = [args],
execution_requirements = {"supports-workers": "1"},
)
return android_lint_out

ANDROID_LINT_ACTION = create_dep(
call = _impl,
attrs = {
"_java_toolchain": attr.label(
default = "@//tools/jdk:current_java_toolchain",
providers = [java_common.JavaToolchainInfo],
),
},
)
156 changes: 156 additions & 0 deletions src/main/starlark/builtins_bzl/common/java/compile_action.bzl
Original file line number Diff line number Diff line change
@@ -0,0 +1,156 @@
# 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",
"ALLOWED_RULES_IN_DEPS",
"ALLOWED_RULES_IN_DEPS_WITH_WARNING",
"COLLECT_SRCS_FROM_PROTO_LIBRARY",
"EXPERIMENTAL_USE_FILEGROUPS_IN_JAVALIBRARY",
"EXTRA_SRCS_TYPES",
)

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 _legacy_jars(attr):
jars = [
file
for dep in attr
if not JavaInfo in dep or dep.kind == "java_binary"
for file in dep[DefaultInfo].files.to_list()
if file.extension == "jar"
]
return [JavaInfo(output_jar = jar, compile_jar = jar) for jar in jars] # Native doesn't construct JavaInfo

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 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)

java_info = java_common.compile(
ctx,
source_files = source_files,
source_jars = source_jars,
resources = resources,
plugins = _filter_provider(JavaPluginInfo, ctx.attr.plugins) + [ctx.attr._java_plugins[JavaPluginInfo]],
deps = _filter_provider(JavaInfo, deps) + _legacy_jars(deps),
native_libraries = _filter_provider(CcInfo, deps, runtime_deps, exports),
runtime_deps = _filter_provider(JavaInfo, runtime_deps) + _legacy_jars(runtime_deps),
exports = _filter_provider(JavaInfo, exports) + _legacy_jars(exports),
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 = ctx.actions.declare_file(output_prefix + "%s.jar" % ctx.attr.name) if EXPERIMENTAL_USE_FILEGROUPS_IN_JAVALIBRARY else ctx.outputs.classjar,
output_source_jar = ctx.actions.declare_file(output_prefix + "%s-src.jar" % ctx.attr.name) if EXPERIMENTAL_USE_FILEGROUPS_IN_JAVALIBRARY else ctx.outputs.sourcejar,
strict_deps = _filter_strict_deps(ctx.fragments.java.strict_java_deps),
)

files = [out.class_jar for out in java_info.java_outputs]

if ctx.attr.neverlink:
runfiles = None
else:
has_sources = source_files or source_jars
run_files = files if has_sources or resources else []
runfiles = ctx.runfiles(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 = depset(files),
runfiles = runfiles,
)
return java_info, default_info

COMPILE_ACTION = create_dep(
_compile_action,
{
"srcs": attr.label_list(
allow_files = [".java", ".srcjar", ".properties"] + 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 = ALLOWED_RULES_IN_DEPS + ALLOWED_RULES_IN_DEPS_WITH_WARNING,
providers = [
[CcInfo],
[JavaInfo],
],
flags = ["SKIP_ANALYSIS_TIME_FILETYPE_CHECK"],
),
"javacopts": attr.string_list(),
"neverlink": attr.bool(),
"_java_toolchain": attr.label(
default = "@//tools/jdk:current_java_toolchain",
providers = [java_common.JavaToolchainInfo],
),
"_java_plugins": attr.label(
default = "@//tools/jdk:java_plugins_flag_alias",
providers = [JavaPluginInfo],
),
},
["java", "google_java", "cpp"],
)
37 changes: 37 additions & 0 deletions src/main/starlark/builtins_bzl/common/java/java_semantics.bzl
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
# 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 Semantics
"""

EXPERIMENTAL_USE_FILEGROUPS_IN_JAVALIBRARY = True
COLLECT_SRCS_FROM_PROTO_LIBRARY = False
EXTRA_SRCS_TYPES = []

ALLOWED_RULES_IN_DEPS = [
"cc_binary", # NB: linkshared=1
"cc_library",
"genrule",
"genproto", # TODO(bazel-team): we should filter using providers instead (starlark rule).
"java_import",
"java_library",
"java_proto_library",
"java_lite_proto_library",
"proto_library",
"sh_binary",
"sh_library",
]

ALLOWED_RULES_IN_DEPS_WITH_WARNING = []
77 changes: 77 additions & 0 deletions src/main/starlark/builtins_bzl/common/java/proguard_validation.bzl
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
# 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.

"""
Proguard
"""

load(":common/rule_util.bzl", "create_dep")

ProguardSpecProvider = _builtins.toplevel.ProguardSpecProvider

def _get_attr_safe(ctx, attr, default):
return getattr(ctx.attr, attr) if hasattr(ctx.attr, attr) else default

def _filter_provider(provider, *attrs):
return [dep[provider] for attr in attrs for dep in attr if provider in dep]

def _collect_transitive_proguard_specs(ctx):
attrs = [
ctx.attr.deps,
_get_attr_safe(ctx, "runtime_deps", []),
_get_attr_safe(ctx, "exports", []),
_get_attr_safe(ctx, "plugins", []),
_get_attr_safe(ctx, "exported_plugins", []),
]

return [proguard.specs for proguard in _filter_provider(ProguardSpecProvider, *attrs)]

def _validate_spec(ctx, spec_file):
validated_proguard_spec = ctx.actions.declare_file(
"validated_proguard/%s/%s_valid" % (ctx.label.name, spec_file.path),
)

args = ctx.actions.args()
args.add("--path", spec_file)
args.add("--output", validated_proguard_spec)

ctx.actions.run(
mnemonic = "ValidateProguard",
progress_message = "Validating proguard configuration %s" % spec_file,
executable = ctx.executable._proguard_allowlister,
arguments = [args],
inputs = [spec_file],
outputs = [validated_proguard_spec],
)

return validated_proguard_spec

def _validate_proguard_specs_impl(ctx):
if ctx.files.proguard_specs and not hasattr(ctx.attr, "_proguard_allowlister"):
fail("_proguard_allowlister is required to use proguard_specs")

return ProguardSpecProvider(
depset(
[_validate_spec(ctx, spec_file) for spec_file in ctx.files.proguard_specs],
transitive = _collect_transitive_proguard_specs(ctx),
),
)

VALIDATE_PROGUARD_SPECS = create_dep(
_validate_proguard_specs_impl,
{
"proguard_specs": attr.label_list(allow_files = True),
},
[],
)
Loading

0 comments on commit de45065

Please sign in to comment.