@@ -73,11 +73,11 @@ def _clean_module(base_module: str, module: str) -> str:
7373# Set common fields for a target entry.
7474# NOTE: This function doesn't populate `srcs`. Instead return an empty `srcs` dict for downstream logic to populate.
7575def _set_entry_common_fields(
76- entry: dict[str, typing.Any] ,
76+ entry: dict,
7777 attrs: bxl.LazyAttrs,
7878 fs: bxl.Filesystem,
7979 target: bxl.ConfiguredTargetNode,
80- known_targets: dict) -> dict[str, list[str | bxl.EnsuredArtifact]]:
80+ known_targets: dict[TargetLabel, bxl.ConfiguredTargetNode] ) -> dict[str, list[str | bxl.EnsuredArtifact]]:
8181 srcs = {}
8282 deps = []
8383 entry["srcs"] = srcs
@@ -102,13 +102,136 @@ def _set_entry_common_fields(
102102
103103 return srcs
104104
105+ def _handle_alias(
106+ entry: dict,
107+ attrs: bxl.LazyAttrs,
108+ target: bxl.ConfiguredTargetNode) -> None:
109+ actual = attrs.get("actual")
110+ if actual != None and actual.value() != None:
111+ entry["alias"] = actual.value().raw_target()
112+ else:
113+ fail("Alias has no actual target".format(target.label))
114+
115+ def _handle_genrule(
116+ entry: dict,
117+ attrs: bxl.LazyAttrs,
118+ fs: bxl.Filesystem,
119+ target: bxl.ConfiguredTargetNode,
120+ known_targets: dict[TargetLabel, bxl.ConfiguredTargetNode],
121+ to_remove: dict[str, None],
122+ to_build: list,
123+ to_insert: list,
124+ genrule_to_insert: list) -> None:
125+ labels = attrs.get("labels")
126+ if "custom_rule_internal" in labels.value():
127+ # skip internal targets, since they will be materialized as part
128+ # of their including target
129+ to_remove[str(target.label.raw_target())] = None
130+ return
131+
132+ srcs = _set_entry_common_fields(entry, attrs, fs, target, known_targets)
133+ to_build.append(target)
134+
135+ # Only one of these will have a value, but get both of them now since
136+ # it's easy.
137+ out = attrs.get("out")
138+ outs = attrs.get("outs")
139+ if out != None and out.value() != None:
140+ items = {out.value(): out.value()}
141+ elif outs != None and outs.value() != None:
142+ items = outs.value()
143+ else:
144+ fail(target)
145+
146+ if len(items) == 1:
147+ module_path = list(items.keys())[0]
148+ for suffix in _MODULE_SUFFIXES:
149+ if module_path.endswith(suffix):
150+ to_build.append(target)
151+ to_insert.append((srcs, _clean_module("", module_path), target.label.with_sub_target()))
152+ break
153+ else:
154+ # we need to handle building the full genrule
155+ genrule_to_insert.append((target, entry))
156+ for (module_path, src_paths) in items.items():
157+ if len(src_paths) < 1:
158+ fail("Target src has no output path: {}".format(target.label))
159+ for suffix in _MODULE_SUFFIXES:
160+ if module_path.endswith(suffix):
161+ _append_or_default_if_module(srcs, _clean_module("", module_path), src_paths[0])
162+ break
163+
164+ def _handle_python_library(
165+ entry: dict,
166+ attrs: bxl.LazyAttrs,
167+ fs: bxl.Filesystem,
168+ target: bxl.ConfiguredTargetNode,
169+ known_targets: dict[TargetLabel, bxl.ConfiguredTargetNode],
170+ to_remove: dict[str, None],
171+ to_build: list,
172+ to_insert: list) -> None:
173+ base_module = attrs.get("base_module")
174+ if base_module != None and base_module.value() != None:
175+ base_module = base_module.value()
176+ else:
177+ base_module = target.label.package
178+
179+ srcs = _set_entry_common_fields(entry, attrs, fs, target, known_targets)
180+
181+ # add type stubs first, so that they're preferred by Pyrefly
182+ type_stubs = attrs.get("type_stubs")
183+ type_stubs = {} if type_stubs == None else type_stubs.value()
184+ _get_and_materialize_sources(
185+ type_stubs,
186+ to_remove,
187+ base_module,
188+ srcs,
189+ to_build,
190+ to_insert,
191+ fs,
192+ )
193+
194+ # python_binary might be the root target, which doesn't have `srcs`.
195+ attr_srcs = attrs.get("srcs")
196+ attr_srcs = {} if attr_srcs == None else attr_srcs.value()
197+ _get_and_materialize_sources(
198+ attr_srcs,
199+ to_remove,
200+ base_module,
201+ srcs,
202+ to_build,
203+ to_insert,
204+ fs,
205+ )
206+
207+ def _build_generated_files(
208+ ctx: bxl.Context,
209+ to_build: list,
210+ to_insert: list,
211+ genrule_to_insert: list) -> None:
212+ if not to_build:
213+ return
214+
215+ built = ctx.build(to_build)
216+ ensured = ctx.output.ensure_multiple(built)
217+
218+ # handle individual generated files
219+ for srcs, module_name, target in to_insert:
220+ _append_or_default_if_module(srcs, module_name, ensured[target][0].rel_path())
221+
222+ # handle genrules
223+ for target, entry in genrule_to_insert:
224+ label = target.label.with_sub_target()
225+ relative_to = ensured[label][0].rel_path()
226+ entry["relative_to"] = relative_to
227+
105228def _get_and_materialize_sources(
106- to_add: list[typing.Any] | dict[str, typing.Any] ,
107- to_remove: dict[str, typing.Any ],
229+ to_add: list | dict,
230+ to_remove: dict[str, None ],
108231 base_module: str,
109232 srcs: dict[str, list[str | bxl.EnsuredArtifact]],
110- to_build: list[typing.Any] ,
111- to_insert: list[typing.Any] ,
233+ to_build: list,
234+ to_insert: list,
112235 fs: bxl.Filesystem):
113236 if type(to_add) == type([]):
114237 for v in to_add:
@@ -181,101 +304,13 @@ def _main(ctx: bxl.Context) -> None:
181304 entries[str(x.label.raw_target())] = entry
182305
183306 if x.rule_type == "prelude//rules.bzl:alias":
184- actual = attrs.get("actual")
185- if actual != None and actual.value() != None:
186- entry["alias"] = actual.value().raw_target()
187- else:
188- fail("Alias has no actual target".format(x.label))
189-
307+ _handle_alias(entry, attrs, x)
190308 elif x.rule_type == "prelude//rules.bzl:genrule":
191- labels = attrs.get("labels")
192- if "custom_rule_internal" in labels.value():
193- # skip internal targets, since they will be materialized as part
194- # of their including target
195- to_remove[str(x.label.raw_target())] = None
196- continue
197-
198- srcs = _set_entry_common_fields(entry, attrs, fs, x, known_targets)
199- to_build.append(x)
200-
201- # Only one of these will have a value, but get both of them now since
202- # it's easy.
203- out = attrs.get("out")
204- outs = attrs.get("outs")
205- if out != None and out.value() != None:
206- items = {out.value(): out.value()}
207- elif outs != None and outs.value() != None:
208- items = outs.value()
209- else:
210- fail(x)
211-
212- if len(items) == 1:
213- module_path = list(items.keys())[0]
214- for suffix in _MODULE_SUFFIXES:
215- if module_path.endswith(suffix):
216- to_build.append(x)
217- to_insert.append((srcs, _clean_module("", module_path), x.label.with_sub_target()))
218- break
219- else:
220- # we need to handle building the full genrule
221- genrule_to_insert.append((x, entry))
222- for (module_path, src_paths) in items.items():
223- if len(src_paths) < 1:
224- fail("Target src has no output path: {}".format(x.label))
225- for suffix in _MODULE_SUFFIXES:
226- if module_path.endswith(suffix):
227- _append_or_default_if_module(srcs, _clean_module("", module_path), src_paths[0])
228- break
229-
309+ _handle_genrule(entry, attrs, fs, x, known_targets, to_remove, to_build, to_insert, genrule_to_insert)
230310 else:
231- # python_library and other rules
232- base_module = attrs.get("base_module")
233- if base_module != None and base_module.value() != None:
234- base_module = base_module.value()
235- else:
236- base_module = x.label.package
237-
238- srcs = _set_entry_common_fields(entry, attrs, fs, x, known_targets)
239-
240- # add type stubs first, so that they're preferred by Pyrefly
241- type_stubs = attrs.get("type_stubs")
242- type_stubs = {} if type_stubs == None else type_stubs.value()
243- _get_and_materialize_sources(
244- type_stubs,
245- to_remove,
246- base_module,
247- srcs,
248- to_build,
249- to_insert,
250- fs,
251- )
252-
253- # python_binary might be the root target, which doesn't have `srcs`.
254- attr_srcs = attrs.get("srcs")
255- attr_srcs = {} if attr_srcs == None else attr_srcs.value()
256- _get_and_materialize_sources(
257- attr_srcs,
258- to_remove,
259- base_module,
260- srcs,
261- to_build,
262- to_insert,
263- fs,
264- )
265-
266- if to_build:
267- built = ctx.build(to_build)
268- ensured = ctx.output.ensure_multiple(built)
269-
270- # handle individual generated files
271- for srcs, module_name, target in to_insert:
272- _append_or_default_if_module(srcs, module_name, ensured[target][0].rel_path())
273-
274- # handle genrules
275- for target, entry in genrule_to_insert:
276- label = target.label.with_sub_target()
277- relative_to = ensured[label][0].rel_path()
278- entry["relative_to"] = relative_to
311+ _handle_python_library(entry, attrs, fs, x, known_targets, to_remove, to_build, to_insert)
312+
313+ _build_generated_files(ctx, to_build, to_insert, genrule_to_insert)
279314
280315 # remove any targets we decided we shouldn't output
281316 for remove in to_remove:
0 commit comments