1# Copyright 2021 The Bazel Authors. All rights reserved. 2# 3# Licensed under the Apache License, Version 2.0 (the "License"); 4# you may not use this file except in compliance with the License. 5# You may obtain a copy of the License at 6# 7# http://www.apache.org/licenses/LICENSE-2.0 8# 9# Unless required by applicable law or agreed to in writing, software 10# distributed under the License is distributed on an "AS IS" BASIS, 11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12# See the License for the specific language governing permissions and 13# limitations under the License. 14 15""" 16Common code for reuse across java_* rules 17""" 18 19load("@rules_cc//cc/common:cc_info.bzl", "CcInfo") 20load("//java/common/rules:android_lint.bzl", "android_lint_subrule") 21load("//java/private:boot_class_path_info.bzl", "BootClassPathInfo") 22load("//java/private:java_common_internal.bzl", "target_kind") 23load("//java/private:java_info.bzl", "JavaInfo", "JavaPluginInfo") 24load(":compile_action.bzl", "compile_action") 25load(":proguard_validation.bzl", "validate_proguard_specs") 26 27# copybara: default multiline visibility 28 29def _filter_srcs(srcs, ext): 30 return [f for f in srcs if f.extension == ext] 31 32def _filter_provider(provider, *attrs): 33 return [dep[provider] for attr in attrs for dep in attr if provider in dep] 34 35# TODO(b/11285003): disallow jar files in deps, require java_import instead 36def _filter_javainfo_and_legacy_jars(attr): 37 dep_list = [] 38 39 # Native code collected data into a NestedSet, using add for legacy jars and 40 # addTransitive for JavaInfo. This resulted in legacy jars being first in the list. 41 for dep in attr: 42 kind = target_kind(dep) 43 if not JavaInfo in dep or kind == "java_binary" or kind == "java_test": 44 for file in dep[DefaultInfo].files.to_list(): 45 if file.extension == "jar": 46 # Native doesn't construct JavaInfo 47 java_info = JavaInfo(output_jar = file, compile_jar = file) 48 dep_list.append(java_info) 49 50 for dep in attr: 51 if JavaInfo in dep: 52 dep_list.append(dep[JavaInfo]) 53 return dep_list 54 55def basic_java_library( 56 ctx, 57 srcs, 58 deps = [], 59 runtime_deps = [], 60 plugins = [], 61 exports = [], 62 exported_plugins = [], 63 resources = [], 64 resource_jars = [], 65 classpath_resources = [], 66 javacopts = [], 67 neverlink = False, 68 enable_compile_jar_action = True, 69 coverage_config = None, 70 proguard_specs = None, 71 add_exports = [], 72 add_opens = [], 73 bootclasspath = None, 74 javabuilder_jvm_flags = None): 75 """ 76 Creates actions that compile and lint Java sources, sets up coverage and returns JavaInfo, InstrumentedFilesInfo and output groups. 77 78 The call creates actions and providers needed and shared by `java_library`, 79 `java_plugin`,`java_binary`, and `java_test` rules and it is primarily 80 intended to be used in those rules. 81 82 Before compilation coverage.runner is added to the dependencies and if 83 present plugins are extended with the value of `--plugin` flag. 84 85 Args: 86 ctx: (RuleContext) Used to register the actions. 87 srcs: (list[File]) The list of source files that are processed to create the target. 88 deps: (list[Target]) The list of other libraries to be linked in to the target. 89 runtime_deps: (list[Target]) Libraries to make available to the final binary or test at runtime only. 90 plugins: (list[Target]) Java compiler plugins to run at compile-time. 91 exports: (list[Target]) Exported libraries. 92 exported_plugins: (list[Target]) The list of `java_plugin`s (e.g. annotation 93 processors) to export to libraries that directly depend on this library. 94 resources: (list[File]) A list of data files to include in a Java jar. 95 resource_jars: (list[File]) A list of jar files to unpack and include in a 96 Java jar. 97 classpath_resources: (list[File]) 98 javacopts: (list[str]) 99 neverlink: (bool) Whether this library should only be used for compilation and not at runtime. 100 enable_compile_jar_action: (bool) Enables header compilation or ijar creation. 101 coverage_config: (struct{runner:JavaInfo, support_files:list[File]|depset[File], env:dict[str,str]}) 102 Coverage configuration. `runner` is added to dependencies during 103 compilation, `support_files` and `env` is returned in InstrumentedFilesInfo. 104 proguard_specs: (list[File]) Files to be used as Proguard specification. 105 Proguard validation is done only when the parameter is set. 106 add_exports: (list[str]) Allow this library to access the given <module>/<package>. 107 add_opens: (list[str]) Allow this library to reflectively access the given <module>/<package>. 108 bootclasspath: (Target) The JDK APIs to compile this library against. 109 javabuilder_jvm_flags: (list[str]) Additional JVM flags to pass to JavaBuilder. 110 Returns: 111 (dict[str, Provider], 112 {files_to_build: list[File], 113 runfiles: list[File], 114 output_groups: dict[str,list[File]]}) 115 """ 116 source_files = _filter_srcs(srcs, "java") 117 source_jars = _filter_srcs(srcs, "srcjar") 118 119 plugins_javaplugininfo = _collect_plugins(plugins) 120 plugins_javaplugininfo.append(ctx.attr._java_plugins[JavaPluginInfo]) 121 122 properties = _filter_srcs(srcs, "properties") 123 if properties: 124 resources = list(resources) 125 resources.extend(properties) 126 127 java_info, compilation_info = compile_action( 128 ctx, 129 ctx.outputs.classjar, 130 ctx.outputs.sourcejar, 131 source_files, 132 source_jars, 133 collect_deps(deps) + ([coverage_config.runner] if coverage_config and coverage_config.runner else []), 134 collect_deps(runtime_deps), 135 plugins_javaplugininfo, 136 collect_deps(exports), 137 _collect_plugins(exported_plugins), 138 resources, 139 resource_jars, 140 classpath_resources, 141 _collect_native_libraries(deps, runtime_deps, exports), 142 javacopts, 143 neverlink, 144 ctx.fragments.java.strict_java_deps, 145 enable_compile_jar_action, 146 add_exports = add_exports, 147 add_opens = add_opens, 148 bootclasspath = bootclasspath[BootClassPathInfo] if bootclasspath else None, 149 javabuilder_jvm_flags = javabuilder_jvm_flags, 150 ) 151 target = {"JavaInfo": java_info} 152 153 output_groups = dict( 154 compilation_outputs = compilation_info.files_to_build, 155 _source_jars = java_info.transitive_source_jars, 156 _direct_source_jars = java_info.source_jars, 157 ) 158 159 if ctx.fragments.java.run_android_lint: 160 generated_source_jars = [ 161 output.generated_source_jar 162 for output in java_info.java_outputs 163 if output.generated_source_jar != None 164 ] 165 lint_output = android_lint_subrule( 166 source_files, 167 source_jars + generated_source_jars, 168 compilation_info, 169 ) 170 if lint_output: 171 output_groups["_validation"] = [lint_output] 172 173 target["InstrumentedFilesInfo"] = coverage_common.instrumented_files_info( 174 ctx, 175 source_attributes = ["srcs"], 176 dependency_attributes = ["deps", "data", "resources", "resource_jars", "exports", "runtime_deps", "jars"], 177 coverage_support_files = coverage_config.support_files if coverage_config else depset(), 178 coverage_environment = coverage_config.env if coverage_config else {}, 179 ) 180 181 if proguard_specs != None: 182 target["ProguardSpecProvider"] = validate_proguard_specs( 183 ctx, 184 proguard_specs, 185 [deps, runtime_deps, exports], 186 ) 187 output_groups["_hidden_top_level_INTERNAL_"] = target["ProguardSpecProvider"].specs 188 189 return target, struct( 190 files_to_build = compilation_info.files_to_build, 191 runfiles = compilation_info.runfiles, 192 output_groups = output_groups, 193 ) 194 195def _collect_plugins(plugins): 196 """Collects plugins from an attribute. 197 198 Use this call to collect plugins from `plugins` or `exported_plugins` attribute. 199 200 The call simply extracts JavaPluginInfo provider. 201 202 Args: 203 plugins: (list[Target]) Attribute to collect plugins from. 204 Returns: 205 (list[JavaPluginInfo]) The plugins. 206 """ 207 return _filter_provider(JavaPluginInfo, plugins) 208 209def collect_deps(deps): 210 """Collects dependencies from an attribute. 211 212 Use this call to collect plugins from `deps`, `runtime_deps`, or `exports` attribute. 213 214 The call extracts JavaInfo and additionaly also "legacy jars". "legacy jars" 215 are wrapped into a JavaInfo. 216 217 Args: 218 deps: (list[Target]) Attribute to collect dependencies from. 219 Returns: 220 (list[JavaInfo]) The dependencies. 221 """ 222 return _filter_javainfo_and_legacy_jars(deps) 223 224def _collect_native_libraries(*attrs): 225 """Collects native libraries from a list of attributes. 226 227 Use this call to collect native libraries from `deps`, `runtime_deps`, or `exports` attributes. 228 229 The call simply extracts CcInfo provider. 230 Args: 231 *attrs: (*list[Target]) Attribute to collect native libraries from. 232 Returns: 233 (list[CcInfo]) The native library dependencies. 234 """ 235 return _filter_provider(CcInfo, *attrs) 236 237def construct_defaultinfo(ctx, files_to_build, files, neverlink, *extra_attrs): 238 """Constructs DefaultInfo for Java library like rule. 239 240 Args: 241 ctx: (RuleContext) Used to construct the runfiles. 242 files_to_build: (list[File]) List of the files built by the rule. 243 files: (list[File]) List of the files include in runfiles. 244 neverlink: (bool) When true empty runfiles are constructed. 245 *extra_attrs: (list[Target]) Extra attributes to merge runfiles from. 246 247 Returns: 248 (DefaultInfo) DefaultInfo provider. 249 """ 250 if neverlink: 251 runfiles = None 252 else: 253 runfiles = ctx.runfiles(files = files, collect_default = True) 254 runfiles = runfiles.merge_all([dep[DefaultInfo].default_runfiles for attr in extra_attrs for dep in attr]) 255 default_info = DefaultInfo( 256 files = depset(files_to_build), 257 runfiles = runfiles, 258 ) 259 return default_info 260