1
+ def _depaggregator_rule_impl (merged , ctx ):
2
+ """
3
+ This method processes declared deps and their transitive closures
4
+ to assemble a cohesive set of jars essential for the build process. During
5
+ this process, it excludes deps specified in 'deps_exclude', which
6
+ lists jar labels to be omitted from packaging due to issues that cannot
7
+ be resolved upstream. By default, with 'exclude_transitives' set to true, any
8
+ transitive deps that are only required by excluded deps
9
+ are also omitted, ensuring that only necessary transitives are included
10
+ in the final package. It uses 'deps_exclude_paths' to exclude deps
11
+ based on partial filename matches, ensuring problematic files are also
12
+ excluded from the build. This method ensures that only necessary
13
+ deps are included for the build process.
14
+ """
15
+ exclude_transitives = ctx .attr .exclude_transitives
16
+
17
+ # list to store jars to be included and a dictionary to track excluded jars
18
+ jars = []
19
+ excludes = {}
20
+
21
+ if exclude_transitives :
22
+ # Dictionary to track transitive dependency paths that should be excluded
23
+ transitives_excludes = {}
24
+
25
+ # List to store deps info for deps present in 'deps_exclude'
26
+ direct_excludes = []
27
+
28
+ # Iterate through the deps specified in 'deps_exclude' to collect
29
+ # jars that should be excluded from the final set.
30
+
31
+ for exclusion_info in ctx .attr .deps_exclude :
32
+ # For each excluded dependency, add its compile-time JARs to the exclusion list
33
+ for compile_jar in exclusion_info [JavaInfo ].full_compile_jars .to_list ():
34
+ excludes [compile_jar .path ] = True
35
+
36
+ if exclude_transitives :
37
+ # Mark all transitives of the current dependency as excluded
38
+ # This list will be updated later based on transitives of non-excluded deps
39
+ direct_excludes .append (str (exclusion_info ))
40
+ for transitive_jar in exclusion_info [JavaInfo ].transitive_runtime_jars .to_list ():
41
+ transitives_excludes [transitive_jar .path ] = True
42
+
43
+ if exclude_transitives :
44
+ # Iterate over all deps, for non-excluded deps, mark their transitives as included.
45
+ for deps_info in ctx .attr .deps :
46
+ # skip the current dependency if it is listed in 'deps_exclude'.
47
+ if str (deps_info ) in direct_excludes :
48
+ continue
49
+
50
+ # For non-excluded deps, mark them and their transitive deps as included (not to be excluded)
51
+ # (transitive_runtime_jars includes both the primary JAR and its transitive deps)
52
+ for transitive_jar in deps_info [JavaInfo ].transitive_runtime_jars .to_list ():
53
+ if transitive_jar .path in transitives_excludes :
54
+ transitives_excludes [transitive_jar .path ] = False
55
+
56
+ # update the excludes list
57
+ for dep_path in transitives_excludes :
58
+ # print("Transitive:", str(dep_path), "is excluded", transitives_excludes[dep_path])
59
+ if transitives_excludes [dep_path ]:
60
+ excludes [dep_path ] = True
61
+
62
+ # compute the final set of jars
63
+ for dep in merged .transitive_runtime_jars .to_list ():
64
+ # If the current JAR is in the exclusion list, skip it (do not include it)
65
+ if excludes .get (dep .path , None ) != None :
66
+ pass
67
+ else :
68
+ # Default to including the JAR unless a pattern match excludes it
69
+ include = True
70
+ for pattern in ctx .attr .deps_exclude_paths :
71
+ if dep .path .find (pattern ) > - 1 :
72
+ include = False
73
+ break
74
+ if include :
75
+ jars .append (dep )
76
+
77
+ return jars
78
+
79
+ def _deps_filter_transitive_impl (ctx ):
80
+ """
81
+ This rule filters out specified deps and JARs from the compile-time
82
+ and runtime deps. It utilizes the 'deps_exclude' attribute to omit
83
+ specific JAR labels and the 'deps_exclude_paths' attribute to exclude
84
+ deps based on partial paths in their filenames. By default, with
85
+ 'exclude_transitives' set to true, any transitive deps solely required
86
+ by the deps in 'deps_exclude' are also excluded. These exclusions ensure
87
+ the final collection includes only the necessary elements for the build
88
+ process, eliminating problematic deps.
89
+ """
90
+
91
+ if len (ctx .attr .deps ) == 0 :
92
+ fail ("Error: 'deps' cannot be an empty list" )
93
+
94
+ # magical incantation for getting upstream transitive closure of java deps
95
+ merged = java_common .merge ([dep [java_common .provider ] for dep in ctx .attr .deps ])
96
+ runtime_dep_merged = java_common .merge ([runtime_dep [java_common .provider ] for runtime_dep in ctx .attr .runtime_deps ])
97
+
98
+ compile_time_jars = _depaggregator_rule_impl (merged , ctx )
99
+ runtime_jars = _depaggregator_rule_impl (runtime_dep_merged , ctx )
100
+
101
+ if len (compile_time_jars ) == 0 :
102
+ fail ("Error: The rule must return at least one compile-time JAR. Excluding all compile-time dependencies is not allowed." )
103
+
104
+ return [
105
+ DefaultInfo (files = depset (compile_time_jars ,)),
106
+ JavaInfo (
107
+ compile_jar = None ,
108
+ output_jar = compile_time_jars [0 ], # output jar must be non-empty, adding a dummy value to it
109
+ exports = [JavaInfo (source_jar = jar , compile_jar = jar , output_jar = jar ) for jar in compile_time_jars ],
110
+ runtime_deps = [JavaInfo (source_jar = jar , compile_jar = jar , output_jar = jar ) for jar in
111
+ runtime_jars ],
112
+ deps = [JavaInfo (source_jar = jar , compile_jar = jar , output_jar = jar ) for jar in compile_time_jars ],
113
+ ),
114
+ ]
115
+
116
+
117
+ deps_filter_transitive = rule (
118
+ implementation = _deps_filter_transitive_impl ,
119
+ attrs = {
120
+ "deps" : attr .label_list (providers = [java_common .provider ]),
121
+ "runtime_deps" : attr .label_list (providers = [java_common .provider ], allow_empty = True ),
122
+ "deps_exclude" : attr .label_list (providers = [java_common .provider ], allow_empty = True ),
123
+ "deps_exclude_paths" : attr .string_list (),
124
+ "exclude_transitives" : attr .bool (default = True ),
125
+ },
126
+ )
0 commit comments