Skip to content

Commit 88a952d

Browse files
authored
Centralize dependency logic (#975)
* calling * lint * path * comments * comments * lint * comment
1 parent 30b80b0 commit 88a952d

19 files changed

+325
-235
lines changed

scala/private/common.bzl

Lines changed: 51 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -11,44 +11,15 @@ def write_manifest_file(actions, output_file, main_class):
1111

1212
def collect_jars(
1313
dep_targets,
14-
dependency_analyzer_is_off = True,
15-
unused_dependency_checker_is_off = True,
16-
plus_one_deps_is_off = True):
14+
dependency_mode,
15+
need_direct_info,
16+
need_indirect_info):
1717
"""Compute the runtime and compile-time dependencies from the given targets""" # noqa
1818

19-
if dependency_analyzer_is_off:
20-
return _collect_jars_when_dependency_analyzer_is_off(
21-
dep_targets,
22-
unused_dependency_checker_is_off,
23-
plus_one_deps_is_off,
24-
)
25-
else:
26-
return _collect_jars_when_dependency_analyzer_is_on(dep_targets)
27-
28-
def collect_plugin_paths(plugins):
29-
"""Get the actual jar paths of plugins as a depset."""
30-
paths = []
31-
for p in plugins:
32-
if hasattr(p, "path"):
33-
paths.append(p)
34-
elif JavaInfo in p:
35-
paths.extend([j.class_jar for j in p[JavaInfo].outputs.jars])
36-
# support http_file pointed at a jar. http_jar uses ijar,
37-
# which breaks scala macros
38-
39-
elif hasattr(p, "files"):
40-
paths.extend([f for f in p.files.to_list() if not_sources_jar(f.basename)])
41-
return depset(paths)
42-
43-
def _collect_jars_when_dependency_analyzer_is_off(
44-
dep_targets,
45-
unused_dependency_checker_is_off,
46-
plus_one_deps_is_off):
19+
transitive_compile_jars = []
20+
jars2labels = {}
4721
compile_jars = []
48-
plus_one_deps_compile_jars = []
4922
runtime_jars = []
50-
jars2labels = {}
51-
5223
deps_providers = []
5324

5425
for dep_target in dep_targets:
@@ -59,60 +30,67 @@ def _collect_jars_when_dependency_analyzer_is_off(
5930
compile_jars.append(java_provider.compile_jars)
6031
runtime_jars.append(java_provider.transitive_runtime_jars)
6132

62-
if not unused_dependency_checker_is_off:
33+
additional_transitive_compile_jars = _additional_transitive_compile_jars(
34+
java_provider = java_provider,
35+
dep_target = dep_target,
36+
dependency_mode = dependency_mode,
37+
)
38+
transitive_compile_jars.append(additional_transitive_compile_jars)
39+
40+
if need_direct_info or need_indirect_info:
41+
if need_indirect_info:
42+
all_jars = additional_transitive_compile_jars.to_list()
43+
else:
44+
all_jars = []
6345
add_labels_of_jars_to(
6446
jars2labels,
6547
dep_target,
66-
[],
48+
all_jars,
6749
java_provider.compile_jars.to_list(),
6850
)
6951

70-
if (not plus_one_deps_is_off) and (PlusOneDeps in dep_target):
71-
plus_one_deps_compile_jars.append(
72-
depset(transitive = [dep[JavaInfo].compile_jars for dep in dep_target[PlusOneDeps].direct_deps if JavaInfo in dep]),
73-
)
74-
7552
return struct(
7653
compile_jars = depset(transitive = compile_jars),
7754
transitive_runtime_jars = depset(transitive = runtime_jars),
7855
jars2labels = JarsToLabelsInfo(jars_to_labels = jars2labels),
79-
transitive_compile_jars = depset(transitive = compile_jars + plus_one_deps_compile_jars),
56+
transitive_compile_jars = depset(transitive = transitive_compile_jars),
8057
deps_providers = deps_providers,
8158
)
8259

83-
def _collect_jars_when_dependency_analyzer_is_on(dep_targets):
84-
transitive_compile_jars = []
85-
jars2labels = {}
86-
compile_jars = []
87-
runtime_jars = []
88-
deps_providers = []
89-
90-
for dep_target in dep_targets:
91-
# we require a JavaInfo for dependencies
92-
# must use java_import or scala_import if you have raw files
93-
java_provider = dep_target[JavaInfo]
94-
deps_providers.append(java_provider)
95-
current_dep_compile_jars = java_provider.compile_jars
96-
current_dep_transitive_compile_jars = java_provider.transitive_compile_time_jars
97-
runtime_jars.append(java_provider.transitive_runtime_jars)
98-
99-
compile_jars.append(current_dep_compile_jars)
100-
transitive_compile_jars.append(current_dep_transitive_compile_jars)
60+
def collect_plugin_paths(plugins):
61+
"""Get the actual jar paths of plugins as a depset."""
62+
paths = []
63+
for p in plugins:
64+
if hasattr(p, "path"):
65+
paths.append(p)
66+
elif JavaInfo in p:
67+
paths.extend([j.class_jar for j in p[JavaInfo].outputs.jars])
68+
# support http_file pointed at a jar. http_jar uses ijar,
69+
# which breaks scala macros
10170

102-
add_labels_of_jars_to(
103-
jars2labels,
104-
dep_target,
105-
current_dep_transitive_compile_jars.to_list(),
106-
current_dep_compile_jars.to_list(),
107-
)
71+
elif hasattr(p, "files"):
72+
paths.extend([f for f in p.files.to_list() if not_sources_jar(f.basename)])
73+
return depset(paths)
10874

109-
return struct(
110-
compile_jars = depset(transitive = compile_jars),
111-
transitive_runtime_jars = depset(transitive = runtime_jars),
112-
jars2labels = JarsToLabelsInfo(jars_to_labels = jars2labels),
113-
transitive_compile_jars = depset(transitive = transitive_compile_jars),
114-
deps_providers = deps_providers,
115-
)
75+
def _additional_transitive_compile_jars(
76+
java_provider,
77+
dep_target,
78+
dependency_mode):
79+
if dependency_mode == "transitive":
80+
return java_provider.transitive_compile_time_jars
81+
elif dependency_mode == "plus-one":
82+
# dep_target will not always have a PlusOneDeps provider, such as
83+
# with scala_maven_import_external, hence the need for the fallback.
84+
if PlusOneDeps in dep_target:
85+
plus_one_jars = [dep[JavaInfo].compile_jars for dep in dep_target[PlusOneDeps].direct_deps if JavaInfo in dep]
86+
87+
# plus_one_jars only contains the deps of deps, not the deps themselves.
88+
# Hence the need to include the dep's compile jars anyways
89+
return depset(transitive = plus_one_jars + [java_provider.compile_jars])
90+
else:
91+
return java_provider.compile_jars
92+
else: # direct
93+
return java_provider.compile_jars
11694

11795
# When import mavan_jar's for scala macros we have to use the jar:file requirement
11896
# since bazel 0.6.0 this brings in the source jar too

scala/private/dependency.bzl

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
# This file contains all computations for what the dependency mode is
2+
# (i.e. transitive, plus-one, direct, etc)
3+
# and what/how dependency analysis is performed (unused deps, strict deps, etc).
4+
5+
def new_dependency_info(
6+
dependency_mode,
7+
unused_deps_mode,
8+
strict_deps_mode,
9+
dependency_tracking_method):
10+
is_strict_deps_on = strict_deps_mode != "off"
11+
12+
# Currently we do not support running both strict and unused deps at the same time
13+
if is_strict_deps_on:
14+
unused_deps_mode = "off"
15+
16+
is_unused_deps_on = unused_deps_mode != "off"
17+
18+
need_direct_jars = is_strict_deps_on or is_unused_deps_on
19+
need_direct_targets = is_unused_deps_on
20+
21+
return struct(
22+
dependency_mode = dependency_mode,
23+
need_indirect_info = is_strict_deps_on,
24+
need_direct_jars = need_direct_jars,
25+
need_direct_targets = need_direct_targets,
26+
need_direct_info = need_direct_jars or need_direct_targets,
27+
dependency_tracking_method = "high-level",
28+
unused_deps_mode = unused_deps_mode,
29+
strict_deps_mode = strict_deps_mode,
30+
use_analyzer = is_strict_deps_on or is_unused_deps_on,
31+
)
32+
33+
# TODO(https://github.com/bazelbuild/rules_scala/issues/987): Clariy the situation
34+
def legacy_unclear_dependency_info_for_protobuf_scrooge(ctx):
35+
return new_dependency_info(
36+
dependency_mode = _legacy_unclear_dependency_mode_for_protobuf_scrooge(ctx),
37+
unused_deps_mode = "off",
38+
strict_deps_mode = get_strict_deps_mode(ctx),
39+
dependency_tracking_method = "high-level",
40+
)
41+
42+
# TODO(https://github.com/bazelbuild/rules_scala/issues/987): Clariy the situation
43+
def _legacy_unclear_dependency_mode_for_protobuf_scrooge(ctx):
44+
if is_strict_deps_on(ctx):
45+
return "transitive"
46+
else:
47+
return "direct"
48+
49+
def get_strict_deps_mode(ctx):
50+
if not hasattr(ctx.attr, "_dependency_analyzer_plugin"):
51+
return "off"
52+
53+
# when the strict deps FT is removed the "default" check
54+
# will be removed since "default" will mean it's turned on
55+
if ctx.fragments.java.strict_java_deps == "default":
56+
return "off"
57+
return ctx.fragments.java.strict_java_deps
58+
59+
def is_strict_deps_on(ctx):
60+
return get_strict_deps_mode(ctx) != "off"

scala/private/phases/phase_collect_exports_jars.bzl

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,4 +12,9 @@ def phase_collect_exports_jars(ctx, p):
1212
# Add information from exports (is key that AFTER all build actions/runfiles analysis)
1313
# Since after, will not show up in deploy_jar or old jars runfiles
1414
# Notice that compile_jars is intentionally transitive for exports
15-
return collect_jars(ctx.attr.exports)
15+
return collect_jars(
16+
ctx.attr.exports,
17+
"direct",
18+
False,
19+
False,
20+
)

scala/private/phases/phase_collect_jars.bzl

Lines changed: 6 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,6 @@
33
#
44
# DOCUMENT THIS
55
#
6-
load(
7-
"@io_bazel_rules_scala//scala/private:rule_impls.bzl",
8-
"is_dependency_analyzer_off",
9-
"is_plus_one_deps_off",
10-
)
116
load(
127
"@io_bazel_rules_scala//scala/private:common.bzl",
138
"collect_jars",
@@ -46,41 +41,32 @@ def phase_collect_jars_junit_test(ctx, p):
4641
)
4742
return _phase_collect_jars_default(ctx, p, args)
4843

49-
def phase_collect_jars_library_for_plugin_bootstrapping(ctx, p):
50-
args = struct(
51-
unused_dependency_checker_mode = "off",
52-
)
53-
return _phase_collect_jars_default(ctx, p, args)
54-
5544
def phase_collect_jars_common(ctx, p):
5645
return _phase_collect_jars_default(ctx, p)
5746

5847
def _phase_collect_jars_default(ctx, p, _args = struct()):
5948
return _phase_collect_jars(
6049
ctx,
50+
p,
6151
_args.base_classpath if hasattr(_args, "base_classpath") else p.scalac_provider.default_classpath,
6252
_args.extra_deps if hasattr(_args, "extra_deps") else [],
6353
_args.extra_runtime_deps if hasattr(_args, "extra_runtime_deps") else [],
64-
_args.unused_dependency_checker_mode if hasattr(_args, "unused_dependency_checker_mode") else p.unused_deps_checker,
6554
)
6655

6756
# Extract very common code out from dependency analysis into single place
6857
# automatically adds dependency on scala-library and scala-reflect
6958
# collects jars from deps, runtime jars from runtime_deps, and
7059
def _phase_collect_jars(
7160
ctx,
61+
p,
7262
base_classpath,
7363
extra_deps,
74-
extra_runtime_deps,
75-
unused_dependency_checker_mode):
76-
unused_dependency_checker_is_off = unused_dependency_checker_mode == "off"
77-
dependency_analyzer_is_off = is_dependency_analyzer_off(ctx)
78-
64+
extra_runtime_deps):
7965
deps_jars = collect_jars(
8066
ctx.attr.deps + extra_deps + base_classpath,
81-
dependency_analyzer_is_off,
82-
unused_dependency_checker_is_off,
83-
is_plus_one_deps_off(ctx),
67+
p.dependency.dependency_mode,
68+
p.dependency.need_direct_info,
69+
p.dependency.need_indirect_info,
8470
)
8571

8672
(

scala/private/phases/phase_compile.bzl

Lines changed: 9 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -42,11 +42,6 @@ def phase_compile_library(ctx, p):
4242

4343
def phase_compile_library_for_plugin_bootstrapping(ctx, p):
4444
args = struct(
45-
unused_dependency_checker_ignored_targets = [
46-
target.label
47-
for target in p.scalac_provider.default_classpath + ctx.attr.exports
48-
],
49-
unused_dependency_checker_mode = "off",
5045
buildijar = ctx.attr.build_ijar,
5146
)
5247
return _phase_compile_default(ctx, p, args)
@@ -114,8 +109,7 @@ def _phase_compile_default(ctx, p, _args = struct()):
114109
_args.srcjars if hasattr(_args, "srcjars") else depset(),
115110
_args.buildijar if hasattr(_args, "buildijar") else True,
116111
_args.implicit_junit_deps_needed_for_java_compilation if hasattr(_args, "implicit_junit_deps_needed_for_java_compilation") else [],
117-
_args.unused_dependency_checker_ignored_targets if hasattr(_args, "unused_dependency_checker_ignored_targets") else [],
118-
_args.unused_dependency_checker_mode if hasattr(_args, "unused_dependency_checker_mode") else p.unused_deps_checker,
112+
unused_dependency_checker_ignored_targets = _args.unused_dependency_checker_ignored_targets if hasattr(_args, "unused_dependency_checker_ignored_targets") else [],
119113
)
120114

121115
def _phase_compile(
@@ -125,8 +119,7 @@ def _phase_compile(
125119
buildijar,
126120
# TODO: generalize this hack
127121
implicit_junit_deps_needed_for_java_compilation,
128-
unused_dependency_checker_ignored_targets,
129-
unused_dependency_checker_mode):
122+
unused_dependency_checker_ignored_targets):
130123
manifest = ctx.outputs.manifest
131124
jars = p.collect_jars.compile_jars
132125
rjars = p.collect_jars.transitive_runtime_jars
@@ -144,10 +137,10 @@ def _phase_compile(
144137
transitive_compile_jars,
145138
jars2labels,
146139
implicit_junit_deps_needed_for_java_compilation,
147-
unused_dependency_checker_mode,
148-
unused_dependency_checker_ignored_targets,
140+
p.dependency,
149141
deps_providers,
150142
default_classpath,
143+
unused_dependency_checker_ignored_targets,
151144
)
152145

153146
# TODO: simplify the return values and use provider
@@ -169,10 +162,10 @@ def _compile_or_empty(
169162
transitive_compile_jars,
170163
jars2labels,
171164
implicit_junit_deps_needed_for_java_compilation,
172-
unused_dependency_checker_mode,
173-
unused_dependency_checker_ignored_targets,
165+
dependency_info,
174166
deps_providers,
175-
default_classpath):
167+
default_classpath,
168+
unused_dependency_checker_ignored_targets):
176169
# We assume that if a srcjar is present, it is not empty
177170
if len(ctx.files.srcs) + len(srcjars.to_list()) == 0:
178171
_build_nosrc_jar(ctx)
@@ -190,11 +183,6 @@ def _compile_or_empty(
190183
in_srcjars = _get_files_with_extension(ctx, _srcjar_extension)
191184
all_srcjars = depset(in_srcjars, transitive = [srcjars])
192185

193-
# We are not able to verify whether dependencies are used when compiling java sources
194-
# Thus we disable unused dependency checking when java sources are found
195-
if len(java_srcs) != 0:
196-
unused_dependency_checker_mode = "off"
197-
198186
sources = scala_srcs + java_srcs
199187
_compile_scala(
200188
ctx,
@@ -216,9 +204,8 @@ def _compile_or_empty(
216204
ctx.attr.expect_java_output,
217205
ctx.attr.scalac_jvm_flags,
218206
ctx.attr._scalac,
219-
unused_dependency_checker_ignored_targets =
220-
unused_dependency_checker_ignored_targets,
221-
unused_dependency_checker_mode = unused_dependency_checker_mode,
207+
dependency_info,
208+
unused_dependency_checker_ignored_targets,
222209
)
223210

224211
# build ijar if needed

0 commit comments

Comments
 (0)