xref: /aosp_15_r20/external/bazelbuild-kotlin-rules/kotlin/common.bzl (revision 3a22c0a33dd99bcca39a024d43e6fbcc55c2806e)
1*3a22c0a3SAlix# Copyright 2022 Google LLC. All rights reserved.
2*3a22c0a3SAlix#
3*3a22c0a3SAlix# Licensed under the Apache License, Version 2.0 (the License);
4*3a22c0a3SAlix# you may not use this file except in compliance with the License.
5*3a22c0a3SAlix# You may obtain a copy of the License at
6*3a22c0a3SAlix#
7*3a22c0a3SAlix#     http://www.apache.org/licenses/LICENSE-2.0
8*3a22c0a3SAlix#
9*3a22c0a3SAlix# Unless required by applicable law or agreed to in writing, software
10*3a22c0a3SAlix# distributed under the License is distributed on an "AS IS" BASIS,
11*3a22c0a3SAlix# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12*3a22c0a3SAlix# See the License for the specific language governing permissions and
13*3a22c0a3SAlix# limitations under the License.
14*3a22c0a3SAlix
15*3a22c0a3SAlix"""Common Kotlin definitions."""
16*3a22c0a3SAlix
17*3a22c0a3SAlixload("//:visibility.bzl", "RULES_DEFS_THAT_COMPILE_KOTLIN")
18*3a22c0a3SAlixload("//kotlin/jvm/util:file_factory.bzl", "FileFactory")
19*3a22c0a3SAlixload("//kotlin/jvm/util:srcjars.bzl", "kt_srcjars")
20*3a22c0a3SAlixload("//toolchains/kotlin_jvm:androidlint_toolchains.bzl", "androidlint_toolchains")
21*3a22c0a3SAlixload("//toolchains/kotlin_jvm:kt_jvm_toolchains.bzl", "kt_jvm_toolchains")
22*3a22c0a3SAlixload("@bazel_skylib//lib:sets.bzl", "sets")
23*3a22c0a3SAlixload("//bazel:stubs.bzl", "lint_actions")
24*3a22c0a3SAlixload("//bazel:stubs.bzl", "jspecify_flags")
25*3a22c0a3SAlixload("//bazel:stubs.bzl", "is_android_lint_exempt")
26*3a22c0a3SAlixload("//bazel:stubs.bzl", "BASE_JVMOPTS")
27*3a22c0a3SAlix
28*3a22c0a3SAlixvisibility(RULES_DEFS_THAT_COMPILE_KOTLIN)
29*3a22c0a3SAlix
30*3a22c0a3SAlix# TODO: Remove the _ALLOWED_*_RULES lists to determine which rules
31*3a22c0a3SAlix# are accepted dependencies to Kotlin rules as the approach does not scale
32*3a22c0a3SAlix# because it will require a cl + release for every new rule.
33*3a22c0a3SAlix
34*3a22c0a3SAlix_EXT = struct(
35*3a22c0a3SAlix    KT = ".kt",
36*3a22c0a3SAlix    JAVA = ".java",
37*3a22c0a3SAlix    JAR = ".jar",
38*3a22c0a3SAlix    SRCJAR = ".srcjar",
39*3a22c0a3SAlix)
40*3a22c0a3SAlix
41*3a22c0a3SAlix_KT_FILE_TYPES = [_EXT.KT]
42*3a22c0a3SAlix
43*3a22c0a3SAlix_KT_JVM_FILE_TYPES = [
44*3a22c0a3SAlix    _EXT.JAVA,
45*3a22c0a3SAlix    _EXT.KT,
46*3a22c0a3SAlix    _EXT.SRCJAR,
47*3a22c0a3SAlix]
48*3a22c0a3SAlix
49*3a22c0a3SAlix_JAR_FILE_TYPE = [_EXT.JAR]
50*3a22c0a3SAlix
51*3a22c0a3SAlix_SRCJAR_FILE_TYPES = [_EXT.JAR, _EXT.SRCJAR]
52*3a22c0a3SAlix
53*3a22c0a3SAlix_RULE_FAMILY = struct(
54*3a22c0a3SAlix    UNKNOWN = 0,
55*3a22c0a3SAlix    JVM_LIBRARY = 1,
56*3a22c0a3SAlix    ANDROID_LIBRARY = 2,
57*3a22c0a3SAlix)
58*3a22c0a3SAlix
59*3a22c0a3SAlixdef _is_dir(file, basename):
60*3a22c0a3SAlix    return file.is_directory and file.basename == basename
61*3a22c0a3SAlix
62*3a22c0a3SAlixdef _is_file(file, extension):
63*3a22c0a3SAlix    return (not file.is_directory) and file.path.endswith(extension)
64*3a22c0a3SAlix
65*3a22c0a3SAlixdef _is_kt_src(src):
66*3a22c0a3SAlix    """Decides if `src` Kotlin code.
67*3a22c0a3SAlix
68*3a22c0a3SAlix    Either:
69*3a22c0a3SAlix      -  a Kotlin source file
70*3a22c0a3SAlix      -  a tree-artifact expected to contain only Kotlin source files
71*3a22c0a3SAlix    """
72*3a22c0a3SAlix
73*3a22c0a3SAlix    return _is_file(src, _EXT.KT) or _is_dir(src, "kotlin")
74*3a22c0a3SAlix
75*3a22c0a3SAlix# Compute module name based on target (b/139403883), similar to Swift
76*3a22c0a3SAlixdef _derive_module_name(ctx):
77*3a22c0a3SAlix    label = _get_original_kt_target_label(ctx)
78*3a22c0a3SAlix    package_part = label.package.replace("/", ".")  # .package has no leading '//'
79*3a22c0a3SAlix    name_part = label.name
80*3a22c0a3SAlix    if package_part:
81*3a22c0a3SAlix        return package_part + "_" + name_part
82*3a22c0a3SAlix    return name_part
83*3a22c0a3SAlix
84*3a22c0a3SAlixdef _get_common_and_user_kotlinc_args(ctx, toolchain, extra_kotlinc_args):
85*3a22c0a3SAlix    return toolchain.kotlinc_cli_flags + [
86*3a22c0a3SAlix        # Set module name so module-level metadata is preserved when merging Jars (b/139403883)
87*3a22c0a3SAlix        "-module-name",
88*3a22c0a3SAlix        _derive_module_name(ctx),
89*3a22c0a3SAlix    ] + jspecify_flags(ctx) + extra_kotlinc_args
90*3a22c0a3SAlix
91*3a22c0a3SAlixdef _kt_plugins_map(
92*3a22c0a3SAlix        android_lint_rulesets = [],
93*3a22c0a3SAlix        java_plugin_datas = depset(),
94*3a22c0a3SAlix        java_plugin_infos = [],
95*3a22c0a3SAlix        kt_codegen_plugin_infos = depset(),
96*3a22c0a3SAlix        kt_compiler_plugin_infos = []):
97*3a22c0a3SAlix    """A struct containing all the plugin types understood by rules_kotlin.
98*3a22c0a3SAlix
99*3a22c0a3SAlix    Args:
100*3a22c0a3SAlix        android_lint_rulesets: (list[lint_actions.AndroidLintRulesInfo]) Android Lint checkers.
101*3a22c0a3SAlix            Each JAR is self-contained and should be loaded in an isolated classloader.
102*3a22c0a3SAlix        java_plugin_datas: (depset[JavaPluginData]) for KtCodegenProcessing.
103*3a22c0a3SAlix        java_plugin_infos: (list[JavaPluginInfo])
104*3a22c0a3SAlix        kt_codegen_plugin_infos: (depset[KtCodegenPluginInfo]) for KtCodegenProcessing.
105*3a22c0a3SAlix        kt_compiler_plugin_infos: (list[KtCompilerPluginInfo])
106*3a22c0a3SAlix    """
107*3a22c0a3SAlix    return struct(
108*3a22c0a3SAlix        android_lint_rulesets = android_lint_rulesets,
109*3a22c0a3SAlix        java_plugin_datas = java_plugin_datas,
110*3a22c0a3SAlix        java_plugin_infos = java_plugin_infos,
111*3a22c0a3SAlix        kt_codegen_plugin_infos = kt_codegen_plugin_infos,
112*3a22c0a3SAlix        kt_compiler_plugin_infos = kt_compiler_plugin_infos,
113*3a22c0a3SAlix    )
114*3a22c0a3SAlix
115*3a22c0a3SAlixdef _run_kotlinc(
116*3a22c0a3SAlix        ctx,
117*3a22c0a3SAlix        file_factory,
118*3a22c0a3SAlix        kt_srcs = [],
119*3a22c0a3SAlix        common_srcs = [],
120*3a22c0a3SAlix        java_srcs_and_dirs = [],
121*3a22c0a3SAlix        kotlincopts = [],
122*3a22c0a3SAlix        compile_jdeps = depset(),
123*3a22c0a3SAlix        toolchain = None,
124*3a22c0a3SAlix        classpath = [],
125*3a22c0a3SAlix        directdep_jars = depset(),
126*3a22c0a3SAlix        plugins = _kt_plugins_map(),
127*3a22c0a3SAlix        friend_jars = depset(),
128*3a22c0a3SAlix        enforce_strict_deps = False,
129*3a22c0a3SAlix        enforce_complete_jdeps = False,
130*3a22c0a3SAlix        mnemonic = None,
131*3a22c0a3SAlix        message_prefix = ""):
132*3a22c0a3SAlix    direct_inputs = []
133*3a22c0a3SAlix    transitive_inputs = []
134*3a22c0a3SAlix    outputs = []
135*3a22c0a3SAlix
136*3a22c0a3SAlix    # Args to kotlinc.
137*3a22c0a3SAlix    #
138*3a22c0a3SAlix    # These go at the end of the commandline. They should be passed through all wrapper
139*3a22c0a3SAlix    # layers without post-processing, except to unpack param files.
140*3a22c0a3SAlix    kotlinc_args = ctx.actions.args()
141*3a22c0a3SAlix    kotlinc_args.use_param_file("@%s", use_always = True)  # Use params file to handle long classpaths (b/76185759)
142*3a22c0a3SAlix    kotlinc_args.set_param_file_format("multiline")  # kotlinc only supports double-quotes ("): https://youtrack.jetbrains.com/issue/KT-24472
143*3a22c0a3SAlix
144*3a22c0a3SAlix    # Args to the kotlinc JVM
145*3a22c0a3SAlix    #
146*3a22c0a3SAlix    # These cannot use a param file because the file wouldn't be read until after the JVM launches.
147*3a22c0a3SAlix    # Values will be prepended with --jvm_flag= for detection.
148*3a22c0a3SAlix    jvm_args = []
149*3a22c0a3SAlix
150*3a22c0a3SAlix    kotlinc_args.add_joined("-cp", classpath, join_with = ":")
151*3a22c0a3SAlix    transitive_inputs.append(classpath)
152*3a22c0a3SAlix    kotlinc_args.add_all(_get_common_and_user_kotlinc_args(ctx, toolchain, kotlincopts))
153*3a22c0a3SAlix
154*3a22c0a3SAlix    kotlinc_args.add(toolchain.jvm_abi_gen_plugin, format = "-Xplugin=%s")
155*3a22c0a3SAlix    direct_inputs.append(toolchain.jvm_abi_gen_plugin)
156*3a22c0a3SAlix    kt_ijar = file_factory.declare_file("-ijar.jar")
157*3a22c0a3SAlix    kotlinc_args.add("-P", kt_ijar, format = "plugin:org.jetbrains.kotlin.jvm.abi:outputDir=%s")
158*3a22c0a3SAlix    outputs.append(kt_ijar)
159*3a22c0a3SAlix
160*3a22c0a3SAlix    for p in plugins.kt_compiler_plugin_infos:
161*3a22c0a3SAlix        kotlinc_args.add(p.jar, format = "-Xplugin=%s")
162*3a22c0a3SAlix        direct_inputs.append(p.jar)
163*3a22c0a3SAlix        kotlinc_args.add_all(p.args, before_each = "-P")
164*3a22c0a3SAlix
165*3a22c0a3SAlix    # Common sources must also be specified as -Xcommon-sources= in addition to appearing in the
166*3a22c0a3SAlix    # source list.
167*3a22c0a3SAlix    if common_srcs:
168*3a22c0a3SAlix        kotlinc_args.add("-Xmulti-platform=true")
169*3a22c0a3SAlix        kotlinc_args.add_all(common_srcs, format_each = "-Xcommon-sources=%s")
170*3a22c0a3SAlix        direct_inputs.extend(common_srcs)
171*3a22c0a3SAlix
172*3a22c0a3SAlix    output = file_factory.declare_file(".jar")
173*3a22c0a3SAlix    kotlinc_args.add("-d", output)
174*3a22c0a3SAlix    outputs.insert(0, output)  # The param file name is derived from the 0th output
175*3a22c0a3SAlix    kotlinc_args.add_all(kt_srcs)
176*3a22c0a3SAlix    direct_inputs.extend(kt_srcs)
177*3a22c0a3SAlix    kotlinc_args.add_all(common_srcs)
178*3a22c0a3SAlix    direct_inputs.extend(common_srcs)
179*3a22c0a3SAlix
180*3a22c0a3SAlix    if java_srcs_and_dirs:
181*3a22c0a3SAlix        # This expands any directories into their contained files
182*3a22c0a3SAlix        kotlinc_args.add_all(java_srcs_and_dirs)
183*3a22c0a3SAlix        direct_inputs.extend(java_srcs_and_dirs)
184*3a22c0a3SAlix
185*3a22c0a3SAlix    kotlinc_args.add_joined(friend_jars, format_joined = "-Xfriend-paths=%s", join_with = ",")
186*3a22c0a3SAlix    transitive_inputs.append(friend_jars)
187*3a22c0a3SAlix
188*3a22c0a3SAlix    # Do not change the "shape" or mnemonic of this action without consulting Kythe team
189*3a22c0a3SAlix    # (kythe-eng@), to avoid breaking the Kotlin Kythe extractor which "shadows" this action.  In
190*3a22c0a3SAlix    # particular, the extractor expects this to be a vanilla "spawn" (ctx.actions.run) so don't
191*3a22c0a3SAlix    # change this to ctx.actions.run_shell or something else without considering Kythe implications
192*3a22c0a3SAlix    # (b/112439843).
193*3a22c0a3SAlix    ctx.actions.run(
194*3a22c0a3SAlix        executable = toolchain.kotlin_compiler,
195*3a22c0a3SAlix        arguments = ["--jvm_flag=" + x for x in jvm_args] + [kotlinc_args],
196*3a22c0a3SAlix        inputs = depset(direct = direct_inputs, transitive = transitive_inputs),
197*3a22c0a3SAlix        outputs = outputs,
198*3a22c0a3SAlix        mnemonic = mnemonic,
199*3a22c0a3SAlix        progress_message = message_prefix + str(_get_original_kt_target_label(ctx)),
200*3a22c0a3SAlix        execution_requirements = {
201*3a22c0a3SAlix            # Ensure comparable results across runs (cold builds, same machine)
202*3a22c0a3SAlix            "no-cache": "1",
203*3a22c0a3SAlix            "no-remote": "1",
204*3a22c0a3SAlix        } if toolchain.is_profiling_enabled(ctx.label) else {
205*3a22c0a3SAlix            "worker-key-mnemonic": "Kt2JavaCompile",
206*3a22c0a3SAlix        },
207*3a22c0a3SAlix        toolchain = toolchain.toolchain_type,
208*3a22c0a3SAlix    )
209*3a22c0a3SAlix
210*3a22c0a3SAlix    return struct(
211*3a22c0a3SAlix        output_jar = output,
212*3a22c0a3SAlix        compile_jar = kt_ijar,
213*3a22c0a3SAlix    )
214*3a22c0a3SAlix
215*3a22c0a3SAlixdef _kt_compile(
216*3a22c0a3SAlix        ctx,
217*3a22c0a3SAlix        file_factory,
218*3a22c0a3SAlix        kt_srcs = [],
219*3a22c0a3SAlix        common_srcs = [],
220*3a22c0a3SAlix        coverage_srcs = [],
221*3a22c0a3SAlix        java_srcs_and_dirs = [],
222*3a22c0a3SAlix        kt_hdrs = None,
223*3a22c0a3SAlix        common_hdrs = None,
224*3a22c0a3SAlix        kotlincopts = [],
225*3a22c0a3SAlix        compile_jdeps = depset(),
226*3a22c0a3SAlix        toolchain = None,
227*3a22c0a3SAlix        classpath = [],
228*3a22c0a3SAlix        directdep_jars = depset(),
229*3a22c0a3SAlix        plugins = _kt_plugins_map(),
230*3a22c0a3SAlix        friend_jars = depset(),
231*3a22c0a3SAlix        enforce_strict_deps = False,
232*3a22c0a3SAlix        enforce_complete_jdeps = False):
233*3a22c0a3SAlix    # TODO: don't run jvm-abi-gen plugin here if we have headers
234*3a22c0a3SAlix    kotlinc_full_result = _run_kotlinc(
235*3a22c0a3SAlix        ctx,
236*3a22c0a3SAlix        kt_srcs = kt_srcs,
237*3a22c0a3SAlix        common_srcs = common_srcs,
238*3a22c0a3SAlix        java_srcs_and_dirs = java_srcs_and_dirs,
239*3a22c0a3SAlix        file_factory = file_factory,
240*3a22c0a3SAlix        kotlincopts = kotlincopts,
241*3a22c0a3SAlix        compile_jdeps = compile_jdeps,
242*3a22c0a3SAlix        toolchain = toolchain,
243*3a22c0a3SAlix        classpath = classpath,
244*3a22c0a3SAlix        directdep_jars = directdep_jars,
245*3a22c0a3SAlix        plugins = plugins,
246*3a22c0a3SAlix        friend_jars = friend_jars,
247*3a22c0a3SAlix        enforce_strict_deps = enforce_strict_deps,
248*3a22c0a3SAlix        enforce_complete_jdeps = enforce_complete_jdeps,
249*3a22c0a3SAlix        mnemonic = "Kt2JavaCompile",
250*3a22c0a3SAlix        message_prefix = "Compiling Kotlin For Java Runtime: ",
251*3a22c0a3SAlix    )
252*3a22c0a3SAlix
253*3a22c0a3SAlix    srcjar = kt_srcjars.zip(
254*3a22c0a3SAlix        ctx,
255*3a22c0a3SAlix        toolchain,
256*3a22c0a3SAlix        file_factory.declare_file("-kt-src.jar"),
257*3a22c0a3SAlix        srcs = kt_srcs,
258*3a22c0a3SAlix        common_srcs = common_srcs,
259*3a22c0a3SAlix    )
260*3a22c0a3SAlix
261*3a22c0a3SAlix    output_jar = kotlinc_full_result.output_jar
262*3a22c0a3SAlix    if ctx.coverage_instrumented():
263*3a22c0a3SAlix        output_jar = _offline_instrument_jar(
264*3a22c0a3SAlix            ctx,
265*3a22c0a3SAlix            toolchain,
266*3a22c0a3SAlix            output_jar,
267*3a22c0a3SAlix            kt_srcs + common_srcs + coverage_srcs,
268*3a22c0a3SAlix        )
269*3a22c0a3SAlix
270*3a22c0a3SAlix    # Use un-instrumented Jar at compile-time to avoid double-instrumenting inline functions
271*3a22c0a3SAlix    # (see b/110763361 for the comparable Gradle issue)
272*3a22c0a3SAlix    compile_jar = kotlinc_full_result.compile_jar
273*3a22c0a3SAlix    if toolchain.header_gen_tool:
274*3a22c0a3SAlix        kotlinc_header_result = _run_kotlinc(
275*3a22c0a3SAlix            ctx,
276*3a22c0a3SAlix            kt_srcs = kt_hdrs,
277*3a22c0a3SAlix            common_srcs = common_hdrs,
278*3a22c0a3SAlix            java_srcs_and_dirs = java_srcs_and_dirs,
279*3a22c0a3SAlix            file_factory = file_factory.derive("-abi"),
280*3a22c0a3SAlix            kotlincopts = kotlincopts,
281*3a22c0a3SAlix            compile_jdeps = compile_jdeps,
282*3a22c0a3SAlix            toolchain = toolchain,
283*3a22c0a3SAlix            classpath = classpath,
284*3a22c0a3SAlix            directdep_jars = directdep_jars,
285*3a22c0a3SAlix            plugins = plugins,
286*3a22c0a3SAlix            friend_jars = friend_jars,
287*3a22c0a3SAlix            enforce_strict_deps = enforce_strict_deps,
288*3a22c0a3SAlix            enforce_complete_jdeps = enforce_complete_jdeps,
289*3a22c0a3SAlix            mnemonic = "Kt2JavaHeaderCompile",
290*3a22c0a3SAlix            message_prefix = "Computing Kotlin ABI interface Jar: ",
291*3a22c0a3SAlix        )
292*3a22c0a3SAlix        compile_jar = kotlinc_header_result.compile_jar
293*3a22c0a3SAlix
294*3a22c0a3SAlix    result = dict(
295*3a22c0a3SAlix        output_jar = output_jar,
296*3a22c0a3SAlix        compile_jar = compile_jar,
297*3a22c0a3SAlix        source_jar = srcjar,
298*3a22c0a3SAlix    )
299*3a22c0a3SAlix    return struct(java_info = JavaInfo(**result), **result)
300*3a22c0a3SAlix
301*3a22c0a3SAlixdef _derive_headers(
302*3a22c0a3SAlix        ctx,
303*3a22c0a3SAlix        toolchain,
304*3a22c0a3SAlix        file_factory,
305*3a22c0a3SAlix        srcs):
306*3a22c0a3SAlix    if not srcs or not toolchain.header_gen_tool:
307*3a22c0a3SAlix        return srcs
308*3a22c0a3SAlix
309*3a22c0a3SAlix    output_dir = file_factory.declare_directory("-headers")
310*3a22c0a3SAlix    args = ctx.actions.args()
311*3a22c0a3SAlix    args.add(output_dir.path, format = "-output_dir=%s")
312*3a22c0a3SAlix    args.add_joined(srcs, format_joined = "-sources=%s", join_with = ",")
313*3a22c0a3SAlix    ctx.actions.run(
314*3a22c0a3SAlix        executable = toolchain.header_gen_tool,
315*3a22c0a3SAlix        arguments = [args],
316*3a22c0a3SAlix        inputs = srcs,
317*3a22c0a3SAlix        outputs = [output_dir],
318*3a22c0a3SAlix        mnemonic = "KtDeriveHeaders",
319*3a22c0a3SAlix        progress_message = "Deriving %s: %s" % (output_dir.basename, _get_original_kt_target_label(ctx)),
320*3a22c0a3SAlix        toolchain = toolchain.toolchain_type,
321*3a22c0a3SAlix    )
322*3a22c0a3SAlix    return [output_dir]
323*3a22c0a3SAlix
324*3a22c0a3SAlixdef _get_original_kt_target_label(ctx):
325*3a22c0a3SAlix    label = ctx.label
326*3a22c0a3SAlix    if label.name.find("_DO_NOT_DEPEND") > 0:
327*3a22c0a3SAlix        # Remove rule suffix added by android_library(
328*3a22c0a3SAlix        label = label.relative(":%s" % label.name[0:label.name.find("_DO_NOT_DEPEND")])
329*3a22c0a3SAlix    elif hasattr(ctx.attr, "_kt_codegen_plugin_build_tool") and label.name.endswith("_processed_srcs"):
330*3a22c0a3SAlix        # Remove rule suffix added by kt_codegen_filegroup. b/259984258
331*3a22c0a3SAlix        label = label.relative(":{}".format(label.name.removesuffix("_processed_srcs")))
332*3a22c0a3SAlix    return label
333*3a22c0a3SAlix
334*3a22c0a3SAlixdef _run_import_deps_checker(
335*3a22c0a3SAlix        ctx,
336*3a22c0a3SAlix        jars_to_check = [],
337*3a22c0a3SAlix        merged_deps = None,
338*3a22c0a3SAlix        enforce_strict_deps = True,
339*3a22c0a3SAlix        jdeps_output = None,
340*3a22c0a3SAlix        deps_checker = None,
341*3a22c0a3SAlix        java_toolchain = None):
342*3a22c0a3SAlix    full_classpath = _create_classpath(java_toolchain, [merged_deps])
343*3a22c0a3SAlix    label = _get_original_kt_target_label(ctx)
344*3a22c0a3SAlix
345*3a22c0a3SAlix    args = ctx.actions.args()
346*3a22c0a3SAlix    args.add("--jdeps_output", jdeps_output)
347*3a22c0a3SAlix    args.add_all(jars_to_check, before_each = "--input")
348*3a22c0a3SAlix    args.add_all(java_toolchain.bootclasspath, before_each = "--bootclasspath_entry")
349*3a22c0a3SAlix    args.add_all(full_classpath, before_each = "--classpath_entry")
350*3a22c0a3SAlix    if enforce_strict_deps:
351*3a22c0a3SAlix        args.add_all(merged_deps.compile_jars, before_each = "--directdep")
352*3a22c0a3SAlix    args.add("error" if enforce_strict_deps else "silence", format = "--checking_mode=%s")
353*3a22c0a3SAlix    args.add("--nocheck_missing_members")  # compiler was happy so no need
354*3a22c0a3SAlix    args.add("--rule_label", label)
355*3a22c0a3SAlix
356*3a22c0a3SAlix    ctx.actions.run(
357*3a22c0a3SAlix        executable = deps_checker,
358*3a22c0a3SAlix        arguments = [args],
359*3a22c0a3SAlix        inputs = depset(jars_to_check, transitive = [full_classpath]),
360*3a22c0a3SAlix        outputs = [jdeps_output],
361*3a22c0a3SAlix        mnemonic = "KtCheckStrictDeps" if enforce_strict_deps else "KtJdeps",
362*3a22c0a3SAlix        progress_message = "%s deps for %s" % (
363*3a22c0a3SAlix            "Checking strict" if enforce_strict_deps else "Computing",
364*3a22c0a3SAlix            label,
365*3a22c0a3SAlix        ),
366*3a22c0a3SAlix    )
367*3a22c0a3SAlix
368*3a22c0a3SAlixdef _offline_instrument_jar(ctx, toolchain, jar, srcs = []):
369*3a22c0a3SAlix    if not _is_file(jar, _EXT.JAR):
370*3a22c0a3SAlix        fail("Expect JAR input but got %s" % jar)
371*3a22c0a3SAlix    file_factory = FileFactory(ctx, jar)
372*3a22c0a3SAlix
373*3a22c0a3SAlix    paths_for_coverage_file = file_factory.declare_file("-kt-paths-for-coverage.txt")
374*3a22c0a3SAlix    paths = ctx.actions.args()
375*3a22c0a3SAlix    paths.set_param_file_format("multiline")  # don't shell-quote, just list file names
376*3a22c0a3SAlix    paths.add_all([src for src in srcs if src.is_source])
377*3a22c0a3SAlix    ctx.actions.write(paths_for_coverage_file, paths)
378*3a22c0a3SAlix
379*3a22c0a3SAlix    output = file_factory.declare_file("-instrumented.jar")
380*3a22c0a3SAlix    args = ctx.actions.args()
381*3a22c0a3SAlix    args.add(jar)
382*3a22c0a3SAlix    args.add(output)
383*3a22c0a3SAlix    args.add(paths_for_coverage_file)
384*3a22c0a3SAlix    ctx.actions.run(
385*3a22c0a3SAlix        executable = toolchain.coverage_instrumenter,
386*3a22c0a3SAlix        arguments = [args],
387*3a22c0a3SAlix        inputs = [jar, paths_for_coverage_file],
388*3a22c0a3SAlix        outputs = [output],
389*3a22c0a3SAlix        mnemonic = "KtJaCoCoInstrument",
390*3a22c0a3SAlix        progress_message = "Instrumenting Kotlin for coverage collection: %s" % _get_original_kt_target_label(ctx),
391*3a22c0a3SAlix        toolchain = toolchain.toolchain_type,
392*3a22c0a3SAlix    )
393*3a22c0a3SAlix
394*3a22c0a3SAlix    return output
395*3a22c0a3SAlix
396*3a22c0a3SAlixdef _singlejar(
397*3a22c0a3SAlix        ctx,
398*3a22c0a3SAlix        inputs,
399*3a22c0a3SAlix        output,
400*3a22c0a3SAlix        singlejar,
401*3a22c0a3SAlix        mnemonic = "KtMergeJar",
402*3a22c0a3SAlix        content = "final Jar",
403*3a22c0a3SAlix        preserve_compression = False,
404*3a22c0a3SAlix        pseudo_inputs = []):
405*3a22c0a3SAlix    label = _get_original_kt_target_label(ctx)
406*3a22c0a3SAlix    args = ctx.actions.args()
407*3a22c0a3SAlix    args.add("--normalize")
408*3a22c0a3SAlix    args.add("--add_missing_directories")  # make output more similar to jar tool (b/114414678)
409*3a22c0a3SAlix    args.add("--exclude_build_data")
410*3a22c0a3SAlix    args.add("--no_duplicates")  # No Kt/Java classname collisions (b/216841985)
411*3a22c0a3SAlix    args.add("--output")
412*3a22c0a3SAlix    args.add(output)
413*3a22c0a3SAlix    args.add("--sources")
414*3a22c0a3SAlix    args.add_all(inputs)
415*3a22c0a3SAlix    args.add("--deploy_manifest_lines")
416*3a22c0a3SAlix    args.add("Target-Label: %s" % label)
417*3a22c0a3SAlix    if preserve_compression:
418*3a22c0a3SAlix        args.add("--dont_change_compression")
419*3a22c0a3SAlix
420*3a22c0a3SAlix    ctx.actions.run(
421*3a22c0a3SAlix        executable = singlejar,
422*3a22c0a3SAlix        arguments = [args],
423*3a22c0a3SAlix        inputs = inputs + pseudo_inputs,
424*3a22c0a3SAlix        outputs = [output],
425*3a22c0a3SAlix        mnemonic = mnemonic,
426*3a22c0a3SAlix        progress_message = "Merging %s: %s" % (content, label),
427*3a22c0a3SAlix        toolchain = "@bazel_tools//tools/jdk:toolchain_type",
428*3a22c0a3SAlix    )
429*3a22c0a3SAlix
430*3a22c0a3SAlixdef _merge_jdeps(ctx, kt_jvm_toolchain, jdeps_files, file_factory):
431*3a22c0a3SAlix    merged_jdeps_file = file_factory.declare_file("-merged.jdeps")
432*3a22c0a3SAlix
433*3a22c0a3SAlix    args = ctx.actions.args()
434*3a22c0a3SAlix    args.add("--kind=jdeps")
435*3a22c0a3SAlix    args.add(merged_jdeps_file, format = "--output=%s")
436*3a22c0a3SAlix    args.add(_get_original_kt_target_label(ctx), format = "--rule_label=%s")
437*3a22c0a3SAlix    args.add_all(jdeps_files)
438*3a22c0a3SAlix
439*3a22c0a3SAlix    ctx.actions.run(
440*3a22c0a3SAlix        executable = kt_jvm_toolchain.jdeps_merger,
441*3a22c0a3SAlix        inputs = jdeps_files,
442*3a22c0a3SAlix        outputs = [merged_jdeps_file],
443*3a22c0a3SAlix        arguments = [args],
444*3a22c0a3SAlix        mnemonic = "KtMergeJdeps",
445*3a22c0a3SAlix        progress_message = "Merging jdeps files %{output}",
446*3a22c0a3SAlix        toolchain = kt_jvm_toolchain.toolchain_type,
447*3a22c0a3SAlix    )
448*3a22c0a3SAlix
449*3a22c0a3SAlix    return merged_jdeps_file
450*3a22c0a3SAlix
451*3a22c0a3SAlixdef _check_srcs_package(target_package, srcs, attr_name):
452*3a22c0a3SAlix    """Makes sure the given srcs live in the given package."""
453*3a22c0a3SAlix
454*3a22c0a3SAlix    # Analogous to RuleContext.checkSrcsSamePackage
455*3a22c0a3SAlix    for src in srcs:
456*3a22c0a3SAlix        if target_package != src.owner.package:
457*3a22c0a3SAlix            fail(("Please do not depend on %s directly in %s.  Either move it to this package or " +
458*3a22c0a3SAlix                  "depend on an appropriate rule in its package.") % (src.owner, attr_name))
459*3a22c0a3SAlix
460*3a22c0a3SAlixdef _split_srcs_by_language(srcs, common_srcs, java_syncer):
461*3a22c0a3SAlix    srcs_set = sets.make(srcs)
462*3a22c0a3SAlix    common_srcs_set = sets.make(common_srcs)
463*3a22c0a3SAlix
464*3a22c0a3SAlix    overlapping_srcs_set = sets.intersection(srcs_set, common_srcs_set)
465*3a22c0a3SAlix    if sets.length(overlapping_srcs_set) != 0:
466*3a22c0a3SAlix        fail("Overlap between srcs and common_srcs: %s" % sets.to_list(overlapping_srcs_set))
467*3a22c0a3SAlix
468*3a22c0a3SAlix    # Split sources, as java requires a separate compile step.
469*3a22c0a3SAlix    kt_srcs = [s for s in srcs if _is_kt_src(s)]
470*3a22c0a3SAlix    java_srcs = [s for s in srcs if _is_file(s, _EXT.JAVA)]
471*3a22c0a3SAlix    java_syncer.add_dirs([s for s in srcs if _is_dir(s, "java")])
472*3a22c0a3SAlix    java_syncer.add_srcjars([s for s in srcs if _is_file(s, _EXT.SRCJAR)])
473*3a22c0a3SAlix
474*3a22c0a3SAlix    expected_srcs_set = sets.make(kt_srcs + java_srcs + java_syncer.dirs + java_syncer.srcjars)
475*3a22c0a3SAlix    unexpected_srcs_set = sets.difference(srcs_set, expected_srcs_set)
476*3a22c0a3SAlix    if sets.length(unexpected_srcs_set) != 0:
477*3a22c0a3SAlix        fail("Unexpected srcs: %s" % sets.to_list(unexpected_srcs_set))
478*3a22c0a3SAlix
479*3a22c0a3SAlix    return (kt_srcs, java_srcs)
480*3a22c0a3SAlix
481*3a22c0a3SAlixdef _merge_exported_plugins(exported_plugins_map):
482*3a22c0a3SAlix    for field in ["java_plugin_datas", "kt_codegen_plugin_infos", "kt_compiler_plugin_infos"]:
483*3a22c0a3SAlix        if getattr(exported_plugins_map, field):
484*3a22c0a3SAlix            fail("exported_plugins doesn't support %s. These are propagated with aspects" % field)
485*3a22c0a3SAlix
486*3a22c0a3SAlix    android_lint_ruleset_jars = []
487*3a22c0a3SAlix
488*3a22c0a3SAlix    return exported_plugins_map.java_plugin_infos + [
489*3a22c0a3SAlix        JavaPluginInfo(
490*3a22c0a3SAlix            processor_class = None,
491*3a22c0a3SAlix            runtime_deps = [
492*3a22c0a3SAlix                # Assume this list is short
493*3a22c0a3SAlix                JavaInfo(output_jar = jar, compile_jar = jar)
494*3a22c0a3SAlix                for jar in android_lint_ruleset_jars
495*3a22c0a3SAlix            ],
496*3a22c0a3SAlix        ),
497*3a22c0a3SAlix    ]
498*3a22c0a3SAlix
499*3a22c0a3SAlix# TODO: Streamline API to generate less actions.
500*3a22c0a3SAlixdef _kt_jvm_library(
501*3a22c0a3SAlix        ctx,
502*3a22c0a3SAlix        kt_toolchain,
503*3a22c0a3SAlix        srcs = [],
504*3a22c0a3SAlix        common_srcs = [],
505*3a22c0a3SAlix        coverage_srcs = [],
506*3a22c0a3SAlix        java_android_lint_config = None,
507*3a22c0a3SAlix        manifest = None,  # set for Android libs, otherwise None.
508*3a22c0a3SAlix        merged_manifest = None,  # set for Android libs, otherwise None.
509*3a22c0a3SAlix        resource_files = [],  # set for Android libs, otherwise empty.
510*3a22c0a3SAlix        classpath_resources = [],  # set for kt_jvm_library, otherwise empty.
511*3a22c0a3SAlix        output = None,
512*3a22c0a3SAlix        output_srcjar = None,  # Will derive default filename if not set.
513*3a22c0a3SAlix        deps = [],
514*3a22c0a3SAlix        exports = [],  # passthrough for JavaInfo constructor
515*3a22c0a3SAlix        runtime_deps = [],  # passthrough for JavaInfo constructor
516*3a22c0a3SAlix        native_libraries = [],  # passthrough of CcInfo for JavaInfo constructor
517*3a22c0a3SAlix        plugins = _kt_plugins_map(),
518*3a22c0a3SAlix        exported_plugins = _kt_plugins_map(),
519*3a22c0a3SAlix        javacopts = [],
520*3a22c0a3SAlix        kotlincopts = [],
521*3a22c0a3SAlix        compile_jdeps = depset(),
522*3a22c0a3SAlix        disable_lint_checks = [],
523*3a22c0a3SAlix        neverlink = False,
524*3a22c0a3SAlix        testonly = False,  # used by Android Lint
525*3a22c0a3SAlix        enforce_strict_deps = True,
526*3a22c0a3SAlix        rule_family = _RULE_FAMILY.UNKNOWN,
527*3a22c0a3SAlix        enforce_complete_jdeps = False,
528*3a22c0a3SAlix        java_toolchain = None,
529*3a22c0a3SAlix        friend_jars = depset(),
530*3a22c0a3SAlix                annotation_processor_additional_outputs = [],
531*3a22c0a3SAlix        annotation_processor_additional_inputs = []):
532*3a22c0a3SAlix    if not java_toolchain:
533*3a22c0a3SAlix        fail("Missing or invalid java_toolchain")
534*3a22c0a3SAlix    if not kt_toolchain:
535*3a22c0a3SAlix        fail("Missing or invalid kt_toolchain")
536*3a22c0a3SAlix
537*3a22c0a3SAlix    file_factory = FileFactory(ctx, output)
538*3a22c0a3SAlix    static_deps = list(deps)  # Defensive copy
539*3a22c0a3SAlix
540*3a22c0a3SAlix    kt_codegen_processing_env = dict()
541*3a22c0a3SAlix    codegen_plugin_output = None
542*3a22c0a3SAlix
543*3a22c0a3SAlix    kt_codegen_processors = kt_codegen_processing_env.get("processors_for_kt_codegen_processing", depset()).to_list()
544*3a22c0a3SAlix    codegen_tags = kt_codegen_processing_env.get("codegen_tags", [])
545*3a22c0a3SAlix    generative_deps = kt_codegen_processing_env.get("codegen_output_java_infos", depset()).to_list()
546*3a22c0a3SAlix
547*3a22c0a3SAlix    java_syncer = kt_srcjars.DirSrcjarSyncer(ctx, kt_toolchain, file_factory)
548*3a22c0a3SAlix    kt_srcs, java_srcs = _split_srcs_by_language(srcs, common_srcs, java_syncer)
549*3a22c0a3SAlix
550*3a22c0a3SAlix    is_android_library_without_kt_srcs = rule_family == _RULE_FAMILY.ANDROID_LIBRARY and not kt_srcs and not common_srcs
551*3a22c0a3SAlix    is_android_library_without_kt_srcs_without_generative_deps = is_android_library_without_kt_srcs and not generative_deps
552*3a22c0a3SAlix
553*3a22c0a3SAlix    # TODO: Remove this special case
554*3a22c0a3SAlix    if kt_srcs and ("flogger" in [p.plugin_id for p in plugins.kt_compiler_plugin_infos]):
555*3a22c0a3SAlix        static_deps.append(kt_toolchain.flogger_runtime)
556*3a22c0a3SAlix
557*3a22c0a3SAlix    if not is_android_library_without_kt_srcs_without_generative_deps:
558*3a22c0a3SAlix        static_deps.extend(kt_toolchain.kotlin_libs)
559*3a22c0a3SAlix
560*3a22c0a3SAlix    # Skip srcs package check for android_library targets with no kotlin sources: b/239725424
561*3a22c0a3SAlix    if not is_android_library_without_kt_srcs:
562*3a22c0a3SAlix        if "check_srcs_package_against_kt_srcs_only" in codegen_tags:
563*3a22c0a3SAlix            _check_srcs_package(ctx.label.package, kt_srcs, "srcs")
564*3a22c0a3SAlix        else:
565*3a22c0a3SAlix            _check_srcs_package(ctx.label.package, srcs, "srcs")
566*3a22c0a3SAlix
567*3a22c0a3SAlix        _check_srcs_package(ctx.label.package, common_srcs, "common_srcs")
568*3a22c0a3SAlix        _check_srcs_package(ctx.label.package, coverage_srcs, "coverage_srcs")
569*3a22c0a3SAlix
570*3a22c0a3SAlix    # Includes generative deps from codegen.
571*3a22c0a3SAlix    extended_deps = static_deps + generative_deps
572*3a22c0a3SAlix    full_classpath = _create_classpath(java_toolchain, extended_deps)
573*3a22c0a3SAlix    exported_plugins = _merge_exported_plugins(exported_plugins)
574*3a22c0a3SAlix
575*3a22c0a3SAlix    # Collect all plugin data, including processors to run and all plugin classpaths,
576*3a22c0a3SAlix    # whether they have processors or not (b/120995492).
577*3a22c0a3SAlix    # This may include go/errorprone plugin classpaths that kapt will ignore.
578*3a22c0a3SAlix    java_plugin_datas = kt_codegen_processing_env.get("java_plugin_data_set", plugins.java_plugin_datas).to_list()
579*3a22c0a3SAlix    processors_for_java_srcs = kt_codegen_processing_env.get("processors_for_java_srcs", depset(transitive = [p.processor_classes for p in java_plugin_datas])).to_list()
580*3a22c0a3SAlix    java_plugin_classpaths_for_java_srcs = depset(transitive = [p.processor_jars for p in java_plugin_datas])
581*3a22c0a3SAlix    out_jars = kt_codegen_processing_env.get("codegen_runtime_output_jars", [])
582*3a22c0a3SAlix    out_srcjars = kt_codegen_processing_env.get("codegen_source_jars", [])
583*3a22c0a3SAlix    out_compilejars = kt_codegen_processing_env.get("codegen_compile_jars", [])
584*3a22c0a3SAlix
585*3a22c0a3SAlix    kt_hdrs = _derive_headers(
586*3a22c0a3SAlix        ctx,
587*3a22c0a3SAlix        toolchain = kt_toolchain,
588*3a22c0a3SAlix        file_factory = file_factory.derive("-kt"),
589*3a22c0a3SAlix        # TODO: prohibit overlap of srcs and common_srcs
590*3a22c0a3SAlix        srcs = kt_srcs,
591*3a22c0a3SAlix    )
592*3a22c0a3SAlix    common_hdrs = _derive_headers(
593*3a22c0a3SAlix        ctx,
594*3a22c0a3SAlix        toolchain = kt_toolchain,
595*3a22c0a3SAlix        file_factory = file_factory.derive("-common"),
596*3a22c0a3SAlix        srcs = common_srcs,
597*3a22c0a3SAlix    )
598*3a22c0a3SAlix
599*3a22c0a3SAlix    kotlinc_result = None
600*3a22c0a3SAlix    if kt_srcs or common_srcs:
601*3a22c0a3SAlix        kotlinc_result = _kt_compile(
602*3a22c0a3SAlix            ctx,
603*3a22c0a3SAlix            kt_srcs = kt_srcs,
604*3a22c0a3SAlix            common_srcs = common_srcs,
605*3a22c0a3SAlix            coverage_srcs = coverage_srcs,
606*3a22c0a3SAlix            java_srcs_and_dirs = java_srcs + java_syncer.dirs,
607*3a22c0a3SAlix            kt_hdrs = kt_hdrs,
608*3a22c0a3SAlix            common_hdrs = common_hdrs,
609*3a22c0a3SAlix            file_factory = file_factory.derive("-kt"),
610*3a22c0a3SAlix            kotlincopts = kotlincopts,
611*3a22c0a3SAlix            compile_jdeps = compile_jdeps,
612*3a22c0a3SAlix            toolchain = kt_toolchain,
613*3a22c0a3SAlix            classpath = full_classpath,
614*3a22c0a3SAlix            plugins = plugins,
615*3a22c0a3SAlix            friend_jars = friend_jars,
616*3a22c0a3SAlix            enforce_strict_deps = enforce_strict_deps,
617*3a22c0a3SAlix            enforce_complete_jdeps = enforce_complete_jdeps,
618*3a22c0a3SAlix        )
619*3a22c0a3SAlix        out_compilejars.append(kotlinc_result.compile_jar)
620*3a22c0a3SAlix        out_srcjars.append(kotlinc_result.source_jar)
621*3a22c0a3SAlix        out_jars.append(kotlinc_result.output_jar)
622*3a22c0a3SAlix
623*3a22c0a3SAlix    classpath_resources_dirs, classpath_resources_non_dirs = _partition(
624*3a22c0a3SAlix        classpath_resources,
625*3a22c0a3SAlix        filter = lambda res: res.is_directory,
626*3a22c0a3SAlix    )
627*3a22c0a3SAlix    if classpath_resources_dirs:
628*3a22c0a3SAlix        out_jars.append(
629*3a22c0a3SAlix            kt_srcjars.zip_resources(
630*3a22c0a3SAlix                ctx,
631*3a22c0a3SAlix                kt_toolchain,
632*3a22c0a3SAlix                file_factory.declare_file("-dir-res.jar"),
633*3a22c0a3SAlix                classpath_resources_dirs,
634*3a22c0a3SAlix            ),
635*3a22c0a3SAlix        )
636*3a22c0a3SAlix
637*3a22c0a3SAlix    javac_java_info = None
638*3a22c0a3SAlix    java_native_headers_jar = None
639*3a22c0a3SAlix
640*3a22c0a3SAlix    if java_srcs or java_syncer.srcjars or classpath_resources:
641*3a22c0a3SAlix        javac_deps = list(extended_deps)  # Defensive copy
642*3a22c0a3SAlix        if kotlinc_result:
643*3a22c0a3SAlix            javac_deps.append(kotlinc_result.java_info)
644*3a22c0a3SAlix            if ctx.coverage_instrumented():
645*3a22c0a3SAlix                # Including the coverage runtime improves jdeps computation (b/130747644), but it
646*3a22c0a3SAlix                # could be runtime-only if we computed compile-time jdeps using the compile JAR
647*3a22c0a3SAlix                # (which doesn't contain instrumentation). See b/117897097.
648*3a22c0a3SAlix                javac_deps.append(kt_toolchain.coverage_runtime)
649*3a22c0a3SAlix
650*3a22c0a3SAlix        javac_out = output if is_android_library_without_kt_srcs_without_generative_deps else file_factory.declare_file("-libjvm-java.jar")
651*3a22c0a3SAlix
652*3a22c0a3SAlix        annotation_plugins = kt_codegen_processing_env.get("java_common_annotation_plugins", list(plugins.java_plugin_infos))
653*3a22c0a3SAlix        enable_annotation_processing = kt_codegen_processing_env.get("enable_java_common_annotation_processing", True)
654*3a22c0a3SAlix
655*3a22c0a3SAlix        javac_java_info = java_common.compile(
656*3a22c0a3SAlix            ctx,
657*3a22c0a3SAlix            source_files = java_srcs,
658*3a22c0a3SAlix            source_jars = java_syncer.srcjars,
659*3a22c0a3SAlix            resources = classpath_resources_non_dirs,
660*3a22c0a3SAlix            # For targets that are not android_library with java-only srcs, exports will be passed
661*3a22c0a3SAlix            # to the final constructed JavaInfo.
662*3a22c0a3SAlix            exports = exports if is_android_library_without_kt_srcs_without_generative_deps else [],
663*3a22c0a3SAlix            output = javac_out,
664*3a22c0a3SAlix            exported_plugins = exported_plugins,
665*3a22c0a3SAlix            deps = javac_deps,
666*3a22c0a3SAlix            # Include default_javac_flags, which reflect Blaze's --javacopt flag, so they win over
667*3a22c0a3SAlix            # all sources of default flags (for Ellipsis builds, see b/125452475).
668*3a22c0a3SAlix            # TODO: remove default_javac_flags here once java_common.compile is fixed.
669*3a22c0a3SAlix            javac_opts = ctx.fragments.java.default_javac_flags + javacopts,
670*3a22c0a3SAlix            plugins = annotation_plugins,
671*3a22c0a3SAlix            strict_deps = "DEFAULT",
672*3a22c0a3SAlix            java_toolchain = java_toolchain,
673*3a22c0a3SAlix            neverlink = neverlink,
674*3a22c0a3SAlix            enable_annotation_processing = enable_annotation_processing,
675*3a22c0a3SAlix            annotation_processor_additional_outputs = annotation_processor_additional_outputs,
676*3a22c0a3SAlix            annotation_processor_additional_inputs = annotation_processor_additional_inputs,
677*3a22c0a3SAlix        )
678*3a22c0a3SAlix
679*3a22c0a3SAlix        out_jars.append(javac_out)
680*3a22c0a3SAlix        out_srcjars.extend(javac_java_info.source_jars)
681*3a22c0a3SAlix        out_compilejars.extend(javac_java_info.compile_jars.to_list())  # unpack singleton depset
682*3a22c0a3SAlix        java_native_headers_jar = javac_java_info.outputs.native_headers
683*3a22c0a3SAlix
684*3a22c0a3SAlix    java_gensrcjar = None
685*3a22c0a3SAlix    java_genjar = None
686*3a22c0a3SAlix
687*3a22c0a3SAlix    if codegen_plugin_output:
688*3a22c0a3SAlix        pass
689*3a22c0a3SAlix
690*3a22c0a3SAlix    elif javac_java_info:
691*3a22c0a3SAlix        java_gensrcjar = javac_java_info.annotation_processing.source_jar
692*3a22c0a3SAlix        java_genjar = javac_java_info.annotation_processing.class_jar
693*3a22c0a3SAlix        if java_gensrcjar:
694*3a22c0a3SAlix            java_syncer.add_srcjars([java_gensrcjar])
695*3a22c0a3SAlix
696*3a22c0a3SAlix    jdeps_output = None
697*3a22c0a3SAlix    compile_jdeps_output = None
698*3a22c0a3SAlix    manifest_proto = None
699*3a22c0a3SAlix
700*3a22c0a3SAlix    # TODO: Move severity overrides to config file when possible again
701*3a22c0a3SAlix    blocking_action_outs = []
702*3a22c0a3SAlix
703*3a22c0a3SAlix    # TODO: Remove the is_android_library_without_kt_srcs condition once KtAndroidLint
704*3a22c0a3SAlix    # uses the same lint checks with AndroidLint
705*3a22c0a3SAlix
706*3a22c0a3SAlix    if (srcs or common_srcs or resource_files) and not is_android_lint_exempt(ctx):
707*3a22c0a3SAlix        lint_flags = [
708*3a22c0a3SAlix            "--java-language-level",  # b/159950410
709*3a22c0a3SAlix            kt_toolchain.java_language_version,
710*3a22c0a3SAlix            "--kotlin-language-level",
711*3a22c0a3SAlix            kt_toolchain.kotlin_language_version,
712*3a22c0a3SAlix            "--nowarn",  # Check for "errors", which includes custom checks that report errors.
713*3a22c0a3SAlix            "--XallowBaselineSuppress",  # allow baseline exemptions of otherwise unsuppressable errors
714*3a22c0a3SAlix            "--exitcode",  # fail on error
715*3a22c0a3SAlix            "--fullpath",  # reduce file path clutter in reported issues
716*3a22c0a3SAlix            "--text",
717*3a22c0a3SAlix            "stdout",  # also log to stdout
718*3a22c0a3SAlix        ]
719*3a22c0a3SAlix        if disable_lint_checks and disable_lint_checks != [""]:
720*3a22c0a3SAlix            lint_flags.append("--disable")
721*3a22c0a3SAlix            lint_flags.append(",".join(disable_lint_checks))
722*3a22c0a3SAlix
723*3a22c0a3SAlix        android_lint_out = lint_actions.run_lint_on_library(
724*3a22c0a3SAlix            ctx,
725*3a22c0a3SAlix            runner = kt_toolchain.android_lint_runner,
726*3a22c0a3SAlix            output = file_factory.declare_file("_android_lint_output.xml"),
727*3a22c0a3SAlix            srcs = kt_srcs + java_srcs + common_srcs,
728*3a22c0a3SAlix            source_jars = java_syncer.srcjars,
729*3a22c0a3SAlix            classpath = full_classpath,
730*3a22c0a3SAlix            manifest = manifest,
731*3a22c0a3SAlix            merged_manifest = merged_manifest,
732*3a22c0a3SAlix            resource_files = resource_files,
733*3a22c0a3SAlix            baseline_file = androidlint_toolchains.get_baseline(ctx),
734*3a22c0a3SAlix            config = (None if (kt_srcs or common_srcs) else java_android_lint_config) or kt_toolchain.android_lint_config,
735*3a22c0a3SAlix            android_lint_rules = plugins.android_lint_rulesets + [
736*3a22c0a3SAlix                lint_actions.AndroidLintRulesetInfo(singlejars = java_plugin_classpaths_for_java_srcs),
737*3a22c0a3SAlix            ],
738*3a22c0a3SAlix            lint_flags = lint_flags,
739*3a22c0a3SAlix            extra_input_depsets = [p.processor_data for p in java_plugin_datas],
740*3a22c0a3SAlix            testonly = testonly,
741*3a22c0a3SAlix            android_java8_libs = kt_toolchain.android_java8_apis_desugared,
742*3a22c0a3SAlix            mnemonic = "AndroidLint" if is_android_library_without_kt_srcs else "KtAndroidLint",  # so LSA extractor can distinguish Kotlin (b/189442586)
743*3a22c0a3SAlix        )
744*3a22c0a3SAlix        blocking_action_outs.append(android_lint_out)
745*3a22c0a3SAlix
746*3a22c0a3SAlix    # Directly return the JavaInfo from java.compile() for java-only android_library targets
747*3a22c0a3SAlix    # to avoid creating a new JavaInfo. See b/239847857 for additional context.
748*3a22c0a3SAlix    if javac_java_info and is_android_library_without_kt_srcs_without_generative_deps:
749*3a22c0a3SAlix        return struct(
750*3a22c0a3SAlix            java_info = javac_java_info,
751*3a22c0a3SAlix            validations = blocking_action_outs,
752*3a22c0a3SAlix        )
753*3a22c0a3SAlix
754*3a22c0a3SAlix    if output_srcjar == None:
755*3a22c0a3SAlix        output_srcjar = file_factory.declare_file("-src.jar")
756*3a22c0a3SAlix    compile_jar = file_factory.declare_file("-compile.jar")
757*3a22c0a3SAlix    single_jar = java_toolchain.single_jar
758*3a22c0a3SAlix    _singlejar(ctx, out_srcjars, output_srcjar, single_jar, mnemonic = "KtMergeSrcjar", content = "srcjar", preserve_compression = True)
759*3a22c0a3SAlix
760*3a22c0a3SAlix    # Don't block compile-time Jar on Android Lint and other validations (b/117991324).
761*3a22c0a3SAlix    _singlejar(ctx, out_compilejars, compile_jar, single_jar, mnemonic = "KtMergeCompileJar", content = "compile-time Jar")
762*3a22c0a3SAlix
763*3a22c0a3SAlix    # Disable validation for Guitar BUILD targets (b/144326858).
764*3a22c0a3SAlix    # TODO Remove use of RUN_ANALYSIS_TIME_VALIDATION once Guitar disables validations
765*3a22c0a3SAlix    use_validation = ctx.var.get("RUN_ANALYSIS_TIME_VALIDATION", "true")  # will be "0" if set by Guitar
766*3a22c0a3SAlix    use_validation = ctx.var.get("kt_use_validations", use_validation)
767*3a22c0a3SAlix
768*3a22c0a3SAlix    # Include marker file in runtime Jar so we can reliably identify 1P Kotlin code
769*3a22c0a3SAlix    # TODO: consider only doing this for android_library(
770*3a22c0a3SAlix    _singlejar(
771*3a22c0a3SAlix        ctx,
772*3a22c0a3SAlix        out_jars + ([kt_toolchain.build_marker] if kt_srcs and ctx.label.package.startswith("java/") else []),
773*3a22c0a3SAlix        output,
774*3a22c0a3SAlix        single_jar,
775*3a22c0a3SAlix        preserve_compression = True,
776*3a22c0a3SAlix        pseudo_inputs = ([] if use_validation == "true" else blocking_action_outs),
777*3a22c0a3SAlix    )
778*3a22c0a3SAlix    result_java_info = JavaInfo(
779*3a22c0a3SAlix        output_jar = output,
780*3a22c0a3SAlix        compile_jar = compile_jar,
781*3a22c0a3SAlix        source_jar = output_srcjar,
782*3a22c0a3SAlix        deps = static_deps,
783*3a22c0a3SAlix        exports = exports,
784*3a22c0a3SAlix        exported_plugins = exported_plugins,
785*3a22c0a3SAlix        runtime_deps = runtime_deps,
786*3a22c0a3SAlix        manifest_proto = manifest_proto,
787*3a22c0a3SAlix        neverlink = neverlink,
788*3a22c0a3SAlix        jdeps = jdeps_output,
789*3a22c0a3SAlix        compile_jdeps = compile_jdeps_output,
790*3a22c0a3SAlix        native_libraries = native_libraries,
791*3a22c0a3SAlix        native_headers_jar = java_native_headers_jar,
792*3a22c0a3SAlix        generated_source_jar = java_gensrcjar,
793*3a22c0a3SAlix        generated_class_jar = java_genjar,
794*3a22c0a3SAlix    )
795*3a22c0a3SAlix
796*3a22c0a3SAlix    return struct(
797*3a22c0a3SAlix        java_info = result_java_info,
798*3a22c0a3SAlix        validations = (blocking_action_outs if use_validation == "true" else []),
799*3a22c0a3SAlix    )
800*3a22c0a3SAlix
801*3a22c0a3SAlixdef _kt_jvm_import(
802*3a22c0a3SAlix        ctx,
803*3a22c0a3SAlix        kt_toolchain,
804*3a22c0a3SAlix        jars = [],
805*3a22c0a3SAlix        srcjar = None,
806*3a22c0a3SAlix        deps = [],
807*3a22c0a3SAlix        runtime_deps = [],
808*3a22c0a3SAlix        neverlink = False,
809*3a22c0a3SAlix                java_toolchain = None,
810*3a22c0a3SAlix        deps_checker = None):
811*3a22c0a3SAlix    if not java_toolchain:
812*3a22c0a3SAlix        fail("Missing or invalid java_toolchain")
813*3a22c0a3SAlix    if not jars:
814*3a22c0a3SAlix        fail("Must import at least one JAR")
815*3a22c0a3SAlix
816*3a22c0a3SAlix    _check_srcs_package(ctx.label.package, jars, "jars")
817*3a22c0a3SAlix    if srcjar:
818*3a22c0a3SAlix        _check_srcs_package(ctx.label.package, [srcjar], "srcjar")
819*3a22c0a3SAlix
820*3a22c0a3SAlix    file_factory = FileFactory(ctx, jars[0])
821*3a22c0a3SAlix    deps = java_common.merge(deps + kt_toolchain.kotlin_libs)
822*3a22c0a3SAlix
823*3a22c0a3SAlix    # Check that any needed deps are declared unless neverlink, in which case Jars won't be used
824*3a22c0a3SAlix    # at runtime so we skip the check, though we'll populate jdeps either way.
825*3a22c0a3SAlix    jdeps_output = file_factory.declare_file(".jdeps")
826*3a22c0a3SAlix    _run_import_deps_checker(
827*3a22c0a3SAlix        ctx,
828*3a22c0a3SAlix        jars_to_check = jars,
829*3a22c0a3SAlix        merged_deps = deps,
830*3a22c0a3SAlix        enforce_strict_deps = not neverlink,
831*3a22c0a3SAlix        jdeps_output = jdeps_output,
832*3a22c0a3SAlix        deps_checker = deps_checker,
833*3a22c0a3SAlix        java_toolchain = java_toolchain,
834*3a22c0a3SAlix    )
835*3a22c0a3SAlix
836*3a22c0a3SAlix    java_info = java_common.merge([
837*3a22c0a3SAlix        JavaInfo(
838*3a22c0a3SAlix            output_jar = jar,
839*3a22c0a3SAlix            compile_jar = java_common.run_ijar(
840*3a22c0a3SAlix                actions = ctx.actions,
841*3a22c0a3SAlix                jar = jar,
842*3a22c0a3SAlix                target_label = _get_original_kt_target_label(ctx),
843*3a22c0a3SAlix                java_toolchain = java_toolchain,
844*3a22c0a3SAlix            ),
845*3a22c0a3SAlix            source_jar = srcjar,
846*3a22c0a3SAlix            deps = [deps],
847*3a22c0a3SAlix            runtime_deps = runtime_deps,
848*3a22c0a3SAlix            neverlink = neverlink,
849*3a22c0a3SAlix            # TODO: Set compile-time jdeps to help reduce Javac classpaths downstream
850*3a22c0a3SAlix            jdeps = jdeps_output,  # not clear this is useful but let's populate since we have it
851*3a22c0a3SAlix        )
852*3a22c0a3SAlix        for jar in jars
853*3a22c0a3SAlix    ])
854*3a22c0a3SAlix
855*3a22c0a3SAlix    # TODO Remove use of RUN_ANALYSIS_TIME_VALIDATION once Guitar disables validations
856*3a22c0a3SAlix    use_validation = ctx.var.get("RUN_ANALYSIS_TIME_VALIDATION", "true")  # will be "0" if set by Guitar
857*3a22c0a3SAlix
858*3a22c0a3SAlix    return struct(
859*3a22c0a3SAlix        java_info = java_info,
860*3a22c0a3SAlix        validations = [jdeps_output] if use_validation == "true" and not neverlink else [],
861*3a22c0a3SAlix    )
862*3a22c0a3SAlix
863*3a22c0a3SAlixdef _validate_proguard_specs(
864*3a22c0a3SAlix        ctx,
865*3a22c0a3SAlix        proguard_specs,
866*3a22c0a3SAlix        proguard_allowlister):
867*3a22c0a3SAlix    validated_proguard_specs = []
868*3a22c0a3SAlix    for proguard_spec in proguard_specs:
869*3a22c0a3SAlix        validated_proguard_spec = ctx.actions.declare_file(
870*3a22c0a3SAlix            "validated_proguard/%s/%s_valid" % (ctx.label.name, proguard_spec.path),
871*3a22c0a3SAlix        )
872*3a22c0a3SAlix        validated_proguard_specs.append(validated_proguard_spec)
873*3a22c0a3SAlix
874*3a22c0a3SAlix        args = ctx.actions.args()
875*3a22c0a3SAlix        args.add("--path", proguard_spec)
876*3a22c0a3SAlix        args.add("--output", validated_proguard_spec)
877*3a22c0a3SAlix
878*3a22c0a3SAlix        ctx.actions.run(
879*3a22c0a3SAlix            executable = proguard_allowlister,
880*3a22c0a3SAlix            toolchain = kt_jvm_toolchains.type,
881*3a22c0a3SAlix            arguments = [args],
882*3a22c0a3SAlix            inputs = [proguard_spec],
883*3a22c0a3SAlix            outputs = [validated_proguard_spec],
884*3a22c0a3SAlix            mnemonic = "ValidateProguard",
885*3a22c0a3SAlix            progress_message = (
886*3a22c0a3SAlix                "Validating proguard configuration %s" % proguard_spec
887*3a22c0a3SAlix            ),
888*3a22c0a3SAlix        )
889*3a22c0a3SAlix    return validated_proguard_specs
890*3a22c0a3SAlix
891*3a22c0a3SAlixdef _collect_proguard_specs(
892*3a22c0a3SAlix        ctx,
893*3a22c0a3SAlix        proguard_specs,
894*3a22c0a3SAlix        propagated_deps,
895*3a22c0a3SAlix        proguard_allowlister):
896*3a22c0a3SAlix    validated_proguard_specs = _validate_proguard_specs(
897*3a22c0a3SAlix        ctx,
898*3a22c0a3SAlix        proguard_specs,
899*3a22c0a3SAlix        proguard_allowlister,
900*3a22c0a3SAlix    )
901*3a22c0a3SAlix
902*3a22c0a3SAlix    return depset(
903*3a22c0a3SAlix        validated_proguard_specs,
904*3a22c0a3SAlix        transitive = [p.specs for p in _collect_providers(ProguardSpecProvider, propagated_deps)],
905*3a22c0a3SAlix        order = "preorder",
906*3a22c0a3SAlix    )
907*3a22c0a3SAlix
908*3a22c0a3SAlixdef _collect_providers(provider, deps):
909*3a22c0a3SAlix    """Collects the requested provider from the given list of deps."""
910*3a22c0a3SAlix    return [dep[provider] for dep in deps if provider in dep]
911*3a22c0a3SAlix
912*3a22c0a3SAlixdef _create_classpath(java_toolchain, deps):
913*3a22c0a3SAlix    # To not confuse strictdeps, order as boot > direct > transitive JARs (b/149107867).
914*3a22c0a3SAlix    return depset(
915*3a22c0a3SAlix        order = "preorder",
916*3a22c0a3SAlix        transitive = (
917*3a22c0a3SAlix            [java_toolchain.bootclasspath] +
918*3a22c0a3SAlix            [dep.compile_jars for dep in deps] +
919*3a22c0a3SAlix            [dep.transitive_compile_time_jars for dep in deps]
920*3a22c0a3SAlix        ),
921*3a22c0a3SAlix    )
922*3a22c0a3SAlix
923*3a22c0a3SAlixdef _partition(sequence, filter):
924*3a22c0a3SAlix    pos, neg = [], []
925*3a22c0a3SAlix    for element in sequence:
926*3a22c0a3SAlix        if filter(element):
927*3a22c0a3SAlix            pos.append(element)
928*3a22c0a3SAlix        else:
929*3a22c0a3SAlix            neg.append(element)
930*3a22c0a3SAlix    return pos, neg
931*3a22c0a3SAlix
932*3a22c0a3SAlixcommon = struct(
933*3a22c0a3SAlix    JAR_FILE_TYPE = _JAR_FILE_TYPE,
934*3a22c0a3SAlix    JVM_FLAGS = BASE_JVMOPTS,
935*3a22c0a3SAlix    KT_FILE_TYPES = _KT_FILE_TYPES,
936*3a22c0a3SAlix    KT_JVM_FILE_TYPES = _KT_JVM_FILE_TYPES,
937*3a22c0a3SAlix    RULE_FAMILY = _RULE_FAMILY,
938*3a22c0a3SAlix    SRCJAR_FILE_TYPES = _SRCJAR_FILE_TYPES,
939*3a22c0a3SAlix    collect_proguard_specs = _collect_proguard_specs,
940*3a22c0a3SAlix    collect_providers = _collect_providers,
941*3a22c0a3SAlix    create_jar_from_tree_artifacts = kt_srcjars.zip_resources,
942*3a22c0a3SAlix    get_common_and_user_kotlinc_args = _get_common_and_user_kotlinc_args,
943*3a22c0a3SAlix    is_kt_src = _is_kt_src,
944*3a22c0a3SAlix    kt_jvm_import = _kt_jvm_import,
945*3a22c0a3SAlix    kt_jvm_library = _kt_jvm_library,
946*3a22c0a3SAlix    kt_plugins_map = _kt_plugins_map,
947*3a22c0a3SAlix    partition = _partition,
948*3a22c0a3SAlix)
949