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