/
jvm_target.py
229 lines (192 loc) · 9.1 KB
/
jvm_target.py
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
# Copyright 2014 Pants project contributors (see CONTRIBUTORS.md).
# Licensed under the Apache License, Version 2.0 (see LICENSE).
from twitter.common.collections import OrderedSet
from pants.backend.jvm.subsystems.java import Java
from pants.backend.jvm.subsystems.jvm_platform import JvmPlatform
from pants.backend.jvm.targets.jar_library import JarLibrary
from pants.backend.jvm.targets.jarable import Jarable
from pants.base.payload import Payload
from pants.base.payload_field import ExcludesField, PrimitiveField, PrimitivesSetField
from pants.build_graph.resources import Resources
from pants.build_graph.target import Target
from pants.java.jar.exclude import Exclude
from pants.util.memo import memoized_property
class JvmTarget(Target, Jarable):
"""A base class for all java module targets that provides path and dependency translation.
:API: public
"""
@classmethod
def subsystems(cls):
return super().subsystems() + (Java, JvmPlatform)
def __init__(self,
address=None,
payload=None,
sources=None,
provides=None,
excludes=None,
services=None,
platform=None,
strict_deps=None,
exports=None,
compiler_option_sets=None,
zinc_file_manager=None,
# Some subclasses can have both .java and .scala sources
# (e.g., JUnitTests, JvmBinary, even ScalaLibrary), so it's convenient
# to have both plugins settings here, even though for other subclasses
# (e.g., JavaLibrary) only one will be relevant.
javac_plugins=None,
javac_plugin_args=None,
scalac_plugins=None,
scalac_plugin_args=None,
**kwargs):
"""
:API: public
:param excludes: List of `exclude <#exclude>`_\\s to filter this target's
transitive dependencies against.
:param sources: Source code files to build. Paths are relative to the BUILD
file's directory.
:type sources: ``Fileset`` (from globs or rglobs) or list of strings
:param services: A dict mapping service interface names to the classes owned by this target
that implement them. Keys are fully qualified service class names, values are
lists of strings, each string the fully qualified class name of a class owned
by this target that implements the service interface and should be
discoverable by the jvm service provider discovery mechanism described here:
https://docs.oracle.com/javase/6/docs/api/java/util/ServiceLoader.html
:param str platform: The name of the platform (defined under the jvm-platform subsystem) to use
for compilation (that is, a key into the --jvm-platform-platforms
dictionary). If unspecified, the platform will default to the first one of
these that exist: (1) the default_platform specified for jvm-platform,
(2) a platform constructed from whatever java version is returned by
DistributionLocator.cached().version.
:param bool strict_deps: When True, only the directly declared deps of the target will be used
at compilation time. This enforces that all direct deps of the target
are declared, and can improve compilation speed due to smaller
classpaths. Transitive deps are always provided at runtime.
:param list exports: A list of exported targets, which will be accessible to dependents even
with strict_deps turned on. A common use case is for library targets to
to export dependencies that it knows its dependents will need. Then any
dependents of that library target will have access to those dependencies
even when strict_deps is True. Note: exports is transitive, which means
dependents have access to the closure of exports. An example will be that
if A exports B, and B exports C, then any targets that depends on A will
have access to both B and C.
:param list compiler_option_sets: A list of compiler_option_sets keys for the target. Platform
dependent.
:param bool zinc_file_manager: Whether to use zinc provided file manager that allows
transactional rollbacks, but in certain cases may conflict with
user libraries.
:param javac_plugins: names of compiler plugins to use when compiling this target with javac.
:param dict javac_plugin_args: Map from javac plugin name to list of arguments for that plugin.
:param scalac_plugins: names of compiler plugins to use when compiling this target with scalac.
:param dict scalac_plugin_args: Map from scalac plugin name to list of arguments for that plugin.
"""
self.address = address # Set in case a TargetDefinitionException is thrown early
payload = payload or Payload()
excludes = ExcludesField(self.assert_list(excludes, expected_type=Exclude, key_arg='excludes'))
payload.add_fields({
'sources': self.create_sources_field(sources, address.spec_path, key_arg='sources'),
'provides': provides,
'excludes': excludes,
'platform': PrimitiveField(platform),
'strict_deps': PrimitiveField(strict_deps),
'exports': PrimitivesSetField(exports or []),
'compiler_option_sets': PrimitivesSetField(compiler_option_sets),
'zinc_file_manager': PrimitiveField(zinc_file_manager),
'javac_plugins': PrimitivesSetField(javac_plugins or []),
'javac_plugin_args': PrimitiveField(javac_plugin_args),
'scalac_plugins': PrimitivesSetField(scalac_plugins or []),
'scalac_plugin_args': PrimitiveField(scalac_plugin_args),
})
super().__init__(address=address, payload=payload, **kwargs)
# Service info is only used when generating resources, it should not affect, for example, a
# compile fingerprint or javadoc fingerprint. As such, its not a payload field.
self._services = services or {}
@property
def strict_deps(self):
"""If set, whether to limit compile time deps to those that are directly declared.
:return: See constructor.
:rtype: bool or None
"""
return self.payload.strict_deps
@property
def export_specs(self):
return self.payload.exports
@memoized_property
def compiler_option_sets(self):
"""For every element in this list, enable the corresponding flags on compilation
of targets.
:return: See constructor.
:rtype: list
"""
return self.payload.compiler_option_sets
@property
def zinc_file_manager(self):
"""If false, the default file manager will be used instead of the zinc provided one.
:return: See constructor.
:rtype: bool or None
"""
return self.payload.zinc_file_manager
@property
def javac_plugins(self):
"""The names of compiler plugins to use when compiling this target with javac.
:return: See constructor.
:rtype: list of strings.
"""
return self.payload.javac_plugins
@property
def javac_plugin_args(self):
"""Map from javac plugin name to list of args for that plugin.
:return: See constructor.
:rtype: map from string to list of strings.
"""
return self.payload.javac_plugin_args
@property
def scalac_plugins(self):
"""The names of compiler plugins to use when compiling this target with scalac.
:return: See constructor.
:rtype: list of strings.
"""
return self.payload.scalac_plugins
@property
def scalac_plugin_args(self):
"""Map from scalac plugin name to list of args for that plugin.
:return: See constructor.
:rtype: map from string to list of strings.
"""
return self.payload.scalac_plugin_args
@property
def platform(self):
"""Platform associated with this target.
:return: The jvm platform object.
:rtype: JvmPlatformSettings
"""
return JvmPlatform.global_instance().get_platform_for_target(self)
@memoized_property
def jar_dependencies(self):
return OrderedSet(self.get_jar_dependencies())
def mark_extra_invalidation_hash_dirty(self):
del self.jar_dependencies
def get_jar_dependencies(self):
jar_deps = OrderedSet()
def collect_jar_deps(target):
if isinstance(target, JarLibrary):
jar_deps.update(target.payload.jars)
self.walk(work=collect_jar_deps)
return jar_deps
@property
def has_resources(self):
return len(self.resources) > 0
@property
def provides(self):
return self.payload.provides
@property
def resources(self):
# TODO: We should deprecate this method, but doing so will require changes to JVM publishing.
# see https://github.com/pantsbuild/pants/issues/4568
return [dependency for dependency in self.dependencies if isinstance(dependency, Resources)]
@property
def excludes(self):
return self.payload.excludes
@property
def services(self):
return self._services