• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Copyright 2023 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"""
16Definition of JavaInfo and JavaPluginInfo provider.
17"""
18
19load("@rules_cc//cc/common:cc_common.bzl", "cc_common")
20load("@rules_cc//cc/common:cc_info.bzl", "CcInfo")
21load("//java/common:java_semantics.bzl", "semantics")
22load(":native.bzl", "get_internal_java_common")
23
24# copybara: default visibility
25
26_JavaOutputInfo = provider(
27    doc = "The outputs of Java compilation.",
28    fields = {
29        "class_jar": "(File) A classes jar file.",
30        "compile_jar": "(File) An interface jar file.",
31        "ijar": "Deprecated: Please use compile_jar.",
32        "compile_jdeps": "(File) Compile time dependencies information (deps.proto file).",
33        "generated_class_jar": "(File) A jar containing classes generated via annotation processing.",
34        "generated_source_jar": "(File) The source jar created as a result of annotation processing.",
35        "native_headers_jar": "(File) A jar of CC header files supporting native method implementation.",
36        "manifest_proto": "(File) The manifest protobuf file of the manifest generated from JavaBuilder.",
37        "jdeps": "(File) The jdeps protobuf file of the manifest generated from JavaBuilder.",
38        "source_jars": "(depset[File]) A depset of sources archive files.",
39        "source_jar": "Deprecated: Please use source_jars instead.",
40    },
41)
42_ModuleFlagsInfo = provider(
43    doc = "Provider for the runtime classpath contributions of a Java binary.",
44    fields = {
45        "add_exports": "(depset[str]) Add-Exports configuration.",
46        "add_opens": "(depset[str]) Add-Opens configuration.",
47    },
48)
49_EMPTY_MODULE_FLAGS_INFO = _ModuleFlagsInfo(add_exports = depset(), add_opens = depset())
50
51def _create_module_flags_info(*, add_exports, add_opens):
52    if add_exports or add_opens:
53        return _ModuleFlagsInfo(add_exports = add_exports, add_opens = add_opens)
54    return _EMPTY_MODULE_FLAGS_INFO
55
56_JavaRuleOutputJarsInfo = provider(
57    doc = "Deprecated: use java_info.java_outputs. Information about outputs of a Java rule.",
58    fields = {
59        "jdeps": "Deprecated: Use java_info.java_outputs.",
60        "native_headers": "Deprecated: Use java_info.java_outputs[i].jdeps.",
61        "jars": "Deprecated: Use java_info.java_outputs[i].native_headers_jar.",
62    },
63)
64_JavaGenJarsInfo = provider(
65    doc = "Deprecated: Information about jars that are a result of annotation processing for a Java rule.",
66    fields = {
67        "enabled": "Deprecated. Returns true if annotation processing was applied on this target.",
68        "class_jar": "Deprecated: Please use JavaInfo.java_outputs.generated_class_jar instead.",
69        "source_jar": "Deprecated: Please use JavaInfo.java_outputs.generated_source_jar instead.",
70        "transitive_class_jars": "Deprecated. A transitive set of class file jars from annotation " +
71                                 "processing of this rule and its dependencies.",
72        "transitive_source_jars": "Deprecated. A transitive set of source archives from annotation " +
73                                  "processing of this rule and its dependencies.",
74        "processor_classpath": "Deprecated: Please use JavaInfo.plugins instead.",
75        "processor_classnames": "Deprecated: Please use JavaInfo.plugins instead.",
76    },
77)
78
79JavaCompilationInfo = provider(
80    doc = "Compilation information in Java rules, for perusal of aspects and tools.",
81    fields = {
82        "boot_classpath": "Boot classpath for this Java target.",
83        "javac_options": """Depset of options to the java compiler. To get the
84            exact list of options passed to javac in the correct order, use the
85            tokenize_javacopts utility in rules_java""",
86        "compilation_classpath": "Compilation classpath for this Java target.",
87        "runtime_classpath": "Run-time classpath for this Java target.",
88    },
89)
90
91def merge(
92        providers,
93        # private to @_builtins:
94        merge_java_outputs = True,
95        merge_source_jars = True):
96    """Merges the given providers into a single JavaInfo.
97
98    Args:
99        providers: ([JavaInfo]) The list of providers to merge.
100        merge_java_outputs: (bool)
101        merge_source_jars: (bool)
102
103    Returns:
104        (JavaInfo) The merged JavaInfo
105    """
106    _validate_provider_list(providers, "providers", JavaInfo)
107
108    plugin_info = merge_plugin_info_without_outputs(providers)
109
110    source_jars = []  # [File]
111    transitive_source_jars = []  # [depset[File]]
112    java_outputs = []  # [_JavaOutputInfo]
113    runtime_output_jars = []  # [File]
114    transitive_runtime_jars = []  # [depset[File]]
115    transitive_compile_time_jars = []  # [depset[File]]
116    compile_jars = []  # [depset[File]]
117    full_compile_jars = []  # [depset[File]]
118    _transitive_full_compile_time_jars = []  # [depset[File]]
119    _compile_time_java_dependencies = []  # [depset[File]]
120    add_exports = []  # [depset[str]]
121    add_opens = []  # [depset[str]]
122    _neverlink = False
123    _constraints = []  # [str]
124    for p in providers:
125        if merge_source_jars:
126            source_jars.extend(p.source_jars)
127            transitive_source_jars.append(p.transitive_source_jars)
128        if merge_java_outputs:
129            java_outputs.extend(p.java_outputs)
130            runtime_output_jars.extend(p.runtime_output_jars)
131        transitive_runtime_jars.append(p.transitive_runtime_jars)
132        transitive_compile_time_jars.append(p.transitive_compile_time_jars)
133        compile_jars.append(p.compile_jars)
134        full_compile_jars.append(p.full_compile_jars)
135        _transitive_full_compile_time_jars.append(p._transitive_full_compile_time_jars)
136        _compile_time_java_dependencies.append(p._compile_time_java_dependencies)
137        add_exports.append(p.module_flags_info.add_exports)
138        add_opens.append(p.module_flags_info.add_opens)
139        _neverlink = _neverlink or p._neverlink
140        _constraints.extend(p._constraints)
141
142    transitive_runtime_jars = depset(order = "preorder", transitive = transitive_runtime_jars)
143    transitive_compile_time_jars = depset(order = "preorder", transitive = transitive_compile_time_jars)
144
145    # java_outputs is a list so we uniquify to avoid https://github.com/bazelbuild/bazel/issues/17170
146    java_outputs = depset(java_outputs).to_list()
147    result = {
148        "transitive_runtime_jars": transitive_runtime_jars,
149        "transitive_compile_time_jars": transitive_compile_time_jars,
150        "compile_jars": depset(order = "preorder", transitive = compile_jars),
151        "full_compile_jars": depset(order = "preorder", transitive = full_compile_jars),
152        "_transitive_full_compile_time_jars": depset(order = "preorder", transitive = _transitive_full_compile_time_jars),
153        "_compile_time_java_dependencies": depset(order = "preorder", transitive = _compile_time_java_dependencies),
154        # runtime_output_jars is a list so we uniquify to avoid https://github.com/bazelbuild/bazel/issues/17170
155        "runtime_output_jars": depset(runtime_output_jars).to_list(),
156        # source_jars is a list so we uniquify to avoid https://github.com/bazelbuild/bazel/issues/17170
157        "source_jars": depset(source_jars).to_list(),
158        "transitive_source_jars": depset(transitive = transitive_source_jars),
159        "java_outputs": java_outputs,
160        "outputs": _JavaRuleOutputJarsInfo(jars = java_outputs, jdeps = None, native_headers = None),
161        "module_flags_info": _create_module_flags_info(
162            add_exports = depset(transitive = add_exports),
163            add_opens = depset(transitive = add_opens),
164        ),
165        "plugins": plugin_info.plugins,
166        "api_generating_plugins": plugin_info.api_generating_plugins,
167        "_neverlink": bool(_neverlink),
168        "_constraints": depset(_constraints).to_list(),
169        "annotation_processing": None,
170        "compilation_info": None,
171    }
172
173    if get_internal_java_common().google_legacy_api_enabled():
174        cc_info = semantics.minimize_cc_info(cc_common.merge_cc_infos(cc_infos = [p.cc_link_params_info for p in providers]))
175        result.update(
176            cc_link_params_info = cc_info,
177            transitive_native_libraries = cc_info.transitive_native_libraries(),
178        )
179    else:
180        result.update(
181            transitive_native_libraries = depset(
182                order = "topological",
183                transitive = [p.transitive_native_libraries for p in providers],
184            ),
185        )
186    return get_internal_java_common().wrap_java_info(_new_javainfo(**result))
187
188def to_java_binary_info(java_info, compilation_info):
189    """Get a copy of the given JavaInfo with minimal info returned by a java_binary
190
191    Args:
192        java_info: (JavaInfo) A JavaInfo provider instance
193        compilation_info: (JavaCompilationInfo)
194    Returns:
195        (JavaInfo) A JavaInfo instance representing a java_binary target
196    """
197    result = {
198        "transitive_runtime_jars": depset(),
199        "transitive_compile_time_jars": depset(),
200        "compile_jars": depset(),
201        "full_compile_jars": depset(),
202        "_transitive_full_compile_time_jars": depset(),
203        "_compile_time_java_dependencies": depset(),
204        "runtime_output_jars": [],
205        "plugins": _EMPTY_PLUGIN_DATA,
206        "api_generating_plugins": _EMPTY_PLUGIN_DATA,
207        "module_flags_info": _EMPTY_MODULE_FLAGS_INFO,
208        "_neverlink": False,
209        "_constraints": [],
210        "annotation_processing": java_info.annotation_processing,
211        "transitive_native_libraries": java_info.transitive_native_libraries,
212        "source_jars": java_info.source_jars,
213        "transitive_source_jars": java_info.transitive_source_jars,
214    }
215    if hasattr(java_info, "cc_link_params_info"):
216        result.update(cc_link_params_info = java_info.cc_link_params_info)
217
218    result["compilation_info"] = compilation_info
219
220    java_outputs = [
221        _JavaOutputInfo(
222            compile_jar = None,
223            ijar = None,  # deprecated
224            compile_jdeps = None,
225            class_jar = output.class_jar,
226            generated_class_jar = output.generated_class_jar,
227            generated_source_jar = output.generated_source_jar,
228            native_headers_jar = output.native_headers_jar,
229            manifest_proto = output.manifest_proto,
230            jdeps = output.jdeps,
231            source_jars = output.source_jars,
232            source_jar = output.source_jar,  # deprecated
233        )
234        for output in java_info.java_outputs
235    ]
236    all_jdeps = [output.jdeps for output in java_info.java_outputs if output.jdeps]
237    all_native_headers = [output.native_headers_jar for output in java_info.java_outputs if output.native_headers_jar]
238    result.update(
239        java_outputs = java_outputs,
240        outputs = _JavaRuleOutputJarsInfo(
241            jars = java_outputs,
242            jdeps = all_jdeps[0] if len(all_jdeps) == 1 else None,
243            native_headers = all_native_headers[0] if len(all_native_headers) == 1 else None,
244        ),
245    )
246
247    # so that translation into native JavaInfo does not add JavaCompilationArgsProvider
248    result.update(_is_binary = True)
249    return _new_javainfo(**result)
250
251def _to_mutable_dict(java_info):
252    return {
253        key: getattr(java_info, key)
254        for key in dir(java_info)
255        if key not in ["to_json", "to_proto"]
256    }
257
258def add_constraints(java_info, constraints = []):
259    """Returns a copy of the given JavaInfo with the given constraints added.
260
261    Args:
262        java_info: (JavaInfo) The JavaInfo to enhance
263        constraints: ([str]) Constraints to add
264
265    Returns:
266        (JavaInfo)
267    """
268    result = _to_mutable_dict(java_info)
269    old_constraints = java_info._constraints if java_info._constraints else []
270    result.update(
271        _constraints = depset(constraints + old_constraints).to_list(),
272    )
273    return _new_javainfo(**result)
274
275def make_non_strict(java_info):
276    """Returns a new JavaInfo instance whose direct-jars part is the union of both the direct and indirect jars of the given Java provider.
277
278    Args:
279        java_info: (JavaInfo) The java info to make non-strict.
280
281    Returns:
282        (JavaInfo)
283    """
284    result = _to_mutable_dict(java_info)
285    result.update(
286        compile_jars = java_info.transitive_compile_time_jars,
287        full_compile_jars = java_info._transitive_full_compile_time_jars,
288    )
289
290    # Omit jdeps, which aren't available transitively and aren't useful for reduced classpath
291    # pruning for non-strict targets: the direct classpath and transitive classpath are the same,
292    # so there's nothing to prune, and reading jdeps at compile-time isn't free.
293    result.update(
294        _compile_time_java_dependencies = depset(),
295    )
296    return _new_javainfo(**result)
297
298def add_module_flags(java_info, add_exports = [], add_opens = []):
299    """Returns a new JavaInfo instance with the additional add_exports/add_opens
300
301    Args:
302        java_info: (JavaInfo) The java info to enhance.
303        add_exports: ([str]) The <module>/<package>s given access to.
304        add_opens: ([str]) The <module>/<package>s given reflective access to.
305    Returns:
306        (JavaInfo)
307    """
308    if not add_exports and not add_opens:
309        return java_info
310
311    result = _to_mutable_dict(java_info)
312    result.update(
313        module_flags_info = _create_module_flags_info(
314            add_exports = depset(add_exports, transitive = [java_info.module_flags_info.add_exports]),
315            add_opens = depset(add_opens, transitive = [java_info.module_flags_info.add_opens]),
316        ),
317    )
318    return _new_javainfo(**result)
319
320def set_annotation_processing(
321        java_info,
322        enabled = False,
323        processor_classnames = [],
324        processor_classpath = None,
325        class_jar = None,
326        source_jar = None):
327    """Returns a copy of the given JavaInfo with the given annotation_processing info.
328
329    Args:
330        java_info: (JavaInfo) The JavaInfo to enhance.
331        enabled: (bool) Whether the rule uses annotation processing.
332        processor_classnames: ([str]) Class names of annotation processors applied.
333        processor_classpath: (depset[File]) Class names of annotation processors applied.
334        class_jar: (File) Optional. Jar that is the result of annotation processing.
335        source_jar: (File) Optional. Source archive resulting from annotation processing.
336
337    Returns:
338        (JavaInfo)
339    """
340    gen_jars_info = java_info.annotation_processing
341    if gen_jars_info:
342        # Existing Jars would be a problem b/c we can't remove them from transitiveXxx sets
343        if gen_jars_info.class_jar and gen_jars_info.class_jar != class_jar:
344            fail("Existing gen_class_jar:", gen_jars_info.class_jar)
345        if gen_jars_info.source_jar and gen_jars_info.source_jar != source_jar:
346            fail("Existing gen_source_jar:", gen_jars_info.class_jar)
347        transitive_class_jars = depset([class_jar] if class_jar else [], transitive = [gen_jars_info.transitive_class_jars])
348        transitive_source_jars = depset([source_jar] if source_jar else [], transitive = [gen_jars_info.transitive_source_jars])
349    else:
350        transitive_class_jars = depset([class_jar] if class_jar else [])
351        transitive_source_jars = depset([source_jar] if source_jar else [])
352
353    result = _to_mutable_dict(java_info)
354    result.update(
355        annotation_processing = _JavaGenJarsInfo(
356            enabled = enabled,
357            class_jar = class_jar,
358            source_jar = source_jar,
359            processor_classnames = processor_classnames,
360            processor_classpath = processor_classpath if processor_classpath else depset(),
361            transitive_class_jars = transitive_class_jars,
362            transitive_source_jars = transitive_source_jars,
363        ),
364    )
365    return _new_javainfo(**result)
366
367def java_info_for_compilation(
368        output_jar,
369        compile_jar,
370        source_jar,
371        generated_class_jar,
372        generated_source_jar,
373        plugin_info,
374        deps,
375        runtime_deps,
376        exports,
377        exported_plugins,
378        compile_jdeps,
379        jdeps,
380        native_headers_jar,
381        manifest_proto,
382        native_libraries,
383        neverlink,
384        add_exports,
385        add_opens,
386        direct_runtime_jars,
387        compilation_info):
388    """Creates a JavaInfo instance represiting the result of java compilation.
389
390    Args:
391        output_jar: (File) The jar that was created as a result of a compilation.
392        compile_jar: (File) A jar that is the compile-time dependency in lieu of `output_jar`.
393        source_jar: (File) The source jar that was used to create the output jar.
394        generated_class_jar: (File) A jar file containing class files compiled from sources
395            generated during annotation processing.
396        generated_source_jar: (File) The source jar that was created as a result of annotation
397            processing.
398        plugin_info: (JavaPluginInfo) Information about annotation processing.
399        deps: ([JavaInfo]) Compile time dependencies that were used to create the output jar.
400        runtime_deps: ([JavaInfo]) Runtime dependencies that are needed for this library.
401        exports: ([JavaInfo]) Libraries to make available for users of this library.
402        exported_plugins: ([JavaPluginInfo]) A list of exported plugins.
403        compile_jdeps: (File) jdeps information about compile time dependencies to be consumed by
404            JavaCompileAction. This should be a binary proto encoded using the deps.proto protobuf
405            included with Bazel. If available this file is typically produced by a header compiler.
406        jdeps: (File) jdeps information for the rule output (if available). This should be a binary
407            proto encoded using the deps.proto protobuf included with Bazel. If available this file
408            is typically produced by a compiler. IDEs and other tools can use this information for
409            more efficient processing.
410        native_headers_jar: (File) A jar containing CC header files supporting native method
411            implementation (typically output of javac -h).
412        manifest_proto: (File) Manifest information for the rule output (if available). This should
413            be a binary proto encoded using the manifest.proto protobuf included with Bazel. IDEs
414            and other tools can use this information for more efficient processing.
415        native_libraries: ([CcInfo]) Native library dependencies that are needed for this library.
416        neverlink: (bool) If true, only use this library for compilation and not at runtime.
417        add_exports: ([str]) The <module>/<package>s this library was given access to.
418        add_opens: ([str]) The <module>/<package>s this library was given reflective access to.
419        direct_runtime_jars: ([File]) The class jars needed directly by this library at runtime.
420            This is usually just the output_jar or empty if there were no sources/resources.
421        compilation_info: (struct) Information for IDE/tools
422
423    Returns:
424        (JavaInfo) the JavaInfo instance
425    """
426    result, concatenated_deps = _javainfo_init_base(
427        output_jar,
428        compile_jar,
429        source_jar,
430        deps,
431        runtime_deps,
432        exports,
433        exported_plugins,
434        jdeps,
435        compile_jdeps,
436        native_headers_jar,
437        manifest_proto,
438        generated_class_jar,
439        generated_source_jar,
440        native_libraries,
441        neverlink,
442    )
443
444    # this differs ever so slightly from the usual JavaInfo in that direct_runtime_jars
445    # does not contain the output_jar is there were no sources/resources
446    transitive_runtime_jars = depset() if neverlink else depset(
447        order = "preorder",
448        direct = direct_runtime_jars,
449        transitive = [dep.transitive_runtime_jars for dep in concatenated_deps.exports_deps + runtime_deps],
450    )
451    result.update(
452        runtime_output_jars = direct_runtime_jars,
453        transitive_runtime_jars = transitive_runtime_jars,
454        transitive_source_jars = depset(
455            direct = [source_jar],
456            # only differs from the usual java_info.transitive_source_jars in the order of deps
457            transitive = [dep.transitive_source_jars for dep in concatenated_deps.runtimedeps_exports_deps],
458        ),
459        # the JavaInfo constructor does not add flags from runtime_deps
460        module_flags_info = _create_module_flags_info(
461            add_exports = depset(add_exports, transitive = [
462                dep.module_flags_info.add_exports
463                for dep in concatenated_deps.runtimedeps_exports_deps
464            ]),
465            add_opens = depset(add_opens, transitive = [
466                dep.module_flags_info.add_opens
467                for dep in concatenated_deps.runtimedeps_exports_deps
468            ]),
469        ),
470    )
471    if compilation_info:
472        result.update(
473            compilation_info = JavaCompilationInfo(
474                javac_options = compilation_info.javac_options,
475                boot_classpath = compilation_info.boot_classpath,
476                compilation_classpath = compilation_info.compilation_classpath,
477                runtime_classpath = compilation_info.runtime_classpath,
478            ),
479            annotation_processing = _JavaGenJarsInfo(
480                enabled = compilation_info.uses_annotation_processing,
481                class_jar = result["annotation_processing"].class_jar,
482                source_jar = result["annotation_processing"].source_jar,
483                processor_classnames = plugin_info.plugins.processor_classes.to_list(),
484                processor_classpath = plugin_info.plugins.processor_jars,
485                transitive_class_jars = result["annotation_processing"].transitive_class_jars,
486                transitive_source_jars = result["annotation_processing"].transitive_source_jars,
487            ),
488        )
489    else:
490        result.update(
491            compilation_info = None,
492            annotation_processing = None,
493        )
494    return get_internal_java_common().wrap_java_info(_new_javainfo(**result))
495
496def _validate_provider_list(provider_list, what, expected_provider_type):
497    get_internal_java_common().check_provider_instances(provider_list, what, expected_provider_type)
498
499def _compute_concatenated_deps(deps, runtime_deps, exports):
500    deps_exports = []
501    deps_exports.extend(deps)
502    deps_exports.extend(exports)
503
504    exports_deps = []
505    exports_deps.extend(exports)
506    exports_deps.extend(deps)
507
508    runtimedeps_exports_deps = []
509    runtimedeps_exports_deps.extend(runtime_deps)
510    runtimedeps_exports_deps.extend(exports_deps)
511
512    return struct(
513        deps_exports = deps_exports,
514        exports_deps = exports_deps,
515        runtimedeps_exports_deps = runtimedeps_exports_deps,
516    )
517
518def _javainfo_init_base(
519        output_jar,
520        compile_jar,
521        source_jar,
522        deps,
523        runtime_deps,
524        exports,
525        exported_plugins,
526        jdeps,
527        compile_jdeps,
528        native_headers_jar,
529        manifest_proto,
530        generated_class_jar,
531        generated_source_jar,
532        native_libraries,
533        neverlink):
534    _validate_provider_list(deps, "deps", JavaInfo)
535    _validate_provider_list(runtime_deps, "runtime_deps", JavaInfo)
536    _validate_provider_list(exports, "exports", JavaInfo)
537    _validate_provider_list(native_libraries, "native_libraries", CcInfo)
538
539    concatenated_deps = _compute_concatenated_deps(deps, runtime_deps, exports)
540
541    source_jars = [source_jar] if source_jar else []
542    plugin_info = merge_plugin_info_without_outputs(exported_plugins + exports)
543    transitive_compile_time_jars = depset(
544        order = "preorder",
545        direct = [compile_jar] if compile_jar else [],
546        transitive = [dep.transitive_compile_time_jars for dep in concatenated_deps.exports_deps],
547    )
548    java_outputs = [_JavaOutputInfo(
549        class_jar = output_jar,
550        compile_jar = compile_jar,
551        ijar = compile_jar,  # deprecated
552        compile_jdeps = compile_jdeps,
553        generated_class_jar = generated_class_jar,
554        generated_source_jar = generated_source_jar,
555        native_headers_jar = native_headers_jar,
556        manifest_proto = manifest_proto,
557        jdeps = jdeps,
558        source_jars = depset(source_jars),
559        source_jar = source_jar,  # deprecated
560    )]
561    result = {
562        "transitive_compile_time_jars": transitive_compile_time_jars,
563        "compile_jars": depset(
564            order = "preorder",
565            direct = [compile_jar] if compile_jar else [],
566            transitive = [dep.compile_jars for dep in exports],
567        ),
568        "full_compile_jars": depset(
569            order = "preorder",
570            direct = [output_jar],
571            transitive = [
572                dep.full_compile_jars
573                for dep in exports
574            ],
575        ),
576        "source_jars": source_jars,
577        "runtime_output_jars": [output_jar],
578        "plugins": plugin_info.plugins,
579        "api_generating_plugins": plugin_info.api_generating_plugins,
580        "java_outputs": java_outputs,
581        # deprecated
582        "outputs": _JavaRuleOutputJarsInfo(
583            jars = java_outputs,
584            jdeps = jdeps,
585            native_headers = native_headers_jar,
586        ),
587        "annotation_processing": _JavaGenJarsInfo(
588            enabled = False,
589            class_jar = generated_class_jar,
590            source_jar = generated_source_jar,
591            transitive_class_jars = depset(
592                direct = [generated_class_jar] if generated_class_jar else [],
593                transitive = [
594                    dep.annotation_processing.transitive_class_jars
595                    for dep in concatenated_deps.deps_exports
596                    if dep.annotation_processing
597                ],
598            ),
599            transitive_source_jars = depset(
600                direct = [generated_source_jar] if generated_source_jar else [],
601                transitive = [
602                    dep.annotation_processing.transitive_source_jars
603                    for dep in concatenated_deps.deps_exports
604                    if dep.annotation_processing
605                ],
606            ),
607            processor_classnames = [],
608            processor_classpath = depset(),
609        ),
610        "_transitive_full_compile_time_jars": depset(
611            order = "preorder",
612            direct = [output_jar],
613            transitive = [dep._transitive_full_compile_time_jars for dep in concatenated_deps.exports_deps],
614        ),
615        "_compile_time_java_dependencies": depset(
616            order = "preorder",
617            transitive = [dep._compile_time_java_dependencies for dep in exports] +
618                         ([depset([compile_jdeps])] if compile_jdeps else []),
619        ),
620        "_neverlink": bool(neverlink),
621        "compilation_info": None,
622        "_constraints": [],
623    }
624
625    if get_internal_java_common().google_legacy_api_enabled():
626        transitive_cc_infos = [dep.cc_link_params_info for dep in concatenated_deps.runtimedeps_exports_deps]
627        transitive_cc_infos.extend(native_libraries)
628        cc_info = semantics.minimize_cc_info(cc_common.merge_cc_infos(cc_infos = transitive_cc_infos))
629        result.update(
630            cc_link_params_info = cc_info,
631            transitive_native_libraries = cc_info.transitive_native_libraries(),
632        )
633    else:
634        result.update(
635            transitive_native_libraries = depset(
636                order = "topological",
637                transitive = [dep.transitive_native_libraries for dep in concatenated_deps.runtimedeps_exports_deps] +
638                             ([cc_common.merge_cc_infos(cc_infos = native_libraries).transitive_native_libraries()] if native_libraries else []),
639            ),
640        )
641    return result, concatenated_deps
642
643def _javainfo_init(
644        output_jar,
645        compile_jar,
646        source_jar = None,
647        compile_jdeps = None,
648        generated_class_jar = None,
649        generated_source_jar = None,
650        native_headers_jar = None,
651        manifest_proto = None,
652        neverlink = False,
653        deps = [],
654        runtime_deps = [],
655        exports = [],
656        exported_plugins = [],
657        jdeps = None,
658        native_libraries = [],
659        add_exports = [],
660        add_opens = []):
661    """The JavaInfo constructor
662
663    Args:
664        output_jar: (File) The jar that was created as a result of a compilation.
665        compile_jar: (File) A jar that is the compile-time dependency in lieu of `output_jar`.
666        source_jar: (File) The source jar that was used to create the output jar. Optional.
667        compile_jdeps: (File) jdeps information about compile time dependencies to be consumed by
668            JavaCompileAction. This should be a binary proto encoded using the deps.proto protobuf
669            included with Bazel. If available this file is typically produced by a header compiler.
670            Optional.
671        generated_class_jar: (File) A jar file containing class files compiled from sources
672            generated during annotation processing. Optional.
673        generated_source_jar: (File) The source jar that was created as a result of annotation
674            processing. Optional.
675        native_headers_jar: (File) A jar containing CC header files supporting native method
676            implementation (typically output of javac -h). Optional.
677        manifest_proto: (File) Manifest information for the rule output (if available). This should
678            be a binary proto encoded using the manifest.proto protobuf included with Bazel. IDEs
679            and other tools can use this information for more efficient processing. Optional.
680        neverlink: (bool) If true, only use this library for compilation and not at runtime.
681        deps: ([JavaInfo]) Compile time dependencies that were used to create the output jar.
682        runtime_deps: ([JavaInfo]) Runtime dependencies that are needed for this library.
683        exports: ([JavaInfo]) Libraries to make available for users of this library.
684        exported_plugins: ([JavaPluginInfo]) Optional. A list of exported plugins.
685        jdeps: (File) jdeps information for the rule output (if available). This should be a binary
686            proto encoded using the deps.proto protobuf included with Bazel. If available this file
687            is typically produced by a compiler. IDEs and other tools can use this information for
688            more efficient processing. Optional.
689        native_libraries: ([CcInfo]) Native library dependencies that are needed for this library.
690        add_exports: ([str]) The <module>/<package>s this library was given access to.
691        add_opens: ([str]) The <module>/<package>s this library was given reflective access to.
692
693    Returns:
694        (dict) arguments to the JavaInfo provider constructor
695    """
696    if add_exports or add_opens:
697        semantics.check_java_info_opens_exports()
698
699    result, concatenated_deps = _javainfo_init_base(
700        output_jar,
701        compile_jar,
702        source_jar,
703        deps,
704        runtime_deps,
705        exports,
706        exported_plugins,
707        jdeps,
708        compile_jdeps,
709        native_headers_jar,
710        manifest_proto,
711        generated_class_jar,
712        generated_source_jar,
713        native_libraries,
714        neverlink,
715    )
716
717    if neverlink:
718        transitive_runtime_jars = depset()
719    else:
720        transitive_runtime_jars = depset(
721            order = "preorder",
722            direct = [output_jar],
723            transitive = [dep.transitive_runtime_jars for dep in concatenated_deps.exports_deps + runtime_deps],
724        )
725
726    # For backward compatibility, we use deps_exports for add_exports/add_opens
727    # for the JavaInfo constructor rather than runtimedeps_exports_deps (used
728    # by java_info_for_compilation). However, runtimedeps_exports_deps makes
729    # more sense, since add_exports/add_opens from runtime_deps are needed at
730    # runtime anyway.
731    #
732    # TODO: When this flag is removed, move this logic into _javainfo_init_base
733    #  and remove the special case from java_info_for_compilation.
734    module_flags_deps = concatenated_deps.deps_exports
735    if get_internal_java_common().incompatible_java_info_merge_runtime_module_flags():
736        module_flags_deps = concatenated_deps.runtimedeps_exports_deps
737
738    result.update(
739        transitive_runtime_jars = transitive_runtime_jars,
740        transitive_source_jars = depset(
741            direct = [source_jar] if source_jar else [],
742            # TODO(hvd): native also adds source jars from deps, but this should be unnecessary
743            transitive = [
744                dep.transitive_source_jars
745                for dep in deps + runtime_deps + exports
746            ],
747        ),
748        module_flags_info = _create_module_flags_info(
749            add_exports = depset(add_exports, transitive = [
750                dep.module_flags_info.add_exports
751                for dep in module_flags_deps
752            ]),
753            add_opens = depset(add_opens, transitive = [
754                dep.module_flags_info.add_opens
755                for dep in module_flags_deps
756            ]),
757        ),
758    )
759    return result
760
761JavaInfo, _new_javainfo = provider(
762    doc = "Info object encapsulating all information by java rules.",
763    fields = {
764        "transitive_runtime_jars": """(depset[File]) A transitive set of jars required on the
765        runtime classpath.
766        <p/>Note: for binary targets (such as java_binary and java_test), this is empty, since such
767        targets are not intended to be dependencies of other Java targets.
768        """,
769        "transitive_compile_time_jars": """(depset[File]) The transitive set of jars required to
770        build the target.
771        <p/>Note: for binary targets (such as java_binary and java_test), this is empty, since such
772        targets are not intended to be dependencies of other Java targets.
773        """,
774        "compile_jars": """(depset[File]) The jars required directly at compile time. They can be interface jars
775                (ijar or hjar), regular jars or both, depending on whether rule
776                implementations chose to create interface jars or not.""",
777        "full_compile_jars": """(depset[File]) The regular, full compile time Jars required by this target directly.
778                They can be:
779                 - the corresponding regular Jars of the interface Jars returned by JavaInfo.compile_jars
780                 - the regular (full) Jars returned by JavaInfo.compile_jars
781
782                Note: JavaInfo.compile_jars can return a mix of interface Jars and
783                regular Jars.<p>Only use this method if interface Jars don't work with
784                your rule set(s) (e.g. some Scala targets) If you're working with
785                Java-only targets it's preferable to use interface Jars via
786                JavaInfo.compile_jars""",
787        "source_jars": """([File]) A list of Jars with all the source files (including those generated by
788                annotations) of the target itself, i.e. NOT including the sources of the
789                transitive dependencies.""",
790        "outputs": "Deprecated: use java_outputs.",
791        "annotation_processing": "Deprecated: Please use plugins instead.",
792        "runtime_output_jars": "([File]) A list of runtime Jars created by this Java/Java-like target.",
793        "transitive_source_jars": "(depset[File]) The Jars of all source files in the transitive closure.",
794        "transitive_native_libraries": """(depset[LibraryToLink]) The transitive set of CC native
795                libraries required by the target.""",
796        "cc_link_params_info": "Deprecated. Do not use. C++ libraries to be linked into Java targets.",
797        "module_flags_info": "(_ModuleFlagsInfo) The Java module flag configuration.",
798        "plugins": """(_JavaPluginDataInfo) Data about all plugins that a consuming target should
799               apply.
800               This is typically either a `java_plugin` itself or a `java_library` exporting
801               one or more plugins.
802               A `java_library` runs annotation processing with all plugins from this field
803               appearing in <code>deps</code> and `plugins` attributes.""",
804        "api_generating_plugins": """"(_JavaPluginDataInfo) Data about API generating plugins
805               defined or exported by this target.
806               Those annotation processors are applied to a Java target before
807               producing its header jars (which contain method signatures). When
808               no API plugins are present, header jars are generated from the
809               sources, reducing critical path.
810               The `api_generating_plugins` is a subset of `plugins`.""",
811        "java_outputs": "(_JavaOutputInfo) Information about outputs of this Java/Java-like target.",
812        "compilation_info": """(java_compilation_info) Compilation information for this
813               Java/Java-like target.""",
814        "_transitive_full_compile_time_jars": "internal API, do not use",
815        "_compile_time_java_dependencies": "internal API, do not use",
816        "_neverlink": "internal API, do not use",
817        "_constraints": "internal API, do not use",
818        "_is_binary": "internal API, do not use",
819    },
820    init = _javainfo_init,
821)
822
823JavaPluginDataInfo = provider(
824    doc = "Provider encapsulating information about a Java compatible plugin.",
825    fields = {
826        "processor_classes": "depset(str) The fully qualified classnames of entry points for the compiler",
827        "processor_jars": "depset(file) Deps containing an annotation processor",
828        "processor_data": "depset(file) Files needed during execution",
829    },
830)
831
832_EMPTY_PLUGIN_DATA = JavaPluginDataInfo(
833    processor_classes = depset(),
834    processor_jars = depset(),
835    processor_data = depset(),
836)
837
838def _create_plugin_data_info(*, processor_classes, processor_jars, processor_data):
839    if processor_classes or processor_jars or processor_data:
840        return JavaPluginDataInfo(
841            processor_classes = processor_classes,
842            processor_jars = processor_jars,
843            processor_data = processor_data,
844        )
845    else:
846        return _EMPTY_PLUGIN_DATA
847
848def disable_plugin_info_annotation_processing(plugin_info):
849    """Returns a copy of the provided JavaPluginInfo without annotation processing info
850
851    Args:
852        plugin_info: (JavaPluginInfo) the instance to transform
853
854    Returns:
855        (JavaPluginInfo) a new, transformed instance.
856     """
857    return _new_javaplugininfo(
858        plugins = _create_plugin_data_info(
859            processor_classes = depset(order = "preorder"),
860            # Preserve the processor path, since it may contain Error Prone plugins
861            # which will be service-loaded by JavaBuilder.
862            processor_jars = plugin_info.plugins.processor_jars,
863            # Preserve data, which may be used by Error Prone plugins.
864            processor_data = plugin_info.plugins.processor_data,
865        ),
866        api_generating_plugins = _EMPTY_PLUGIN_DATA,
867        java_outputs = plugin_info.java_outputs,
868    )
869
870def merge_plugin_info_without_outputs(infos):
871    """ Merge plugin information from a list of JavaPluginInfo or JavaInfo
872
873    Args:
874        infos: ([JavaPluginInfo|JavaInfo]) list of providers to merge
875
876    Returns:
877        (JavaPluginInfo)
878    """
879    plugins = []
880    api_generating_plugins = []
881    for info in infos:
882        if _has_plugin_data(info.plugins):
883            plugins.append(info.plugins)
884        if _has_plugin_data(info.api_generating_plugins):
885            api_generating_plugins.append(info.api_generating_plugins)
886    return _new_javaplugininfo(
887        plugins = _merge_plugin_data(plugins),
888        api_generating_plugins = _merge_plugin_data(api_generating_plugins),
889        java_outputs = [],
890    )
891
892def _has_plugin_data(plugin_data):
893    return plugin_data and (
894        plugin_data.processor_classes or
895        plugin_data.processor_jars or
896        plugin_data.processor_data
897    )
898
899def _merge_plugin_data(datas):
900    return _create_plugin_data_info(
901        processor_classes = depset(transitive = [p.processor_classes for p in datas]),
902        processor_jars = depset(transitive = [p.processor_jars for p in datas]),
903        processor_data = depset(transitive = [p.processor_data for p in datas]),
904    )
905
906def _javaplugininfo_init(
907        runtime_deps,
908        processor_class,
909        data = [],
910        generates_api = False):
911    """ Constructs JavaPluginInfo
912
913    Args:
914        runtime_deps: ([JavaInfo]) list of deps containing an annotation
915             processor.
916        processor_class: (String) The fully qualified class name that the Java
917             compiler uses as an entry point to the annotation processor.
918        data: (depset[File]) The files needed by this annotation
919             processor during execution.
920        generates_api: (boolean) Set to true when this annotation processor
921            generates API code. Such an annotation processor is applied to a
922            Java target before producing its header jars (which contains method
923            signatures). When no API plugins are present, header jars are
924            generated from the sources, reducing the critical path.
925            WARNING: This parameter affects build performance, use it only if
926            necessary.
927
928    Returns:
929        (JavaPluginInfo)
930    """
931
932    java_infos = merge(runtime_deps)
933    processor_data = data if type(data) == "depset" else depset(data)
934    plugins = _create_plugin_data_info(
935        processor_classes = depset([processor_class]) if processor_class else depset(),
936        processor_jars = java_infos.transitive_runtime_jars,
937        processor_data = processor_data,
938    )
939    return {
940        "plugins": plugins,
941        "api_generating_plugins": plugins if generates_api else _EMPTY_PLUGIN_DATA,
942        "java_outputs": java_infos.java_outputs,
943    }
944
945JavaPluginInfo, _new_javaplugininfo = provider(
946    doc = "Provider encapsulating information about Java plugins.",
947    fields = {
948        "plugins": """
949            Returns data about all plugins that a consuming target should apply.
950            This is typically either a <code>java_plugin</code> itself or a
951            <code>java_library</code> exporting one or more plugins.
952            A <code>java_library</code> runs annotation processing with all
953            plugins from this field appearing in <code>deps</code> and
954            <code>plugins</code> attributes.""",
955        "api_generating_plugins": """
956            Returns data about API generating plugins defined or exported by
957            this target.
958            Those annotation processors are applied to a Java target before
959            producing its header jars (which contain method signatures). When
960            no API plugins are present, header jars are generated from the
961            sources, reducing critical path.
962            The <code>api_generating_plugins</code> is a subset of
963            <code>plugins</code>.""",
964        "java_outputs": """
965            Returns information about outputs of this Java/Java-like target.
966        """,
967    },
968    init = _javaplugininfo_init,
969)
970