# Copyright 2020 Google LLC # # 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. """ Definition of java_single_jar. """ def _check_non_empty(value, name): if not value: fail("%s must be non-empty" % name) def _java_single_jar(ctx): _check_non_empty(ctx.attr.root_packages, "root_packages") inputs = depset() if ctx.attr.source_jar: inputs = depset(transitive = [dep[JavaInfo].transitive_source_jars for dep in ctx.attr.deps]) else: inputs = depset(transitive = [dep[JavaInfo].transitive_runtime_jars for dep in ctx.attr.deps]) args = ctx.actions.args() args.add_all("--sources", inputs) args.use_param_file( "@%s", use_always = True, ) args.set_param_file_format("multiline") args.add("--output", ctx.outputs.jar) args.add("--normalize") resource_files = depset( transitive = [resource.files for resource in ctx.attr.resources], ).to_list() args.add("--resources") for resource_file in resource_files: if not resource_file.path.startswith("src/main/resources"): fail("resource %s must be stored in src/main/resources/" % resource_file.path) relative_path = resource_file.path.replace("src/main/resources/", "") # Map src/main/resources/a/b/c.txt to a/b/c.txt. args.add(resource_file.path, format = "%s:" + relative_path) # Maybe compress code. if not ctx.attr.source_jar: # 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) # Each package prefix has to be specified in its own --include_prefixes arg. for p in ctx.attr.root_packages: args.add("--include_prefixes", p.replace(".", "/")) if ctx.attr.exclude_build_data: args.add("--exclude_build_data") args.add_all("--deploy_manifest_lines", ctx.attr.manifest_lines, format_each = "\"%s\"") ctx.actions.run( inputs = inputs.to_list() + resource_files, outputs = [ctx.outputs.jar], arguments = [args], progress_message = "Merging into %s" % ctx.outputs.jar.short_path, mnemonic = "JavaSingleJar", executable = ctx.executable._singlejar, ) java_single_jar = rule( attrs = { "deps": attr.label_list(providers = [JavaInfo]), "resources": attr.label_list( providers = [JavaInfo], allow_files = True, ), "_singlejar": attr.label( default = Label("@bazel_tools//tools/jdk:singlejar"), cfg = "exec", allow_single_file = True, executable = True, ), "source_jar": attr.bool(default = False), "compress": attr.string(default = "preserve"), "root_packages": attr.string_list(), "exclude_build_data": attr.bool(default = True), "manifest_lines": attr.string_list(), }, outputs = { "jar": "%{name}.jar", }, implementation = _java_single_jar, doc = """ Collects Java dependencies and jar files into a single jar Args: deps: The Java targets (including java_import and java_library) to collect transitive dependencies from. Both compile-time dependencies (deps, exports) and runtime dependencies (runtime_deps) are collected. Resources are also collected. Native cc_library or java_wrap_cc dependencies are not. resources: A combination of resource files. Files must be stored in src/main/resources. Mapping rules: src/main/resources/a/b/c.txt will be copied to a/b/c.txt in the output jar. compress: 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. source_jar: Whether to combine only the source jars of input to create a single output source jar. The compiled code jars of input will be ignored. root_packages: Java packages to include in generated jar. exclude_build_data: Whether to omit the build-data.properties file generated by default. manifest_lines: lines to put in the output manifest file (manifest files in the input jars are ignored) Outputs: {name}.jar: A single jar containing all of the input. """, )