@@ -142,22 +142,26 @@ def build(
142142 "cache_wheel_server_url" ,
143143 help = "url to a wheel server from where fromager can check if it had already built the wheel" ,
144144)
145+ @click .argument ("graph_file" )
145146@click .argument ("build_order_file" )
146147@click .pass_obj
147148def build_sequence (
148149 wkctx : context .WorkContext ,
150+ graph_file : str ,
149151 build_order_file : str ,
150152 force : bool ,
151153 cache_wheel_server_url : str | None ,
152154) -> None :
153155 """Build a sequence of wheels in order
154156
155- BUILD_ORDER_FILE is the build-order.json files to build
157+ GRAPH_FILE is a graph.json file containing the dependency relationships
158+ between packages, used to resolve build dependencies.
156159
157- SDIST_SERVER_URL is the URL for a PyPI-compatible package index hosting sdists
160+ BUILD_ORDER_FILE is the build-order.json file specifying the build order.
158161
159162 Performs the equivalent of the 'build' command for each item in
160- the build order file.
163+ the build order file, using the dependency graph to populate
164+ build environments instead of PEP 517 discovery hooks.
161165
162166 """
163167 server .start_wheel_server (wkctx )
@@ -173,6 +177,9 @@ def build_sequence(
173177 f"{ wkctx .wheel_server_url = } , { cache_wheel_server_url = } "
174178 )
175179
180+ logger .info ("reading dependency graph from %s" , graph_file )
181+ graph = dependency_graph .DependencyGraph .from_file (graph_file )
182+
176183 entries : list [BuildSequenceEntry ] = []
177184
178185 logger .info ("reading build order from %s" , build_order_file )
@@ -191,6 +198,10 @@ def build_sequence(
191198 else :
192199 req = Requirement (f"{ dist_name } =={ resolved_version } " )
193200
201+ build_requirements = _get_build_requirements_from_graph (
202+ graph , dist_name , resolved_version
203+ )
204+
194205 with req_ctxvar_context (req , resolved_version ):
195206 logger .info ("building %s" , resolved_version )
196207 entry = _build (
@@ -200,6 +211,7 @@ def build_sequence(
200211 source_download_url = source_download_url ,
201212 force = force ,
202213 cache_wheel_server_url = cache_wheel_server_url ,
214+ build_requirements = build_requirements ,
203215 )
204216 if entry .prebuilt :
205217 logger .info (
@@ -326,6 +338,7 @@ def _build(
326338 source_download_url : str ,
327339 force : bool ,
328340 cache_wheel_server_url : str | None ,
341+ build_requirements : typing .Iterable [dependency_graph .DependencyNode ] | None = None ,
329342) -> BuildSequenceEntry :
330343 """Handle one version of one wheel.
331344
@@ -417,12 +430,20 @@ def _build(
417430 )
418431
419432 # Build environment
420- build_env = build_environment .prepare_build_environment (
421- ctx = wkctx ,
422- req = req ,
423- version = resolved_version ,
424- sdist_root_dir = source_root_dir ,
425- )
433+ if build_requirements is not None :
434+ build_env = build_environment .prepare_build_environment_from_graph (
435+ ctx = wkctx ,
436+ req = req ,
437+ sdist_root_dir = source_root_dir ,
438+ build_requirements = build_requirements ,
439+ )
440+ else :
441+ build_env = build_environment .prepare_build_environment (
442+ ctx = wkctx ,
443+ req = req ,
444+ version = resolved_version ,
445+ sdist_root_dir = source_root_dir ,
446+ )
426447
427448 # Make a new source distribution, in case we patched the code.
428449 sdist_filename = sources .build_sdist (
@@ -544,6 +565,7 @@ def _build_parallel(
544565 source_download_url : str ,
545566 force : bool ,
546567 cache_wheel_server_url : str | None ,
568+ build_requirements : typing .Iterable [dependency_graph .DependencyNode ] | None = None ,
547569) -> BuildSequenceEntry :
548570 """
549571 This function runs in a thread to manage the build of a single package.
@@ -556,7 +578,24 @@ def _build_parallel(
556578 source_download_url = source_download_url ,
557579 force = force ,
558580 cache_wheel_server_url = cache_wheel_server_url ,
581+ build_requirements = build_requirements ,
582+ )
583+
584+
585+ def _get_build_requirements_from_graph (
586+ graph : dependency_graph .DependencyGraph ,
587+ dist_name : str ,
588+ version : Version ,
589+ ) -> list [dependency_graph .DependencyNode ]:
590+ """Look up build requirements for a package from the dependency graph."""
591+ node_key = f"{ canonicalize_name (dist_name )} =={ version } "
592+ node = graph .nodes .get (node_key )
593+ if node is None :
594+ raise KeyError (
595+ f"package { node_key } not found in dependency graph; "
596+ f"ensure the graph file matches the build order"
559597 )
598+ return list (node .iter_build_requirements ())
560599
561600
562601def _nodes_to_string (nodes : typing .Iterable [dependency_graph .DependencyNode ]) -> str :
@@ -681,6 +720,7 @@ def update_progressbar_cb(future: concurrent.futures.Future) -> None:
681720 source_download_url = node .download_url ,
682721 force = force ,
683722 cache_wheel_server_url = cache_wheel_server_url ,
723+ build_requirements = list (node .iter_build_requirements ()),
684724 )
685725 future .add_done_callback (update_progressbar_cb )
686726 future2node [future ] = node
0 commit comments