Opensource java_single_jar in rules_java
PiperOrigin-RevId: 565664709
Change-Id: Id6d082ebfd28af9db53aff8700d697cb4ae21426
diff --git a/java/BUILD b/java/BUILD
index 8e07ca3..9e6bd30 100644
--- a/java/BUILD
+++ b/java/BUILD
@@ -16,3 +16,9 @@
visibility = ["//visibility:public"],
deps = ["//java/private"],
)
+
+bzl_library(
+ name = "java_single_jar",
+ srcs = ["java_single_jar.bzl"],
+ visibility = ["//visibility:public"],
+)
diff --git a/java/java_single_jar.bzl b/java/java_single_jar.bzl
new file mode 100644
index 0000000..6632c62
--- /dev/null
+++ b/java/java_single_jar.bzl
@@ -0,0 +1,117 @@
+""" Definition of _java_single_jar. """
+
+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)
+
+ args = ctx.actions.args()
+ args.add_all("--sources", inputs)
+ args.use_param_file("@%s")
+ args.set_param_file_format("multiline")
+ 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(
+ providers = [JavaInfo],
+ 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.""",
+ ),
+ "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("//tools/jdk: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.
+""",
+)