blob: 6e85bdefe6383d51bc58b57867df05ad2a1bc299 [file] [log] [blame]
""" Definition of _java_single_jar. """
load("//java/common:java_common.bzl", "java_common")
load("//java/common:java_info.bzl", "JavaInfo")
def _java_single_jar(ctx):
transitive_inputs = []
for dep in ctx.attr.deps:
if JavaInfo in dep:
info = dep[JavaInfo]
transitive_inputs.append(info.transitive_runtime_jars)
if hasattr(info, "compilation_info"):
compilation_info = info.compilation_info
if hasattr(compilation_info, "runtime_classpath"):
transitive_inputs.append(compilation_info.runtime_classpath)
else:
files = []
for f in dep[DefaultInfo].files.to_list():
if not f.extension == "jar":
fail("unexpected file type in java_single_jar.deps: %s" % f.path)
files.append(f)
transitive_inputs.append(depset(files))
inputs = depset(transitive = transitive_inputs)
if hasattr(java_common, "JavaRuntimeClasspathInfo"):
deploy_env_jars = depset(transitive = [
dep[java_common.JavaRuntimeClasspathInfo].runtime_classpath
for dep in ctx.attr.deploy_env
])
excluded_jars = {jar: None for jar in deploy_env_jars.to_list()}
if excluded_jars:
inputs = depset([jar for jar in inputs.to_list() if jar not in excluded_jars])
args = ctx.actions.args()
args.add_all("--sources", inputs)
args.use_param_file("@%s")
args.set_param_file_format("multiline")
args.add_all("--deploy_manifest_lines", ctx.attr.deploy_manifest_lines)
args.add("--output", ctx.outputs.jar)
args.add("--normalize")
# Deal with limitation of singlejar flags: tool's default behavior is
# "no", but you get that behavior only by absence of compression flags.
if ctx.attr.compress == "preserve":
args.add("--dont_change_compression")
elif ctx.attr.compress == "yes":
args.add("--compression")
elif ctx.attr.compress == "no":
pass
else:
fail("\"compress\" attribute (%s) must be: yes, no, preserve." % ctx.attr.compress)
if ctx.attr.exclude_build_data:
args.add("--exclude_build_data")
if ctx.attr.multi_release:
args.add("--multi_release")
ctx.actions.run(
inputs = inputs,
outputs = [ctx.outputs.jar],
arguments = [args],
progress_message = "Merging into %s" % ctx.outputs.jar.short_path,
mnemonic = "JavaSingleJar",
executable = ctx.executable._singlejar,
)
files = depset([ctx.outputs.jar])
providers = [DefaultInfo(
files = files,
runfiles = ctx.runfiles(transitive_files = files),
)]
if hasattr(java_common, "JavaRuntimeClasspathInfo"):
providers.append(java_common.JavaRuntimeClasspathInfo(runtime_classpath = inputs))
return providers
java_single_jar = rule(
attrs = {
"deps": attr.label_list(
allow_files = True,
doc = """
The Java targets (including java_import and java_library) to collect
transitive dependencies from. Runtime dependencies are collected via
deps, exports, and runtime_deps. Resources are also collected.
Native cc_library or java_wrap_cc dependencies are not.""",
),
"deploy_manifest_lines": attr.string_list(doc = """
A list of lines to add to the <code>META-INF/manifest.mf</code> file."""),
"deploy_env": attr.label_list(
providers = [java_common.JavaRuntimeClasspathInfo] if hasattr(java_common, "JavaRuntimeClasspathInfo") else [],
allow_files = False,
doc = """
A list of `java_binary` or `java_single_jar` targets which represent
the deployment environment for this binary.
Set this attribute when building a plugin which will be loaded by another
`java_binary`.
`deploy_env` dependencies are excluded from the jar built by this rule.""",
),
"compress": attr.string(default = "preserve", doc = """
Whether to always deflate ("yes"), always store ("no"), or pass
through unmodified ("preserve"). The default is "preserve", and is the
most efficient option -- no extra work is done to inflate or deflate."""),
"exclude_build_data": attr.bool(default = True, doc = """
Whether to omit the build-data.properties file generated
by default."""),
"multi_release": attr.bool(default = True, doc = """Whether to enable Multi-Release output jars."""),
"_singlejar": attr.label(
default = Label("//toolchains:singlejar"),
cfg = "exec",
allow_single_file = True,
executable = True,
),
},
outputs = {
"jar": "%{name}.jar",
},
implementation = _java_single_jar,
doc = """
Collects Java dependencies and jar files into a single jar
`java_single_jar` collects Java dependencies and jar files into a single jar.
This is similar to java_binary with everything related to executables disabled,
and provides an alternative to the java_binary "deploy jar hack".
## Example
```skylark
load("//tools/build_defs/java_single_jar:java_single_jar.bzl", "java_single_jar")
java_single_jar(
name = "my_single_jar",
deps = [
"//java/com/google/foo",
"//java/com/google/bar",
],
)
```
Outputs:
{name}.jar: A single jar containing all of the inputs.
""",
)