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