1""" Definition of _java_single_jar. """ 2 3load("//java/common:java_common.bzl", "java_common") 4load("//java/common:java_info.bzl", "JavaInfo") 5 6def _java_single_jar(ctx): 7 transitive_inputs = [] 8 for dep in ctx.attr.deps: 9 if JavaInfo in dep: 10 info = dep[JavaInfo] 11 transitive_inputs.append(info.transitive_runtime_jars) 12 if hasattr(info, "compilation_info"): 13 compilation_info = info.compilation_info 14 if hasattr(compilation_info, "runtime_classpath"): 15 transitive_inputs.append(compilation_info.runtime_classpath) 16 else: 17 files = [] 18 for f in dep[DefaultInfo].files.to_list(): 19 if not f.extension == "jar": 20 fail("unexpected file type in java_single_jar.deps: %s" % f.path) 21 files.append(f) 22 transitive_inputs.append(depset(files)) 23 inputs = depset(transitive = transitive_inputs) 24 25 if hasattr(java_common, "JavaRuntimeClasspathInfo"): 26 deploy_env_jars = depset(transitive = [ 27 dep[java_common.JavaRuntimeClasspathInfo].runtime_classpath 28 for dep in ctx.attr.deploy_env 29 ]) 30 excluded_jars = {jar: None for jar in deploy_env_jars.to_list()} 31 if excluded_jars: 32 inputs = depset([jar for jar in inputs.to_list() if jar not in excluded_jars]) 33 34 args = ctx.actions.args() 35 args.add_all("--sources", inputs) 36 args.use_param_file("@%s") 37 args.set_param_file_format("multiline") 38 args.add_all("--deploy_manifest_lines", ctx.attr.deploy_manifest_lines) 39 args.add("--output", ctx.outputs.jar) 40 args.add("--normalize") 41 42 # Deal with limitation of singlejar flags: tool's default behavior is 43 # "no", but you get that behavior only by absence of compression flags. 44 if ctx.attr.compress == "preserve": 45 args.add("--dont_change_compression") 46 elif ctx.attr.compress == "yes": 47 args.add("--compression") 48 elif ctx.attr.compress == "no": 49 pass 50 else: 51 fail("\"compress\" attribute (%s) must be: yes, no, preserve." % ctx.attr.compress) 52 53 if ctx.attr.exclude_build_data: 54 args.add("--exclude_build_data") 55 if ctx.attr.multi_release: 56 args.add("--multi_release") 57 58 ctx.actions.run( 59 inputs = inputs, 60 outputs = [ctx.outputs.jar], 61 arguments = [args], 62 progress_message = "Merging into %s" % ctx.outputs.jar.short_path, 63 mnemonic = "JavaSingleJar", 64 executable = ctx.executable._singlejar, 65 ) 66 67 files = depset([ctx.outputs.jar]) 68 providers = [DefaultInfo( 69 files = files, 70 runfiles = ctx.runfiles(transitive_files = files), 71 )] 72 if hasattr(java_common, "JavaRuntimeClasspathInfo"): 73 providers.append(java_common.JavaRuntimeClasspathInfo(runtime_classpath = inputs)) 74 return providers 75 76java_single_jar = rule( 77 attrs = { 78 "deps": attr.label_list( 79 allow_files = True, 80 doc = """ 81 The Java targets (including java_import and java_library) to collect 82 transitive dependencies from. Runtime dependencies are collected via 83 deps, exports, and runtime_deps. Resources are also collected. 84 Native cc_library or java_wrap_cc dependencies are not.""", 85 ), 86 "deploy_manifest_lines": attr.string_list(doc = """ 87 A list of lines to add to the <code>META-INF/manifest.mf</code> file."""), 88 "deploy_env": attr.label_list( 89 providers = [java_common.JavaRuntimeClasspathInfo] if hasattr(java_common, "JavaRuntimeClasspathInfo") else [], 90 allow_files = False, 91 doc = """ 92 A list of `java_binary` or `java_single_jar` targets which represent 93 the deployment environment for this binary. 94 95 Set this attribute when building a plugin which will be loaded by another 96 `java_binary`. 97 98 `deploy_env` dependencies are excluded from the jar built by this rule.""", 99 ), 100 "compress": attr.string(default = "preserve", doc = """ 101 Whether to always deflate ("yes"), always store ("no"), or pass 102 through unmodified ("preserve"). The default is "preserve", and is the 103 most efficient option -- no extra work is done to inflate or deflate."""), 104 "exclude_build_data": attr.bool(default = True, doc = """ 105 Whether to omit the build-data.properties file generated 106 by default."""), 107 "multi_release": attr.bool(default = True, doc = """Whether to enable Multi-Release output jars."""), 108 "_singlejar": attr.label( 109 default = Label("//toolchains:singlejar"), 110 cfg = "exec", 111 allow_single_file = True, 112 executable = True, 113 ), 114 }, 115 outputs = { 116 "jar": "%{name}.jar", 117 }, 118 implementation = _java_single_jar, 119 doc = """ 120Collects Java dependencies and jar files into a single jar 121 122`java_single_jar` collects Java dependencies and jar files into a single jar. 123This is similar to java_binary with everything related to executables disabled, 124and provides an alternative to the java_binary "deploy jar hack". 125 126## Example 127 128```skylark 129load("//tools/build_defs/java_single_jar:java_single_jar.bzl", "java_single_jar") 130 131java_single_jar( 132 name = "my_single_jar", 133 deps = [ 134 "//java/com/google/foo", 135 "//java/com/google/bar", 136 ], 137) 138``` 139 140Outputs: 141 {name}.jar: A single jar containing all of the inputs. 142""", 143) 144