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