• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Copyright 2021 The Bazel Authors. All rights reserved.
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"""
16Common code for reuse across java_* rules
17"""
18
19load("@rules_cc//cc/common:cc_info.bzl", "CcInfo")
20load("//java/common/rules:android_lint.bzl", "android_lint_subrule")
21load("//java/private:boot_class_path_info.bzl", "BootClassPathInfo")
22load("//java/private:java_common_internal.bzl", "target_kind")
23load("//java/private:java_info.bzl", "JavaInfo", "JavaPluginInfo")
24load(":compile_action.bzl", "compile_action")
25load(":proguard_validation.bzl", "validate_proguard_specs")
26
27# copybara: default multiline visibility
28
29def _filter_srcs(srcs, ext):
30    return [f for f in srcs if f.extension == ext]
31
32def _filter_provider(provider, *attrs):
33    return [dep[provider] for attr in attrs for dep in attr if provider in dep]
34
35# TODO(b/11285003): disallow jar files in deps, require java_import instead
36def _filter_javainfo_and_legacy_jars(attr):
37    dep_list = []
38
39    # Native code collected data into a NestedSet, using add for legacy jars and
40    # addTransitive for JavaInfo. This resulted in legacy jars being first in the list.
41    for dep in attr:
42        kind = target_kind(dep)
43        if not JavaInfo in dep or kind == "java_binary" or kind == "java_test":
44            for file in dep[DefaultInfo].files.to_list():
45                if file.extension == "jar":
46                    # Native doesn't construct JavaInfo
47                    java_info = JavaInfo(output_jar = file, compile_jar = file)
48                    dep_list.append(java_info)
49
50    for dep in attr:
51        if JavaInfo in dep:
52            dep_list.append(dep[JavaInfo])
53    return dep_list
54
55def basic_java_library(
56        ctx,
57        srcs,
58        deps = [],
59        runtime_deps = [],
60        plugins = [],
61        exports = [],
62        exported_plugins = [],
63        resources = [],
64        resource_jars = [],
65        classpath_resources = [],
66        javacopts = [],
67        neverlink = False,
68        enable_compile_jar_action = True,
69        coverage_config = None,
70        proguard_specs = None,
71        add_exports = [],
72        add_opens = [],
73        bootclasspath = None,
74        javabuilder_jvm_flags = None):
75    """
76    Creates actions that compile and lint Java sources, sets up coverage and returns JavaInfo, InstrumentedFilesInfo and output groups.
77
78    The call creates actions and providers needed and shared by `java_library`,
79    `java_plugin`,`java_binary`, and `java_test` rules and it is primarily
80    intended to be used in those rules.
81
82    Before compilation coverage.runner is added to the dependencies and if
83    present plugins are extended with the value of `--plugin` flag.
84
85    Args:
86      ctx: (RuleContext) Used to register the actions.
87      srcs: (list[File]) The list of source files that are processed to create the target.
88      deps: (list[Target]) The list of other libraries to be linked in to the target.
89      runtime_deps: (list[Target]) Libraries to make available to the final binary or test at runtime only.
90      plugins: (list[Target]) Java compiler plugins to run at compile-time.
91      exports: (list[Target]) Exported libraries.
92      exported_plugins: (list[Target]) The list of `java_plugin`s (e.g. annotation
93        processors) to export to libraries that directly depend on this library.
94      resources: (list[File]) A list of data files to include in a Java jar.
95      resource_jars: (list[File]) A list of jar files to unpack and include in a
96        Java jar.
97      classpath_resources: (list[File])
98      javacopts: (list[str])
99      neverlink: (bool) Whether this library should only be used for compilation and not at runtime.
100      enable_compile_jar_action: (bool) Enables header compilation or ijar creation.
101      coverage_config: (struct{runner:JavaInfo, support_files:list[File]|depset[File], env:dict[str,str]})
102        Coverage configuration. `runner` is added to dependencies during
103        compilation, `support_files` and `env` is returned in InstrumentedFilesInfo.
104      proguard_specs: (list[File]) Files to be used as Proguard specification.
105        Proguard validation is done only when the parameter is set.
106      add_exports: (list[str]) Allow this library to access the given <module>/<package>.
107      add_opens: (list[str]) Allow this library to reflectively access the given <module>/<package>.
108      bootclasspath: (Target) The JDK APIs to compile this library against.
109      javabuilder_jvm_flags: (list[str]) Additional JVM flags to pass to JavaBuilder.
110    Returns:
111      (dict[str, Provider],
112        {files_to_build: list[File],
113         runfiles: list[File],
114         output_groups: dict[str,list[File]]})
115    """
116    source_files = _filter_srcs(srcs, "java")
117    source_jars = _filter_srcs(srcs, "srcjar")
118
119    plugins_javaplugininfo = _collect_plugins(plugins)
120    plugins_javaplugininfo.append(ctx.attr._java_plugins[JavaPluginInfo])
121
122    properties = _filter_srcs(srcs, "properties")
123    if properties:
124        resources = list(resources)
125        resources.extend(properties)
126
127    java_info, compilation_info = compile_action(
128        ctx,
129        ctx.outputs.classjar,
130        ctx.outputs.sourcejar,
131        source_files,
132        source_jars,
133        collect_deps(deps) + ([coverage_config.runner] if coverage_config and coverage_config.runner else []),
134        collect_deps(runtime_deps),
135        plugins_javaplugininfo,
136        collect_deps(exports),
137        _collect_plugins(exported_plugins),
138        resources,
139        resource_jars,
140        classpath_resources,
141        _collect_native_libraries(deps, runtime_deps, exports),
142        javacopts,
143        neverlink,
144        ctx.fragments.java.strict_java_deps,
145        enable_compile_jar_action,
146        add_exports = add_exports,
147        add_opens = add_opens,
148        bootclasspath = bootclasspath[BootClassPathInfo] if bootclasspath else None,
149        javabuilder_jvm_flags = javabuilder_jvm_flags,
150    )
151    target = {"JavaInfo": java_info}
152
153    output_groups = dict(
154        compilation_outputs = compilation_info.files_to_build,
155        _source_jars = java_info.transitive_source_jars,
156        _direct_source_jars = java_info.source_jars,
157    )
158
159    if ctx.fragments.java.run_android_lint:
160        generated_source_jars = [
161            output.generated_source_jar
162            for output in java_info.java_outputs
163            if output.generated_source_jar != None
164        ]
165        lint_output = android_lint_subrule(
166            source_files,
167            source_jars + generated_source_jars,
168            compilation_info,
169        )
170        if lint_output:
171            output_groups["_validation"] = [lint_output]
172
173    target["InstrumentedFilesInfo"] = coverage_common.instrumented_files_info(
174        ctx,
175        source_attributes = ["srcs"],
176        dependency_attributes = ["deps", "data", "resources", "resource_jars", "exports", "runtime_deps", "jars"],
177        coverage_support_files = coverage_config.support_files if coverage_config else depset(),
178        coverage_environment = coverage_config.env if coverage_config else {},
179    )
180
181    if proguard_specs != None:
182        target["ProguardSpecProvider"] = validate_proguard_specs(
183            ctx,
184            proguard_specs,
185            [deps, runtime_deps, exports],
186        )
187        output_groups["_hidden_top_level_INTERNAL_"] = target["ProguardSpecProvider"].specs
188
189    return target, struct(
190        files_to_build = compilation_info.files_to_build,
191        runfiles = compilation_info.runfiles,
192        output_groups = output_groups,
193    )
194
195def _collect_plugins(plugins):
196    """Collects plugins from an attribute.
197
198    Use this call to collect plugins from `plugins` or `exported_plugins` attribute.
199
200    The call simply extracts JavaPluginInfo provider.
201
202    Args:
203      plugins: (list[Target]) Attribute to collect plugins from.
204    Returns:
205      (list[JavaPluginInfo]) The plugins.
206    """
207    return _filter_provider(JavaPluginInfo, plugins)
208
209def collect_deps(deps):
210    """Collects dependencies from an attribute.
211
212    Use this call to collect plugins from `deps`, `runtime_deps`, or `exports` attribute.
213
214    The call extracts JavaInfo and additionaly also "legacy jars". "legacy jars"
215    are wrapped into a JavaInfo.
216
217    Args:
218      deps: (list[Target]) Attribute to collect dependencies from.
219    Returns:
220      (list[JavaInfo]) The dependencies.
221    """
222    return _filter_javainfo_and_legacy_jars(deps)
223
224def _collect_native_libraries(*attrs):
225    """Collects native libraries from a list of attributes.
226
227    Use this call to collect native libraries from `deps`, `runtime_deps`, or `exports` attributes.
228
229    The call simply extracts CcInfo provider.
230    Args:
231      *attrs: (*list[Target]) Attribute to collect native libraries from.
232    Returns:
233      (list[CcInfo]) The native library dependencies.
234    """
235    return _filter_provider(CcInfo, *attrs)
236
237def construct_defaultinfo(ctx, files_to_build, files, neverlink, *extra_attrs):
238    """Constructs DefaultInfo for Java library like rule.
239
240    Args:
241      ctx: (RuleContext) Used to construct the runfiles.
242      files_to_build: (list[File]) List of the files built by the rule.
243      files: (list[File]) List of the files include in runfiles.
244      neverlink: (bool) When true empty runfiles are constructed.
245      *extra_attrs: (list[Target]) Extra attributes to merge runfiles from.
246
247    Returns:
248      (DefaultInfo) DefaultInfo provider.
249    """
250    if neverlink:
251        runfiles = None
252    else:
253        runfiles = ctx.runfiles(files = files, collect_default = True)
254        runfiles = runfiles.merge_all([dep[DefaultInfo].default_runfiles for attr in extra_attrs for dep in attr])
255    default_info = DefaultInfo(
256        files = depset(files_to_build),
257        runfiles = runfiles,
258    )
259    return default_info
260