• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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