xref: /aosp_15_r20/external/bazelbuild-kotlin-rules/kotlin/jvm_library.internal.bzl (revision 3a22c0a33dd99bcca39a024d43e6fbcc55c2806e)
1# Copyright 2022 Google LLC. 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"""Kotlin kt_jvm_library rule."""
16
17load("//kotlin:compiler_opt.bzl", "kotlincopts_attrs", "merge_kotlincopts")
18load("//toolchains/kotlin_jvm:androidlint_toolchains.bzl", "androidlint_toolchains")
19load("//toolchains/kotlin_jvm:java_toolchains.bzl", "java_toolchains")
20load("//toolchains/kotlin_jvm:kt_jvm_toolchains.bzl", "kt_jvm_toolchains")
21load("@bazel_skylib//lib:dicts.bzl", "dicts")
22load("//bazel:stubs.bzl", "lint_actions")
23load(":common.bzl", "common")
24load(":compiler_plugin.bzl", "KtCompilerPluginInfo")
25load(":traverse_exports.bzl", "kt_traverse_exports")
26load(":jvm_compile.bzl", "kt_jvm_compile")
27
28# TODO: Use this function in all Kotlin rules
29def _make_default_info(ctx, direct_files, propagated_attrs):
30    # Collect runfiles from deps
31    transitive_runfiles = []
32    for p in common.collect_providers(DefaultInfo, propagated_attrs):
33        transitive_runfiles.append(p.data_runfiles.files)
34        transitive_runfiles.append(p.default_runfiles.files)
35    runfiles = ctx.runfiles(
36        files = direct_files,
37        transitive_files = depset(transitive = transitive_runfiles),
38        collect_default = True,  # handles data attribute
39    )
40
41    return DefaultInfo(
42        files = depset(direct_files),
43        runfiles = runfiles,
44    )
45
46def _jvm_library_impl(ctx):
47    kt_jvm_toolchain = kt_jvm_toolchains.get(ctx)
48
49    for target in ctx.attr.runtime_deps:
50        if (JavaInfo not in target) and (CcInfo not in target):
51            fail("Unexpected runtime dependency (must provide JavaInfo or CcInfo): " + str(target.label))
52
53    if not ctx.files.srcs and not ctx.files.common_srcs and not ctx.attr.exports and not ctx.attr.exported_plugins:
54        fail("Expected a source-bearing or an export-oriented target:\n" +
55             "One of {srcs, common_srcs, exports, exported_plugins} of target %s must be non empty" % ctx.label)
56
57    compile_result = kt_jvm_compile(
58        ctx,
59        output = ctx.outputs.jar,
60        srcs = ctx.files.srcs,
61        common_srcs = ctx.files.common_srcs,
62        deps = ctx.attr.deps,
63        plugins = ctx.attr.plugins,
64        exported_plugins = ctx.attr.exported_plugins,
65        runtime_deps = ctx.attr.runtime_deps,
66        exports = ctx.attr.exports,
67        javacopts = ctx.attr.javacopts,
68        kotlincopts = merge_kotlincopts(ctx),
69        neverlink = ctx.attr.neverlink,
70        testonly = ctx.attr.testonly,
71                android_lint_plugins = ctx.attr._android_lint_plugins,
72        manifest = None,
73        merged_manifest = None,
74        resource_files = [],
75        classpath_resources = ctx.files.resources,
76        kt_toolchain = kt_jvm_toolchain,
77        java_toolchain = java_toolchains.get(ctx),
78        disable_lint_checks = ctx.attr.disable_lint_checks,
79        rule_family = common.RULE_FAMILY.JVM_LIBRARY,
80    )
81
82    java_info = compile_result.java_info
83
84    # Collect and validate proguard_specs
85    # TODO should also propagate IDL proguard_specs when there's idl_srcs
86    transitive_proguard_configs = common.collect_proguard_specs(
87        ctx,
88        ctx.files.proguard_specs,
89        ctx.attr.deps + ctx.attr.exports,
90        kt_jvm_toolchain.proguard_whitelister,
91    )
92
93    # Create OutputGroupInfo
94    output_groups = dict(
95        _validation = depset(compile_result.validations),
96        _source_jars = depset(
97            java_info.source_jars,
98            transitive = [java_info.transitive_source_jars],
99        ),
100        _direct_source_jars = depset(java_info.source_jars),
101        _hidden_top_level_INTERNAL_ = depset(
102            transitive = [
103                info._hidden_top_level_INTERNAL_
104                for info in common.collect_providers(
105                    OutputGroupInfo,
106                    ctx.attr.deps + ctx.attr.exports,
107                )
108            ] + [transitive_proguard_configs],
109        ),
110    )
111
112    return [
113        java_info,
114        ProguardSpecProvider(transitive_proguard_configs),
115        _make_default_info(
116            ctx,
117            [ctx.outputs.jar],
118            propagated_attrs = ctx.attr.deps + ctx.attr.runtime_deps + ctx.attr.exports,
119        ),
120        OutputGroupInfo(**output_groups),
121        coverage_common.instrumented_files_info(
122            ctx,
123            source_attributes = ["srcs", "common_srcs"],
124            dependency_attributes = ["data", "deps", "resources", "runtime_deps"],
125        ),
126    ]
127
128_KT_JVM_LIBRARY_ATTRS = dicts.add(
129    androidlint_toolchains.attrs,
130    java_toolchains.attrs,
131    kotlincopts_attrs(),
132    kt_jvm_toolchains.attrs,
133    common_srcs = attr.label_list(
134        allow_files = common.KT_FILE_TYPES,
135        allow_empty = True,
136        doc = """The list of common multi-platform source files that are processed to create
137                 the target.""",
138    ),
139    data = attr.label_list(
140        allow_files = True,
141    ),
142    deps = attr.label_list(
143        providers = [
144            # Each provider-set expands on allow_rules
145            [JavaInfo],
146        ],
147        aspects = [
148            kt_traverse_exports.aspect,
149        ],
150        doc = """The list of libraries this library directly depends on at compile-time. For Java
151                     and Kotlin libraries listed, the Jars they build as well as the transitive closure
152                     of their `deps` and `exports` will be on the compile-time classpath for this rule;
153                     also, the transitive closure of their `deps`, `runtime_deps`, and `exports` will be
154                     on the runtime classpath (excluding dependencies only depended on as `neverlink`).
155
156                     Note on strict_deps: any Java type explicitly or implicitly referred to in `srcs`
157                     must be included here. This is a stronger requirement than what is enforced for
158                     `java_library`. Any build failures resulting from this requirement will include the
159                     missing dependencies and a command to fix the rule.""",
160    ),
161    disable_lint_checks = attr.string_list(
162        doc = """A list of lint checks to be skipped for this target.""",
163    ),
164    exported_plugins = attr.label_list(
165        providers = [
166            [JavaPluginInfo],
167            [KtCompilerPluginInfo],
168            [lint_actions.AndroidLintRulesetInfo],
169        ],
170        cfg = "exec",
171        doc = """JVM plugins to export to users.
172
173                     Every plugin listed will run during compliations that depend on this target, as
174                     if it were listed directly in that target's `plugins` attribute. `java_*` targets
175                     will not run kotlinc plugins""",
176    ),
177    exports = attr.label_list(
178        providers = [
179            # Each provider-set expands on allow_rules
180            [JavaInfo],
181        ],
182        aspects = [
183            kt_traverse_exports.aspect,
184        ],
185        doc = """List of libraries treated as if they were part of this library by upstream
186                     Java/Kotlin dependencies, see go/be-java#java_library.exports. These libraries
187                     are **not** automatically also dependencies of this library.""",
188    ),
189    javacopts = attr.string_list(
190        doc = """Additional flags to pass to javac if used as part of this rule, which is the case
191                     if `.java` `srcs` are provided or annotation processors generate sources for this
192                     rule.""",
193    ),
194    neverlink = attr.bool(
195        default = False,
196        doc = """Only use this library for compilation and not at runtime. Useful if the library
197                  will be provided by the runtime environment during execution.""",
198    ),
199    plugins = attr.label_list(
200        providers = [
201            [JavaPluginInfo],
202            [KtCompilerPluginInfo],
203            [lint_actions.AndroidLintRulesetInfo],
204        ],
205        cfg = "exec",
206        doc = """JVM plugins to run during compilation.
207
208                     Every plugin listed will run whenever this library is built. Resources generated by the
209                     plugin will be included in the output JAR. A library may also inherit plugins from
210                     dependencies that use `exported_plugins`.""",
211    ),
212    proguard_specs = attr.label_list(
213        allow_files = True,
214        doc = """Proguard specifications to go along with this library.""",
215    ),
216    resources = attr.label_list(
217        allow_files = True,
218        doc = """A list of data files to include in the Jar, see
219                         go/be#java_library.resources.""",
220    ),
221    runtime_deps = attr.label_list(
222        providers = [
223            # Each provider-set expands on allow_rules
224            [JavaInfo],
225            [CcInfo],  # for JNI / native dependencies
226        ],
227        aspects = [
228            kt_traverse_exports.aspect,
229        ],
230        doc = """Runtime-only dependencies.""",
231    ),
232    srcs = attr.label_list(
233        allow_files = common.KT_JVM_FILE_TYPES,
234        allow_empty = True,
235        doc = """The list of source files that are processed to create the target.
236                 To support circular dependencies, this can include `.kt` and `.java` files.""",
237    ),
238    _android_lint_plugins = attr.label_list(
239        providers = [lint_actions.AndroidLintRulesetInfo],
240        cfg = "exec",
241        doc = """Additional Android Lint checks to run at compile-time.""",
242    ),
243)
244
245kt_jvm_library_helper = rule(
246    attrs = _KT_JVM_LIBRARY_ATTRS,
247    fragments = ["java"],
248    outputs = dict(
249        jar = "lib%{name}.jar",
250        srcjar = "lib%{name}-src.jar",  # implicit declared output for consistency with java_library
251    ),
252    provides = [JavaInfo],
253    implementation = _jvm_library_impl,
254    toolchains = [kt_jvm_toolchains.type, "@bazel_tools//tools/jdk:toolchain_type"],
255    doc = """This rule compiles Kotlin (and Java) sources into a Jar file. Most Java-like libraries
256             and binaries can depend on this rule, and this rule can in turn depend on Kotlin and
257             Java libraries. This rule supports a subset of attributes supported by `java_library`.
258             In addition to documentation provided as part of this rule, please also refer to their
259             documentation as part of `java_library`.""",
260)
261