1# Copyright 2020 Google LLC 2# 3# Licensed under the Apache License, Version 2.0 (the "License"); 4# you may not use this file except in compliance with the License. 5# You may obtain a copy of the License at 6# 7# http://www.apache.org/licenses/LICENSE-2.0 8# 9# Unless required by applicable law or agreed to in writing, software 10# distributed under the License is distributed on an "AS IS" BASIS, 11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12# See the License for the specific language governing permissions and 13# limitations under the License. 14 15""" Definition of java_single_jar. """ 16 17load("@rules_java//java:defs.bzl", "JavaInfo") 18 19def _check_non_empty(value, name): 20 if not value: 21 fail("%s must be non-empty" % name) 22 23def _java_single_jar(ctx): 24 _check_non_empty(ctx.attr.root_packages, "root_packages") 25 26 inputs = depset() 27 if ctx.attr.source_jar: 28 inputs = depset(transitive = [dep[JavaInfo].transitive_source_jars for dep in ctx.attr.deps]) 29 else: 30 inputs = depset(transitive = [dep[JavaInfo].transitive_runtime_jars for dep in ctx.attr.deps]) 31 32 args = ctx.actions.args() 33 args.add_all("--sources", inputs) 34 args.use_param_file( 35 "@%s", 36 use_always = True, 37 ) 38 args.set_param_file_format("multiline") 39 args.add("--output", ctx.outputs.jar) 40 args.add("--normalize") 41 42 resource_files = depset( 43 transitive = [resource.files for resource in ctx.attr.resources], 44 ).to_list() 45 args.add("--resources") 46 for resource_file in resource_files: 47 if not resource_file.path.startswith("src/main/resources"): 48 fail("resource %s must be stored in src/main/resources/" % resource_file.path) 49 relative_path = resource_file.path.replace("src/main/resources/", "") 50 51 # Map src/main/resources/a/b/c.txt to a/b/c.txt. 52 args.add(resource_file.path, format = "%s:" + relative_path) 53 54 # Maybe compress code. 55 if not ctx.attr.source_jar: 56 # Deal with limitation of singlejar flags: tool's default behavior is 57 # "no", but you get that behavior only by absence of compression flags. 58 if ctx.attr.compress == "preserve": 59 args.add("--dont_change_compression") 60 elif ctx.attr.compress == "yes": 61 args.add("--compression") 62 elif ctx.attr.compress == "no": 63 pass 64 else: 65 fail("\"compress\" attribute (%s) must be: yes, no, preserve." % ctx.attr.compress) 66 67 # Each package prefix has to be specified in its own --include_prefixes arg. 68 for p in ctx.attr.root_packages: 69 args.add("--include_prefixes", p.replace(".", "/")) 70 71 if ctx.attr.exclude_build_data: 72 args.add("--exclude_build_data") 73 74 args.add_all("--deploy_manifest_lines", ctx.attr.manifest_lines, format_each = "\"%s\"") 75 76 ctx.actions.run( 77 inputs = inputs.to_list() + resource_files, 78 outputs = [ctx.outputs.jar], 79 arguments = [args], 80 progress_message = "Merging into %s" % ctx.outputs.jar.short_path, 81 mnemonic = "JavaSingleJar", 82 executable = ctx.executable._singlejar, 83 ) 84 85java_single_jar = rule( 86 attrs = { 87 "deps": attr.label_list(providers = [JavaInfo]), 88 "resources": attr.label_list( 89 providers = [JavaInfo], 90 allow_files = True, 91 ), 92 "_singlejar": attr.label( 93 default = Label("@bazel_tools//tools/jdk:singlejar"), 94 cfg = "exec", 95 allow_single_file = True, 96 executable = True, 97 ), 98 "source_jar": attr.bool(default = False), 99 "compress": attr.string(default = "preserve"), 100 "root_packages": attr.string_list(), 101 "exclude_build_data": attr.bool(default = True), 102 "manifest_lines": attr.string_list(), 103 }, 104 outputs = { 105 "jar": "%{name}.jar", 106 }, 107 implementation = _java_single_jar, 108 doc = """ 109Collects Java dependencies and jar files into a single jar 110 111Args: 112 deps: The Java targets (including java_import and java_library) to collect 113 transitive dependencies from. Both compile-time dependencies (deps, 114 exports) and runtime dependencies (runtime_deps) are collected. 115 Resources are also collected. Native cc_library or java_wrap_cc 116 dependencies are not. 117 resources: A combination of resource files. Files must be stored in 118 src/main/resources. Mapping rules: src/main/resources/a/b/c.txt will be 119 copied to a/b/c.txt in the output jar. 120 compress: Whether to always deflate ("yes"), always store ("no"), or pass 121 through unmodified ("preserve"). The default is "preserve", and is the 122 most efficient option -- no extra work is done to inflate or deflate. 123 source_jar: Whether to combine only the source jars of input to create a single 124 output source jar. The compiled code jars of input will be ignored. 125 root_packages: Java packages to include in generated jar. 126 exclude_build_data: Whether to omit the build-data.properties file generated 127 by default. 128 manifest_lines: lines to put in the output manifest file (manifest 129 files in the input jars are ignored) 130 131Outputs: 132 {name}.jar: A single jar containing all of the input. 133""", 134) 135