Skip to content

Commit 7ebf9a2

Browse files
authored
Move ensure_rust_toolchain to buildall (#83)
Rather than installing the rust toolchain in each build step that uses rust, do it once in buildall. Split off from #81.
1 parent 632c8e6 commit 7ebf9a2

File tree

3 files changed

+51
-3
lines changed

3 files changed

+51
-3
lines changed

pyodide_build/build_env.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,7 @@
1919
from pyodide_build.recipe import load_all_recipes
2020

2121
RUST_BUILD_PRELUDE = """
22-
rustup toolchain install ${RUST_TOOLCHAIN} && rustup default ${RUST_TOOLCHAIN}
23-
rustup target add wasm32-unknown-emscripten --toolchain ${RUST_TOOLCHAIN}
22+
rustup default ${RUST_TOOLCHAIN}
2423
"""
2524

2625

pyodide_build/buildall.py

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
from pyodide_build.build_env import BuildArgs
3434
from pyodide_build.buildpkg import needs_rebuild
3535
from pyodide_build.common import (
36+
exit_with_stdio,
3637
extract_wheel_metadata_file,
3738
find_matching_wheels,
3839
find_missing_executables,
@@ -158,6 +159,8 @@ def build(self, build_args: BuildArgs, build_dir: Path) -> None:
158159
# been updated and should be rebuilt even though its own
159160
# files haven't been updated.
160161
"--force-rebuild",
162+
# We already did the rust setup in buildall
163+
"--skip-rust-setup",
161164
],
162165
check=False,
163166
stdout=subprocess.DEVNULL,
@@ -645,6 +648,28 @@ def run(self, n_jobs: int, already_built: set[str]) -> None:
645648
self.build_queue.put((job_priority(dependent), dependent))
646649

647650

651+
def _ensure_rust_toolchain():
652+
rust_toolchain = build_env.get_build_flag("RUST_TOOLCHAIN")
653+
result = subprocess.run(
654+
["rustup", "toolchain", "install", rust_toolchain], check=False
655+
)
656+
if result.returncode == 0:
657+
result = subprocess.run(
658+
[
659+
"rustup",
660+
"target",
661+
"add",
662+
"wasm32-unknown-emscripten",
663+
"--toolchain",
664+
rust_toolchain,
665+
],
666+
check=False,
667+
)
668+
if result.returncode != 0:
669+
logger.error("ERROR: rustup toolchain install failed")
670+
exit_with_stdio(result)
671+
672+
648673
def build_from_graph(
649674
pkg_map: dict[str, BasePackage],
650675
build_args: BuildArgs,
@@ -686,6 +711,12 @@ def build_from_graph(
686711
for pkg_name in needs_build:
687712
pkg_map[pkg_name].unbuilt_host_dependencies.difference_update(already_built)
688713

714+
needs_rust = any(
715+
pkg_map[pkg_name].meta.is_rust_package() for pkg_name in needs_build
716+
)
717+
if needs_rust:
718+
_ensure_rust_toolchain()
719+
689720
if already_built:
690721
logger.info(
691722
"The following packages are already built: [bold]%s[/bold]",

pyodide_build/cli/build_recipes.py

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
import typer
66

7-
from pyodide_build import build_env, buildall
7+
from pyodide_build import build_env, buildall, recipe
88
from pyodide_build.build_env import BuildArgs, init_environment
99
from pyodide_build.buildpkg import RecipeBuilder
1010
from pyodide_build.common import get_num_cores
@@ -17,6 +17,7 @@ class Args:
1717
build_dir: Path
1818
install_dir: Path
1919
build_args: BuildArgs
20+
skip_rust_setup: bool
2021
force_rebuild: bool
2122
n_jobs: int
2223

@@ -28,6 +29,7 @@ def __init__(
2829
install_dir: Path | str | None = None,
2930
build_args: BuildArgs,
3031
force_rebuild: bool,
32+
skip_rust_setup: bool = False,
3133
n_jobs: int | None = None,
3234
):
3335
cwd = Path.cwd()
@@ -41,6 +43,7 @@ def __init__(
4143
)
4244
self.build_args = build_args
4345
self.force_rebuild = force_rebuild
46+
self.skip_rust_setup = skip_rust_setup
4447
self.n_jobs = n_jobs or get_num_cores()
4548
if not self.recipe_dir.is_dir():
4649
raise FileNotFoundError(f"Recipe directory {self.recipe_dir} not found")
@@ -93,6 +96,11 @@ def build_recipes_no_deps(
9396
"--continue",
9497
help="Continue a build from the middle. For debugging. Implies '--force-rebuild'",
9598
),
99+
skip_rust_setup: bool = typer.Option(
100+
False,
101+
"--skip-rust-setup",
102+
help="Don't setup rust environment when building a rust package",
103+
),
96104
) -> None:
97105
"""Build packages using yaml recipes but don't try to resolve dependencies"""
98106
init_environment()
@@ -113,15 +121,25 @@ def build_recipes_no_deps(
113121
build_dir=build_dir,
114122
recipe_dir=recipe_dir,
115123
force_rebuild=force_rebuild,
124+
skip_rust_setup=skip_rust_setup,
116125
)
117126

118127
return build_recipes_no_deps_impl(packages, args, continue_)
119128

120129

130+
def _rust_setup(recipe_dir: Path, packages: list[str]):
131+
recipes = recipe.load_recipes(recipe_dir, packages, False)
132+
if any(recipe.is_rust_package() for recipe in recipes.values()):
133+
buildall._ensure_rust_toolchain()
134+
135+
121136
def build_recipes_no_deps_impl(
122137
packages: list[str], args: Args, continue_: bool
123138
) -> None:
124139
# TODO: use multiprocessing?
140+
if not args.skip_rust_setup:
141+
_rust_setup(args.recipe_dir, packages)
142+
125143
for package in packages:
126144
package_path = args.recipe_dir / package
127145
package_build_dir = args.build_dir / package / "build"

0 commit comments

Comments
 (0)