1
1
load ("@io_bazel_rules_scala//scala:jars_to_labels.bzl" , "JarsToLabelsInfo" )
2
2
load ("@io_bazel_rules_scala//scala:plusone.bzl" , "PlusOneDeps" )
3
+ load ("@io_bazel_rules_scala//scala:providers.bzl" , "ScalaInfo" )
3
4
load ("@bazel_skylib//lib:paths.bzl" , "paths" )
4
5
5
6
def write_manifest_file (actions , output_file , main_class ):
@@ -22,6 +23,7 @@ def collect_jars(
22
23
compile_jars = []
23
24
runtime_jars = []
24
25
deps_providers = []
26
+ macro_classpath = []
25
27
26
28
for dep_target in dep_targets :
27
29
# we require a JavaInfo for dependencies
@@ -50,11 +52,34 @@ def collect_jars(
50
52
java_provider .compile_jars .to_list (),
51
53
)
52
54
55
+ # Macros are different from ordinary targets in that they’re used at compile time instead of at runtime. That
56
+ # means that both their compile-time classpath and runtime classpath are needed at compile time. We could have
57
+ # `scala_macro_library` targets include their runtime dependencies in their compile-time dependencies, but then
58
+ # we wouldn't have any guarantees classpath order.
59
+ #
60
+ # Consider the following scenario. Target A depends on targets B and C. Target C is a macro target, whereas
61
+ # target B isn't. Targets C depends on target B. If target A doesn't include the runtime version of target C on
62
+ # the compile classpath before the compile (`ijar`d) version of target B that target C depends on, then target A
63
+ # won't use the correct version of target B at compile-time when evaluating the macros contained in target C.
64
+ #
65
+ # For that reason, we opt for a different approach: have `scala_macro_library` targets export `JavaInfo`
66
+ # providers as normal, but put their transitive runtime dependencies first on the classpath. Note that we
67
+ # shouldn't encounter any issues with external dependencies, so long as they aren't `ijar`d.
68
+ if ScalaInfo in dep_target and dep_target [ScalaInfo ].contains_macros :
69
+ macro_classpath .append (java_provider .transitive_runtime_jars )
70
+
71
+ add_labels_of_jars_to (
72
+ jars2labels ,
73
+ dep_target ,
74
+ [],
75
+ java_provider .transitive_runtime_jars .to_list (),
76
+ )
77
+
53
78
return struct (
54
- compile_jars = depset (transitive = compile_jars ),
79
+ compile_jars = depset (order = "preorder" , transitive = macro_classpath + compile_jars ),
55
80
transitive_runtime_jars = depset (transitive = runtime_jars ),
56
81
jars2labels = JarsToLabelsInfo (jars_to_labels = jars2labels ),
57
- transitive_compile_jars = depset (transitive = transitive_compile_jars ),
82
+ transitive_compile_jars = depset (order = "preorder" , transitive = macro_classpath + transitive_compile_jars ),
58
83
deps_providers = deps_providers ,
59
84
)
60
85
0 commit comments