From 30cbe323f3182f4dc9482221def13292b9afd3b9 Mon Sep 17 00:00:00 2001 From: Hood Chatham Date: Mon, 13 Jan 2025 21:36:34 +0100 Subject: [PATCH 01/21] Build with wasm exception handling For now, we need to use a custom rust toolchain for this. Apparently all alternatives to this don't work. -Zbuild-std doesn't work with panic=abort (https://github.com/rust-lang/cargo/issues/7359) and my attempts to use a custom sysroot with either https://github.com/RalfJung/rustc-build-sysroot/ or https://github.com/DianaNites/cargo-sysroot/ seem to hit the same problem as with `-Zbuild-std`. Thus, I think the only reasonable way to go is to build the sysroot from the rust source directory. Perhaps we can eventually approach this by copying the `lib/rustlib/wasm32-unknown-emscripten/lib/` folder out of the build of the rust compiler on top of a nightly install of the compiler. For now, there is the additional problem that we need this patch to fix unwind=abort: https://github.com/rust-lang/rust/pull/135450 I got my copy of the rust compiler by checking out this commit: https://github.com/hoodmane/rust/commit/052ba16e2c1da50c80042cc7291b42e105a1e855 two commits ahead of the rust main branch and running: ``` ./x build --stage 2 --target x86_64-unknown-linux-gnu,wasm32-unknown-emscripten ``` --- pyodide_build/build_env.py | 3 +- pyodide_build/buildpkg.py | 16 +++++++ pyodide_build/config.py | 2 +- pyodide_build/xbuildenv.py | 89 +++++++++++++++++++------------------- 4 files changed, 63 insertions(+), 47 deletions(-) diff --git a/pyodide_build/build_env.py b/pyodide_build/build_env.py index eeaca3a4..1773738e 100644 --- a/pyodide_build/build_env.py +++ b/pyodide_build/build_env.py @@ -19,8 +19,7 @@ from pyodide_build.recipe import load_all_recipes RUST_BUILD_PRELUDE = """ -rustup toolchain install ${RUST_TOOLCHAIN} && rustup default ${RUST_TOOLCHAIN} -rustup target add wasm32-unknown-emscripten --toolchain ${RUST_TOOLCHAIN} +rustup default ${RUST_TOOLCHAIN} """ diff --git a/pyodide_build/buildpkg.py b/pyodide_build/buildpkg.py index 9bf1a4d4..dc58e8b8 100755 --- a/pyodide_build/buildpkg.py +++ b/pyodide_build/buildpkg.py @@ -460,6 +460,21 @@ def _get_helper_vars(self) -> dict[str, str]: } +def _ensure_rust_toolchain(): + return + pyodide_root = get_pyodide_root() + toolchain_version = "emscripten_2025-01-13_052ba16" + toolchain_path = (pyodide_root / ".rust-toolchain" / toolchain_version) + if toolchain_path.exists(): + return + from .xbuildenv import download_and_unpack_archive + download_and_unpack_archive("http://pyodide-cache.s3-website-us-east-1.amazonaws.com/rustc/{toolchain_version}", toolchain_path) + result = subprocess.run(["rustup", "toolchain", "link", toolchain_version, toolchain_path], check = False) + if result.returncode != 0: + logger.error("ERROR: rustup toolchain install failed") + exit_with_stdio(result) + + class RecipeBuilderPackage(RecipeBuilder): """ Recipe builder for python packages. @@ -467,6 +482,7 @@ class RecipeBuilderPackage(RecipeBuilder): def _build_package(self, bash_runner: BashRunnerWithSharedEnvironment) -> None: if self.recipe.is_rust_package(): + _ensure_rust_toolchain() bash_runner.run( RUST_BUILD_PRELUDE, script_name="rust build prelude", diff --git a/pyodide_build/config.py b/pyodide_build/config.py index 89cdc809..126d8558 100644 --- a/pyodide_build/config.py +++ b/pyodide_build/config.py @@ -207,7 +207,7 @@ def to_env(self) -> dict[str, str]: "rustflags": "-C link-arg=-sSIDE_MODULE=2 -C link-arg=-sWASM_BIGINT -Z link-native-libraries=no", "cargo_build_target": "wasm32-unknown-emscripten", "cargo_target_wasm32_unknown_emscripten_linker": "emcc", - "rust_toolchain": "nightly-2024-01-29", + "rust_toolchain": "emscripten_2025-01-13_052ba16", # Other configuration "pyodide_jobs": "1", "skip_emscripten_version_check": "0", diff --git a/pyodide_build/xbuildenv.py b/pyodide_build/xbuildenv.py index e09cadda..038bc029 100644 --- a/pyodide_build/xbuildenv.py +++ b/pyodide_build/xbuildenv.py @@ -21,6 +21,50 @@ PYTHON_VERSION_MARKER_FILE = ".build-python-version" +def download_and_unpack_archive(url: str, path: Path) -> None: + """ + Download the cross-build environment from the given URL and extract it to the given path. + + Parameters + ---------- + url + URL to download the cross-build environment from. + path + Path to extract the cross-build environment to. + If the path already exists, raise an error. + """ + logger.info("Downloading Pyodide cross-build environment from %s", url) + + if path.exists(): + raise FileExistsError(f"Path {path} already exists") + + try: + resp = urlopen(url) + data = resp.read() + except Exception as e: + raise ValueError( + f"Failed to download cross-build environment from {url}" + ) from e + + # FIXME: requests makes a verbose output (see: https://github.com/pyodide/pyodide/issues/4810) + # r = requests.get(url) + + # if r.status_code != 200: + # raise ValueError( + # f"Failed to download cross-build environment from {url} (status code: {r.status_code})" + # ) + + with NamedTemporaryFile(suffix=".tar") as f: + f_path = Path(f.name) + f_path.write_bytes(data) + with warnings.catch_warnings(): + # Python 3.12-3.13 emits a DeprecationWarning when using shutil.unpack_archive without a filter, + # but filter doesn't work well for zip files, so we suppress the warning until we find a better solution. + # https://github.com/python/cpython/issues/112760 + warnings.simplefilter("ignore") + shutil.unpack_archive(str(f_path), path) + + class CrossBuildEnvManager: """ Manager for the cross-build environment. @@ -194,7 +238,7 @@ def install( download_path, ) else: - self._download(download_url, download_path) + download_and_unpack_archive(download_url, download_path) try: # there is an redundant directory "xbuildenv" inside the xbuildenv archive @@ -240,49 +284,6 @@ def _find_latest_version(self) -> str: return latest.version - def _download(self, url: str, path: Path) -> None: - """ - Download the cross-build environment from the given URL and extract it to the given path. - - Parameters - ---------- - url - URL to download the cross-build environment from. - path - Path to extract the cross-build environment to. - If the path already exists, raise an error. - """ - logger.info("Downloading Pyodide cross-build environment from %s", url) - - if path.exists(): - raise FileExistsError(f"Path {path} already exists") - - try: - resp = urlopen(url) - data = resp.read() - except Exception as e: - raise ValueError( - f"Failed to download cross-build environment from {url}" - ) from e - - # FIXME: requests makes a verbose output (see: https://github.com/pyodide/pyodide/issues/4810) - # r = requests.get(url) - - # if r.status_code != 200: - # raise ValueError( - # f"Failed to download cross-build environment from {url} (status code: {r.status_code})" - # ) - - with NamedTemporaryFile(suffix=".tar") as f: - f_path = Path(f.name) - f_path.write_bytes(data) - with warnings.catch_warnings(): - # Python 3.12-3.13 emits a DeprecationWarning when using shutil.unpack_archive without a filter, - # but filter doesn't work well for zip files, so we suppress the warning until we find a better solution. - # https://github.com/python/cpython/issues/112760 - warnings.simplefilter("ignore") - shutil.unpack_archive(str(f_path), path) - def _install_cross_build_packages( self, xbuildenv_root: Path, xbuildenv_pyodide_root: Path ) -> None: From a02dda77bab885792b1f8c615b4128da512ae5cb Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 13 Jan 2025 20:54:04 +0000 Subject: [PATCH 02/21] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- pyodide_build/buildpkg.py | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/pyodide_build/buildpkg.py b/pyodide_build/buildpkg.py index dc58e8b8..bb697678 100755 --- a/pyodide_build/buildpkg.py +++ b/pyodide_build/buildpkg.py @@ -464,12 +464,18 @@ def _ensure_rust_toolchain(): return pyodide_root = get_pyodide_root() toolchain_version = "emscripten_2025-01-13_052ba16" - toolchain_path = (pyodide_root / ".rust-toolchain" / toolchain_version) + toolchain_path = pyodide_root / ".rust-toolchain" / toolchain_version if toolchain_path.exists(): return from .xbuildenv import download_and_unpack_archive - download_and_unpack_archive("http://pyodide-cache.s3-website-us-east-1.amazonaws.com/rustc/{toolchain_version}", toolchain_path) - result = subprocess.run(["rustup", "toolchain", "link", toolchain_version, toolchain_path], check = False) + + download_and_unpack_archive( + "http://pyodide-cache.s3-website-us-east-1.amazonaws.com/rustc/{toolchain_version}", + toolchain_path, + ) + result = subprocess.run( + ["rustup", "toolchain", "link", toolchain_version, toolchain_path], check=False + ) if result.returncode != 0: logger.error("ERROR: rustup toolchain install failed") exit_with_stdio(result) From 3186d203a0d449dbfd6682a1671828f249809917 Mon Sep 17 00:00:00 2001 From: Hood Chatham Date: Mon, 13 Jan 2025 22:09:01 +0100 Subject: [PATCH 03/21] Fix --- pyodide_build/buildpkg.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/pyodide_build/buildpkg.py b/pyodide_build/buildpkg.py index bb697678..06059638 100755 --- a/pyodide_build/buildpkg.py +++ b/pyodide_build/buildpkg.py @@ -461,7 +461,6 @@ def _get_helper_vars(self) -> dict[str, str]: def _ensure_rust_toolchain(): - return pyodide_root = get_pyodide_root() toolchain_version = "emscripten_2025-01-13_052ba16" toolchain_path = pyodide_root / ".rust-toolchain" / toolchain_version @@ -470,7 +469,7 @@ def _ensure_rust_toolchain(): from .xbuildenv import download_and_unpack_archive download_and_unpack_archive( - "http://pyodide-cache.s3-website-us-east-1.amazonaws.com/rustc/{toolchain_version}", + f"http://pyodide-cache.s3-website-us-east-1.amazonaws.com/rustc/{toolchain_version}", toolchain_path, ) result = subprocess.run( From 8256e72f8a5713c0914100ea308d8c1a332d2f75 Mon Sep 17 00:00:00 2001 From: Hood Chatham Date: Mon, 13 Jan 2025 22:19:35 +0100 Subject: [PATCH 04/21] Fix again --- pyodide_build/buildpkg.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pyodide_build/buildpkg.py b/pyodide_build/buildpkg.py index 06059638..855d3043 100755 --- a/pyodide_build/buildpkg.py +++ b/pyodide_build/buildpkg.py @@ -469,8 +469,8 @@ def _ensure_rust_toolchain(): from .xbuildenv import download_and_unpack_archive download_and_unpack_archive( - f"http://pyodide-cache.s3-website-us-east-1.amazonaws.com/rustc/{toolchain_version}", - toolchain_path, + f"http://pyodide-cache.s3-website-us-east-1.amazonaws.com/rustc/{toolchain_version}.tar.bz2", + toolchain_path.parent, ) result = subprocess.run( ["rustup", "toolchain", "link", toolchain_version, toolchain_path], check=False From 5e46696511ba3c4c3edd25f7440d34226d95720a Mon Sep 17 00:00:00 2001 From: Hood Chatham Date: Mon, 13 Jan 2025 22:45:14 +0100 Subject: [PATCH 05/21] Only download rust toolchain once --- pyodide_build/buildall.py | 29 ++++++++++++++- pyodide_build/buildpkg.py | 21 ----------- pyodide_build/common.py | 46 +++++++++++++++++++++++- pyodide_build/tests/test_xbuildenv.py | 15 ++++---- pyodide_build/xbuildenv.py | 52 +++------------------------ 5 files changed, 83 insertions(+), 80 deletions(-) diff --git a/pyodide_build/buildall.py b/pyodide_build/buildall.py index a739c050..b1f0f248 100755 --- a/pyodide_build/buildall.py +++ b/pyodide_build/buildall.py @@ -30,9 +30,11 @@ from rich.table import Table from pyodide_build import build_env, recipe -from pyodide_build.build_env import BuildArgs +from pyodide_build.build_env import BuildArgs, get_pyodide_root from pyodide_build.buildpkg import needs_rebuild from pyodide_build.common import ( + download_and_unpack_archive, + exit_with_stdio, extract_wheel_metadata_file, find_matching_wheels, find_missing_executables, @@ -645,6 +647,25 @@ def run(self, n_jobs: int, already_built: set[str]) -> None: self.build_queue.put((job_priority(dependent), dependent)) +def _ensure_rust_toolchain(): + pyodide_root = get_pyodide_root() + toolchain_version = "emscripten_2025-01-13_052ba16" + toolchain_path = pyodide_root / ".rust-toolchain" / toolchain_version + if toolchain_path.exists(): + return + download_and_unpack_archive( + f"http://pyodide-cache.s3-website-us-east-1.amazonaws.com/rustc/{toolchain_version}.tar.bz2", + toolchain_path.parent, + "rust toolchain", + ) + result = subprocess.run( + ["rustup", "toolchain", "link", toolchain_version, toolchain_path], check=False + ) + if result.returncode != 0: + logger.error("ERROR: rustup toolchain install failed") + exit_with_stdio(result) + + def build_from_graph( pkg_map: dict[str, BasePackage], build_args: BuildArgs, @@ -686,6 +707,12 @@ def build_from_graph( for pkg_name in needs_build: pkg_map[pkg_name].unbuilt_host_dependencies.difference_update(already_built) + needs_rust = any( + pkg_map[pkg_name].meta.is_rust_package() for pkg_name in needs_rebuild + ) + if needs_rust: + _ensure_rust_toolchain() + if already_built: logger.info( "The following packages are already built: [bold]%s[/bold]", diff --git a/pyodide_build/buildpkg.py b/pyodide_build/buildpkg.py index 855d3043..9bf1a4d4 100755 --- a/pyodide_build/buildpkg.py +++ b/pyodide_build/buildpkg.py @@ -460,26 +460,6 @@ def _get_helper_vars(self) -> dict[str, str]: } -def _ensure_rust_toolchain(): - pyodide_root = get_pyodide_root() - toolchain_version = "emscripten_2025-01-13_052ba16" - toolchain_path = pyodide_root / ".rust-toolchain" / toolchain_version - if toolchain_path.exists(): - return - from .xbuildenv import download_and_unpack_archive - - download_and_unpack_archive( - f"http://pyodide-cache.s3-website-us-east-1.amazonaws.com/rustc/{toolchain_version}.tar.bz2", - toolchain_path.parent, - ) - result = subprocess.run( - ["rustup", "toolchain", "link", toolchain_version, toolchain_path], check=False - ) - if result.returncode != 0: - logger.error("ERROR: rustup toolchain install failed") - exit_with_stdio(result) - - class RecipeBuilderPackage(RecipeBuilder): """ Recipe builder for python packages. @@ -487,7 +467,6 @@ class RecipeBuilderPackage(RecipeBuilder): def _build_package(self, bash_runner: BashRunnerWithSharedEnvironment) -> None: if self.recipe.is_rust_package(): - _ensure_rust_toolchain() bash_runner.run( RUST_BUILD_PRELUDE, script_name="rust build prelude", diff --git a/pyodide_build/common.py b/pyodide_build/common.py index 2f930704..c30c0e25 100644 --- a/pyodide_build/common.py +++ b/pyodide_build/common.py @@ -10,13 +10,15 @@ import sys import textwrap import tomllib +import warnings import zipfile from collections import deque from collections.abc import Generator, Iterable, Iterator, Mapping from contextlib import contextmanager from pathlib import Path -from tempfile import TemporaryDirectory +from tempfile import NamedTemporaryFile, TemporaryDirectory from typing import Any, NoReturn +from urllib.request import urlopen from zipfile import ZipFile from packaging.tags import Tag @@ -447,3 +449,45 @@ def to_bool(value: str) -> bool: Convert a string to a boolean value. Useful for parsing environment variables. """ return value.lower() not in {"", "0", "false", "no", "off"} + + +def download_and_unpack_archive(url: str, path: Path, descr: str) -> None: + """ + Download the cross-build environment from the given URL and extract it to the given path. + + Parameters + ---------- + url + URL to download the cross-build environment from. + path + Path to extract the cross-build environment to. + If the path already exists, raise an error. + """ + logger.info("Downloading %s from %s", descr, url) + + if path.exists(): + raise FileExistsError(f"Path {path} already exists") + + try: + resp = urlopen(url) + data = resp.read() + except Exception as e: + raise ValueError(f"Failed to download {descr} from {url}") from e + + # FIXME: requests makes a verbose output (see: https://github.com/pyodide/pyodide/issues/4810) + # r = requests.get(url) + + # if r.status_code != 200: + # raise ValueError( + # f"Failed to download cross-build environment from {url} (status code: {r.status_code})" + # ) + + with NamedTemporaryFile(suffix=".tar") as f: + f_path = Path(f.name) + f_path.write_bytes(data) + with warnings.catch_warnings(): + # Python 3.12-3.13 emits a DeprecationWarning when using shutil.unpack_archive without a filter, + # but filter doesn't work well for zip files, so we suppress the warning until we find a better solution. + # https://github.com/python/cpython/issues/112760 + warnings.simplefilter("ignore") + shutil.unpack_archive(str(f_path), path) diff --git a/pyodide_build/tests/test_xbuildenv.py b/pyodide_build/tests/test_xbuildenv.py index 3cb5934e..4faeb675 100644 --- a/pyodide_build/tests/test_xbuildenv.py +++ b/pyodide_build/tests/test_xbuildenv.py @@ -2,6 +2,7 @@ import pytest +from pyodide_build.common import download_and_unpack_archive from pyodide_build.xbuildenv import CrossBuildEnvManager, _url_to_version @@ -91,24 +92,20 @@ def test_current_version(self, tmp_path): assert manager.current_version == "0.25.0" def test_download(self, tmp_path, dummy_xbuildenv_url): - manager = CrossBuildEnvManager(tmp_path) - download_path = tmp_path / "test" - manager._download(dummy_xbuildenv_url, download_path) + download_and_unpack_archive(dummy_xbuildenv_url, download_path, "") assert download_path.exists() assert (download_path / "xbuildenv").exists() assert (download_path / "xbuildenv" / "pyodide-root").exists() def test_download_path_exists(self, tmp_path): - manager = CrossBuildEnvManager(tmp_path) - download_path = tmp_path / "test" download_path.mkdir() with pytest.raises(FileExistsError, match="Path .* already exists"): - manager._download( - "https://example.com/xbuildenv-0.25.0.tar.bz2", download_path + download_and_unpack_archive( + "https://example.com/xbuildenv-0.25.0.tar.bz2", download_path, "" ) def test_find_latest_version(self, tmp_path, fake_xbuildenv_releases_compatible): @@ -224,7 +221,7 @@ def test_install_cross_build_packages( manager = CrossBuildEnvManager(tmp_path) download_path = tmp_path / "test" - manager._download(dummy_xbuildenv_url, download_path) + download_and_unpack_archive(dummy_xbuildenv_url, download_path, "") xbuildenv_root = download_path / "xbuildenv" xbuildenv_pyodide_root = xbuildenv_root / "pyodide-root" @@ -248,7 +245,7 @@ def test_create_package_index(self, tmp_path, dummy_xbuildenv_url): manager = CrossBuildEnvManager(tmp_path) download_path = tmp_path / "test" - manager._download(dummy_xbuildenv_url, download_path) + download_and_unpack_archive(dummy_xbuildenv_url, download_path, "") xbuildenv_root = download_path / "xbuildenv" xbuildenv_pyodide_root = xbuildenv_root / "pyodide-root" diff --git a/pyodide_build/xbuildenv.py b/pyodide_build/xbuildenv.py index 038bc029..43a85435 100644 --- a/pyodide_build/xbuildenv.py +++ b/pyodide_build/xbuildenv.py @@ -1,14 +1,12 @@ import json import shutil import subprocess -import warnings from pathlib import Path -from tempfile import NamedTemporaryFile -from urllib.request import urlopen from pyodide_lock import PyodideLockSpec from pyodide_build import build_env +from pyodide_build.common import download_and_unpack_archive from pyodide_build.create_package_index import create_package_index from pyodide_build.logger import logger from pyodide_build.xbuildenv_releases import ( @@ -21,50 +19,6 @@ PYTHON_VERSION_MARKER_FILE = ".build-python-version" -def download_and_unpack_archive(url: str, path: Path) -> None: - """ - Download the cross-build environment from the given URL and extract it to the given path. - - Parameters - ---------- - url - URL to download the cross-build environment from. - path - Path to extract the cross-build environment to. - If the path already exists, raise an error. - """ - logger.info("Downloading Pyodide cross-build environment from %s", url) - - if path.exists(): - raise FileExistsError(f"Path {path} already exists") - - try: - resp = urlopen(url) - data = resp.read() - except Exception as e: - raise ValueError( - f"Failed to download cross-build environment from {url}" - ) from e - - # FIXME: requests makes a verbose output (see: https://github.com/pyodide/pyodide/issues/4810) - # r = requests.get(url) - - # if r.status_code != 200: - # raise ValueError( - # f"Failed to download cross-build environment from {url} (status code: {r.status_code})" - # ) - - with NamedTemporaryFile(suffix=".tar") as f: - f_path = Path(f.name) - f_path.write_bytes(data) - with warnings.catch_warnings(): - # Python 3.12-3.13 emits a DeprecationWarning when using shutil.unpack_archive without a filter, - # but filter doesn't work well for zip files, so we suppress the warning until we find a better solution. - # https://github.com/python/cpython/issues/112760 - warnings.simplefilter("ignore") - shutil.unpack_archive(str(f_path), path) - - class CrossBuildEnvManager: """ Manager for the cross-build environment. @@ -238,7 +192,9 @@ def install( download_path, ) else: - download_and_unpack_archive(download_url, download_path) + download_and_unpack_archive( + download_url, download_path, "Pyodide cross-build environment" + ) try: # there is an redundant directory "xbuildenv" inside the xbuildenv archive From adda8a5be20ff5342277b7c82281571c1f51e269 Mon Sep 17 00:00:00 2001 From: Hood Chatham Date: Mon, 13 Jan 2025 23:38:06 +0100 Subject: [PATCH 06/21] Fix --- pyodide_build/buildall.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyodide_build/buildall.py b/pyodide_build/buildall.py index b1f0f248..6509a529 100755 --- a/pyodide_build/buildall.py +++ b/pyodide_build/buildall.py @@ -708,7 +708,7 @@ def build_from_graph( pkg_map[pkg_name].unbuilt_host_dependencies.difference_update(already_built) needs_rust = any( - pkg_map[pkg_name].meta.is_rust_package() for pkg_name in needs_rebuild + pkg_map[pkg_name].meta.is_rust_package() for pkg_name in needs_build ) if needs_rust: _ensure_rust_toolchain() From b33d1c9960caba367af0e5699a4192e7bf1621b5 Mon Sep 17 00:00:00 2001 From: Hood Chatham Date: Tue, 14 Jan 2025 14:22:59 +0100 Subject: [PATCH 07/21] Always run rustup toolchain link --- pyodide_build/buildall.py | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/pyodide_build/buildall.py b/pyodide_build/buildall.py index 6509a529..defe6ff6 100755 --- a/pyodide_build/buildall.py +++ b/pyodide_build/buildall.py @@ -651,13 +651,12 @@ def _ensure_rust_toolchain(): pyodide_root = get_pyodide_root() toolchain_version = "emscripten_2025-01-13_052ba16" toolchain_path = pyodide_root / ".rust-toolchain" / toolchain_version - if toolchain_path.exists(): - return - download_and_unpack_archive( - f"http://pyodide-cache.s3-website-us-east-1.amazonaws.com/rustc/{toolchain_version}.tar.bz2", - toolchain_path.parent, - "rust toolchain", - ) + if not toolchain_path.exists(): + download_and_unpack_archive( + f"http://pyodide-cache.s3-website-us-east-1.amazonaws.com/rustc/{toolchain_version}.tar.bz2", + toolchain_path.parent, + "rust toolchain", + ) result = subprocess.run( ["rustup", "toolchain", "link", toolchain_version, toolchain_path], check=False ) From f2d72e71a1440cefb775fe39b506ce27798ac59a Mon Sep 17 00:00:00 2001 From: Hood Chatham Date: Tue, 14 Jan 2025 14:23:15 +0100 Subject: [PATCH 08/21] Add wasm-sjlj suffix to wasm-eh libs --- pyodide_build/pywasmcross.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/pyodide_build/pywasmcross.py b/pyodide_build/pywasmcross.py index e3c54e68..e6b016e9 100755 --- a/pyodide_build/pywasmcross.py +++ b/pyodide_build/pywasmcross.py @@ -118,6 +118,9 @@ def replay_genargs_handle_dashl(arg: str, used_libs: set[str]) -> str | None: if arg == "-lgfortran": return None + if arg in ["-lfreetype", "-lpng"]: + arg += "-wasm-sjlj" + # WASM link doesn't like libraries being included twice # skip second one if arg in used_libs: From 3c3dc793f50e25c374ef142509120bb293f9f50f Mon Sep 17 00:00:00 2001 From: Hood Chatham Date: Tue, 14 Jan 2025 19:21:39 +0100 Subject: [PATCH 09/21] Update Emscripten toolchain version --- pyodide_build/buildall.py | 2 +- pyodide_build/config.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pyodide_build/buildall.py b/pyodide_build/buildall.py index defe6ff6..c2db5902 100755 --- a/pyodide_build/buildall.py +++ b/pyodide_build/buildall.py @@ -649,7 +649,7 @@ def run(self, n_jobs: int, already_built: set[str]) -> None: def _ensure_rust_toolchain(): pyodide_root = get_pyodide_root() - toolchain_version = "emscripten_2025-01-13_052ba16" + toolchain_version = "emscripten_2025-01-13_724fd8dedf1" toolchain_path = pyodide_root / ".rust-toolchain" / toolchain_version if not toolchain_path.exists(): download_and_unpack_archive( diff --git a/pyodide_build/config.py b/pyodide_build/config.py index 126d8558..919f97d7 100644 --- a/pyodide_build/config.py +++ b/pyodide_build/config.py @@ -207,7 +207,7 @@ def to_env(self) -> dict[str, str]: "rustflags": "-C link-arg=-sSIDE_MODULE=2 -C link-arg=-sWASM_BIGINT -Z link-native-libraries=no", "cargo_build_target": "wasm32-unknown-emscripten", "cargo_target_wasm32_unknown_emscripten_linker": "emcc", - "rust_toolchain": "emscripten_2025-01-13_052ba16", + "rust_toolchain": "emscripten_2025-01-13_724fd8dedf1", # Other configuration "pyodide_jobs": "1", "skip_emscripten_version_check": "0", From 663e78e73516a14a3060b3a5b6f8e216e6323b45 Mon Sep 17 00:00:00 2001 From: Hood Chatham Date: Wed, 15 Jan 2025 12:32:43 +0100 Subject: [PATCH 10/21] Remove duplication of toolchain name --- pyodide_build/buildall.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyodide_build/buildall.py b/pyodide_build/buildall.py index dd070778..d7822025 100755 --- a/pyodide_build/buildall.py +++ b/pyodide_build/buildall.py @@ -650,8 +650,8 @@ def run(self, n_jobs: int, already_built: set[str]) -> None: def _ensure_rust_toolchain(): + toolchain_version = build_env.get_build_flag("RUST_TOOLCHAIN") pyodide_root = get_pyodide_root() - toolchain_version = "emscripten_2025-01-13_724fd8dedf1" toolchain_path = pyodide_root / ".rust-toolchain" / toolchain_version if not toolchain_path.exists(): download_and_unpack_archive( From 529a5835e040c73cdcbd8ce1c0eb377657d020cc Mon Sep 17 00:00:00 2001 From: Hood Chatham Date: Wed, 15 Jan 2025 12:36:19 +0100 Subject: [PATCH 11/21] Pass recipe ldflags through library rewriting logic as well --- pyodide_build/pywasmcross.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/pyodide_build/pywasmcross.py b/pyodide_build/pywasmcross.py index e6b016e9..a6ec1705 100755 --- a/pyodide_build/pywasmcross.py +++ b/pyodide_build/pywasmcross.py @@ -581,7 +581,10 @@ def handle_command_generate_args( # noqa: C901 # Better to fail at compile or link time. if is_link_cmd(line): new_args.append("-Wl,--fatal-warnings") - new_args.extend(build_args.ldflags.split()) + for arg in build_args.ldflags.split(): + if arg.startswith("-l"): + arg = replay_genargs_handle_dashl(arg, used_libs) + new_args.append(arg) new_args.extend(get_export_flags(line, build_args.exports)) if "-c" in line: From a63c7b929d285934cecb24c48e9164c7884c19e2 Mon Sep 17 00:00:00 2001 From: Hood Chatham Date: Wed, 15 Jan 2025 12:38:58 +0100 Subject: [PATCH 12/21] Add ignore for too many branches lint --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index b8b8fd0e..5cc29d69 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -133,7 +133,7 @@ lint.select = [ lint.logger-objects = ["pyodide_build.logger.logger"] -lint.ignore = ["E402", "E501", "E731", "E741", "PERF401", "PLW2901", "UP038"] +lint.ignore = ["E402", "E501", "E731", "E741", "PERF401", "PLW2901", "UP038", "PLR0912"] # line-length = 219 # E501: Recommended goal is 88 to match black target-version = "py312" From b50d1c13fc270190a20e76fb1170271215b1a70d Mon Sep 17 00:00:00 2001 From: Hood Chatham Date: Wed, 15 Jan 2025 20:52:43 +0100 Subject: [PATCH 13/21] Only install Emscripten target from url --- pyodide_build/buildall.py | 49 +++++++++++++++++++++++++++++---------- pyodide_build/common.py | 4 ++-- 2 files changed, 39 insertions(+), 14 deletions(-) diff --git a/pyodide_build/buildall.py b/pyodide_build/buildall.py index d7822025..5dc6f222 100755 --- a/pyodide_build/buildall.py +++ b/pyodide_build/buildall.py @@ -649,22 +649,47 @@ def run(self, n_jobs: int, already_built: set[str]) -> None: self.build_queue.put((job_priority(dependent), dependent)) -def _ensure_rust_toolchain(): - toolchain_version = build_env.get_build_flag("RUST_TOOLCHAIN") - pyodide_root = get_pyodide_root() - toolchain_path = pyodide_root / ".rust-toolchain" / toolchain_version - if not toolchain_path.exists(): - download_and_unpack_archive( - f"http://pyodide-cache.s3-website-us-east-1.amazonaws.com/rustc/{toolchain_version}.tar.bz2", - toolchain_path.parent, - "rust toolchain", - ) +def _run(cmd, *args, check=False, **kwargs): result = subprocess.run( - ["rustup", "toolchain", "link", toolchain_version, toolchain_path], check=False + cmd, + *args, + **kwargs, + check=check ) if result.returncode != 0: - logger.error("ERROR: rustup toolchain install failed") + logger.error("ERROR: command failed %s", " ".join(cmd)) exit_with_stdio(result) + return result + + +def _ensure_rust_toolchain(): + rust_toolchain = build_env.get_build_flag("RUST_TOOLCHAIN") + _run(["rustup", "toolchain", "install", rust_toolchain]) + _run(["rustup", "default", rust_toolchain]) + + url = f"http://pyodide-cache.s3-website-us-east-1.amazonaws.com/rustc-emscripten-target/{rust_toolchain}.tar.bz2" + if not url: + # Install target with rustup target add + _run([ + "rustup", + "target", + "add", + "wasm32-unknown-emscripten", + "--toolchain", + rust_toolchain, + ]) + return + + # Install target from url + result = _run(["rustup", "which", "--toolchain", rust_toolchain, "rustc"], capture_output=True, text=True) + toolchain_root = Path(result.stdout).parents[1] + rustlib = toolchain_root / "lib/rustlib" + install_token = rustlib / "wasm32-unknown-emscripten_install-url.txt" + if install_token.exists() and install_token.read_text() == url: + return + shutil.rmtree(rustlib / "wasm32-unknown-emscripten", ignore_errors=True) + download_and_unpack_archive(url, rustlib, "wasm32-unknown-emscripten target", exists_ok=True) + install_token.write_text(url) def build_from_graph( diff --git a/pyodide_build/common.py b/pyodide_build/common.py index c30c0e25..735786a3 100644 --- a/pyodide_build/common.py +++ b/pyodide_build/common.py @@ -451,7 +451,7 @@ def to_bool(value: str) -> bool: return value.lower() not in {"", "0", "false", "no", "off"} -def download_and_unpack_archive(url: str, path: Path, descr: str) -> None: +def download_and_unpack_archive(url: str, path: Path, descr: str, *, exists_ok: boolean = False) -> None: """ Download the cross-build environment from the given URL and extract it to the given path. @@ -465,7 +465,7 @@ def download_and_unpack_archive(url: str, path: Path, descr: str) -> None: """ logger.info("Downloading %s from %s", descr, url) - if path.exists(): + if not exists_ok and path.exists(): raise FileExistsError(f"Path {path} already exists") try: From 3b1734bd5388a133f8699c12c0bbea54054e00e7 Mon Sep 17 00:00:00 2001 From: Hood Chatham Date: Wed, 15 Jan 2025 21:01:08 +0100 Subject: [PATCH 14/21] Fix syntax error --- pyodide_build/common.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyodide_build/common.py b/pyodide_build/common.py index 735786a3..c35392fc 100644 --- a/pyodide_build/common.py +++ b/pyodide_build/common.py @@ -451,7 +451,7 @@ def to_bool(value: str) -> bool: return value.lower() not in {"", "0", "false", "no", "off"} -def download_and_unpack_archive(url: str, path: Path, descr: str, *, exists_ok: boolean = False) -> None: +def download_and_unpack_archive(url: str, path: Path, descr: str, *, exists_ok: bool = False) -> None: """ Download the cross-build environment from the given URL and extract it to the given path. From c93aab1ef68f9b3b9d58a18622f49fc0a35035b4 Mon Sep 17 00:00:00 2001 From: Hood Chatham Date: Wed, 15 Jan 2025 21:01:41 +0100 Subject: [PATCH 15/21] Move target url to config variable --- pyodide_build/buildall.py | 2 +- pyodide_build/config.py | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/pyodide_build/buildall.py b/pyodide_build/buildall.py index 5dc6f222..5adb52f5 100755 --- a/pyodide_build/buildall.py +++ b/pyodide_build/buildall.py @@ -667,7 +667,7 @@ def _ensure_rust_toolchain(): _run(["rustup", "toolchain", "install", rust_toolchain]) _run(["rustup", "default", rust_toolchain]) - url = f"http://pyodide-cache.s3-website-us-east-1.amazonaws.com/rustc-emscripten-target/{rust_toolchain}.tar.bz2" + url = build_env.get_build_flag("RUST_EMSCRIPTEN_TARGET_URL") if not url: # Install target with rustup target add _run([ diff --git a/pyodide_build/config.py b/pyodide_build/config.py index 919f97d7..42450c7b 100644 --- a/pyodide_build/config.py +++ b/pyodide_build/config.py @@ -160,6 +160,7 @@ def to_env(self) -> dict[str, str]: "cpythoninstall": "CPYTHONINSTALL", "rustflags": "RUSTFLAGS", "rust_toolchain": "RUST_TOOLCHAIN", + "rust_emscripten_target_url": "RUST_EMSCRIPTEN_TARGET_URL", "cflags": "SIDE_MODULE_CFLAGS", "cxxflags": "SIDE_MODULE_CXXFLAGS", "ldflags": "SIDE_MODULE_LDFLAGS", @@ -190,6 +191,7 @@ def to_env(self) -> dict[str, str]: "cxxflags", "ldflags", "rust_toolchain", + "rust_emscripten_target_url", "meson_cross_file", "skip_emscripten_version_check", "build_dependency_index_url", @@ -208,6 +210,7 @@ def to_env(self) -> dict[str, str]: "cargo_build_target": "wasm32-unknown-emscripten", "cargo_target_wasm32_unknown_emscripten_linker": "emcc", "rust_toolchain": "emscripten_2025-01-13_724fd8dedf1", + "rust_emscripten_target_url": "", # Other configuration "pyodide_jobs": "1", "skip_emscripten_version_check": "0", From 036626dec34b3277698f4cd8f7fc4bf72ec05bfc Mon Sep 17 00:00:00 2001 From: Hood Chatham Date: Wed, 15 Jan 2025 21:02:56 +0100 Subject: [PATCH 16/21] Set default rust_toolchain to nightly-2025-01-15 --- pyodide_build/config.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyodide_build/config.py b/pyodide_build/config.py index 42450c7b..9ab2f192 100644 --- a/pyodide_build/config.py +++ b/pyodide_build/config.py @@ -209,7 +209,7 @@ def to_env(self) -> dict[str, str]: "rustflags": "-C link-arg=-sSIDE_MODULE=2 -C link-arg=-sWASM_BIGINT -Z link-native-libraries=no", "cargo_build_target": "wasm32-unknown-emscripten", "cargo_target_wasm32_unknown_emscripten_linker": "emcc", - "rust_toolchain": "emscripten_2025-01-13_724fd8dedf1", + "rust_toolchain": "nightly-2025-01-15", "rust_emscripten_target_url": "", # Other configuration "pyodide_jobs": "1", From 7bbdde23e23fd9c0f619c271635101e74e385124 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Wed, 15 Jan 2025 20:03:07 +0000 Subject: [PATCH 17/21] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- pyodide_build/buildall.py | 37 ++++++++++++++++++++----------------- pyodide_build/common.py | 4 +++- 2 files changed, 23 insertions(+), 18 deletions(-) diff --git a/pyodide_build/buildall.py b/pyodide_build/buildall.py index 5adb52f5..7db2e89f 100755 --- a/pyodide_build/buildall.py +++ b/pyodide_build/buildall.py @@ -30,7 +30,7 @@ from rich.table import Table from pyodide_build import build_env, recipe -from pyodide_build.build_env import BuildArgs, get_pyodide_root +from pyodide_build.build_env import BuildArgs from pyodide_build.buildpkg import needs_rebuild from pyodide_build.common import ( download_and_unpack_archive, @@ -650,12 +650,7 @@ def run(self, n_jobs: int, already_built: set[str]) -> None: def _run(cmd, *args, check=False, **kwargs): - result = subprocess.run( - cmd, - *args, - **kwargs, - check=check - ) + result = subprocess.run(cmd, *args, **kwargs, check=check) if result.returncode != 0: logger.error("ERROR: command failed %s", " ".join(cmd)) exit_with_stdio(result) @@ -670,25 +665,33 @@ def _ensure_rust_toolchain(): url = build_env.get_build_flag("RUST_EMSCRIPTEN_TARGET_URL") if not url: # Install target with rustup target add - _run([ - "rustup", - "target", - "add", - "wasm32-unknown-emscripten", - "--toolchain", - rust_toolchain, - ]) + _run( + [ + "rustup", + "target", + "add", + "wasm32-unknown-emscripten", + "--toolchain", + rust_toolchain, + ] + ) return # Install target from url - result = _run(["rustup", "which", "--toolchain", rust_toolchain, "rustc"], capture_output=True, text=True) + result = _run( + ["rustup", "which", "--toolchain", rust_toolchain, "rustc"], + capture_output=True, + text=True, + ) toolchain_root = Path(result.stdout).parents[1] rustlib = toolchain_root / "lib/rustlib" install_token = rustlib / "wasm32-unknown-emscripten_install-url.txt" if install_token.exists() and install_token.read_text() == url: return shutil.rmtree(rustlib / "wasm32-unknown-emscripten", ignore_errors=True) - download_and_unpack_archive(url, rustlib, "wasm32-unknown-emscripten target", exists_ok=True) + download_and_unpack_archive( + url, rustlib, "wasm32-unknown-emscripten target", exists_ok=True + ) install_token.write_text(url) diff --git a/pyodide_build/common.py b/pyodide_build/common.py index c35392fc..6f02c68d 100644 --- a/pyodide_build/common.py +++ b/pyodide_build/common.py @@ -451,7 +451,9 @@ def to_bool(value: str) -> bool: return value.lower() not in {"", "0", "false", "no", "off"} -def download_and_unpack_archive(url: str, path: Path, descr: str, *, exists_ok: bool = False) -> None: +def download_and_unpack_archive( + url: str, path: Path, descr: str, *, exists_ok: bool = False +) -> None: """ Download the cross-build environment from the given URL and extract it to the given path. From 114e477f2d9262877f82abb1dcda8cfa60d18d95 Mon Sep 17 00:00:00 2001 From: Hood Chatham Date: Wed, 15 Jan 2025 21:13:36 +0100 Subject: [PATCH 18/21] Only change pywasmcross behavior for new abi --- pyodide_build/pypabuild.py | 1 + pyodide_build/pywasmcross.py | 10 ++++++---- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/pyodide_build/pypabuild.py b/pyodide_build/pypabuild.py index c72574ea..2f541a2b 100644 --- a/pyodide_build/pypabuild.py +++ b/pyodide_build/pypabuild.py @@ -280,6 +280,7 @@ def get_build_env( args["orig__name__"] = __name__ args["pythoninclude"] = get_build_flag("PYTHONINCLUDE") args["PATH"] = env["PATH"] + args["abi"] = get_build_flag("PYODIDE_ABI_VERSION") pywasmcross_env = json.dumps(args) # Store into environment variable and to disk. In most cases we will diff --git a/pyodide_build/pywasmcross.py b/pyodide_build/pywasmcross.py index a6ec1705..4e8aedaf 100755 --- a/pyodide_build/pywasmcross.py +++ b/pyodide_build/pywasmcross.py @@ -77,6 +77,7 @@ class CrossCompileArgs(NamedTuple): target_install_dir: str = "" # The path to the target Python installation pythoninclude: str = "" # path to the cross-compiled Python include directory exports: Literal["whole_archive", "requested", "pyinit"] | list[str] = "pyinit" + abi: str = "" def is_link_cmd(line: list[str]) -> bool: @@ -93,7 +94,7 @@ def is_link_cmd(line: list[str]) -> bool: return False -def replay_genargs_handle_dashl(arg: str, used_libs: set[str]) -> str | None: +def replay_genargs_handle_dashl(arg: str, used_libs: set[str], abi: str) -> str | None: """ Figure out how to replace a `-lsomelib` argument. @@ -118,7 +119,7 @@ def replay_genargs_handle_dashl(arg: str, used_libs: set[str]) -> str | None: if arg == "-lgfortran": return None - if arg in ["-lfreetype", "-lpng"]: + if abi > "2025" and arg in ["-lfreetype", "-lpng"]: arg += "-wasm-sjlj" # WASM link doesn't like libraries being included twice @@ -558,7 +559,7 @@ def handle_command_generate_args( # noqa: C901 continue if arg.startswith("-l"): - result = replay_genargs_handle_dashl(arg, used_libs) + result = replay_genargs_handle_dashl(arg, used_libs, build_args.abi) elif arg.startswith("-I"): result = replay_genargs_handle_dashI(arg, build_args.target_install_dir) elif arg.startswith("-Wl"): @@ -583,7 +584,7 @@ def handle_command_generate_args( # noqa: C901 new_args.append("-Wl,--fatal-warnings") for arg in build_args.ldflags.split(): if arg.startswith("-l"): - arg = replay_genargs_handle_dashl(arg, used_libs) + arg = replay_genargs_handle_dashl(arg, used_libs, build_args.abi) new_args.append(arg) new_args.extend(get_export_flags(line, build_args.exports)) @@ -644,6 +645,7 @@ def compiler_main(): target_install_dir=PYWASMCROSS_ARGS["target_install_dir"], pythoninclude=PYWASMCROSS_ARGS["pythoninclude"], exports=PYWASMCROSS_ARGS["exports"], + abi=PYWASMCROSS_ARGS["abi"], ) basename = Path(sys.argv[0]).name args = list(sys.argv) From 194c4630b61964ba661a1af3cc79daaf470abef5 Mon Sep 17 00:00:00 2001 From: Hood Chatham Date: Fri, 31 Jan 2025 16:14:49 +0100 Subject: [PATCH 19/21] Don't append None to new_args --- pyodide_build/pywasmcross.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/pyodide_build/pywasmcross.py b/pyodide_build/pywasmcross.py index 4e8aedaf..36a4487f 100755 --- a/pyodide_build/pywasmcross.py +++ b/pyodide_build/pywasmcross.py @@ -585,7 +585,8 @@ def handle_command_generate_args( # noqa: C901 for arg in build_args.ldflags.split(): if arg.startswith("-l"): arg = replay_genargs_handle_dashl(arg, used_libs, build_args.abi) - new_args.append(arg) + if arg: + new_args.append(arg) new_args.extend(get_export_flags(line, build_args.exports)) if "-c" in line: From ba33a1c4fc342cbe4582120a4726d2fbb0885b8f Mon Sep 17 00:00:00 2001 From: Hood Chatham Date: Thu, 27 Feb 2025 08:51:11 +0100 Subject: [PATCH 20/21] Don't adjust flags from recipes --- pyodide_build/pywasmcross.py | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/pyodide_build/pywasmcross.py b/pyodide_build/pywasmcross.py index 36a4487f..67bccc25 100755 --- a/pyodide_build/pywasmcross.py +++ b/pyodide_build/pywasmcross.py @@ -582,11 +582,7 @@ def handle_command_generate_args( # noqa: C901 # Better to fail at compile or link time. if is_link_cmd(line): new_args.append("-Wl,--fatal-warnings") - for arg in build_args.ldflags.split(): - if arg.startswith("-l"): - arg = replay_genargs_handle_dashl(arg, used_libs, build_args.abi) - if arg: - new_args.append(arg) + new_args.extend(build_args.ldflags.split()) new_args.extend(get_export_flags(line, build_args.exports)) if "-c" in line: From 6fe58829b5338ce678fcbe63a7d19028194e6656 Mon Sep 17 00:00:00 2001 From: Hood Chatham Date: Thu, 27 Feb 2025 09:02:41 +0100 Subject: [PATCH 21/21] Add comments --- pyodide_build/pywasmcross.py | 6 ++++++ pyodide_build/recipe/graph_builder.py | 6 +++++- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/pyodide_build/pywasmcross.py b/pyodide_build/pywasmcross.py index 67bccc25..40003e18 100755 --- a/pyodide_build/pywasmcross.py +++ b/pyodide_build/pywasmcross.py @@ -77,6 +77,8 @@ class CrossCompileArgs(NamedTuple): target_install_dir: str = "" # The path to the target Python installation pythoninclude: str = "" # path to the cross-compiled Python include directory exports: Literal["whole_archive", "requested", "pyinit"] | list[str] = "pyinit" + # Pyodide abi, e.g., 2025_0 + # Sometimes we have to inject compile flags only for certain abis. abi: str = "" @@ -119,6 +121,10 @@ def replay_genargs_handle_dashl(arg: str, used_libs: set[str], abi: str) -> str if arg == "-lgfortran": return None + # Some Emscripten libraries that use setjmp/longjmp. + # The Emscripten linker should automatically know to use these variants so + # this shouldn't be necessary. + # This suffix will need to change soon to `-legacysjlj`. if abi > "2025" and arg in ["-lfreetype", "-lpng"]: arg += "-wasm-sjlj" diff --git a/pyodide_build/recipe/graph_builder.py b/pyodide_build/recipe/graph_builder.py index 42001816..b408dd08 100755 --- a/pyodide_build/recipe/graph_builder.py +++ b/pyodide_build/recipe/graph_builder.py @@ -729,12 +729,16 @@ def _ensure_rust_toolchain(): ) return - # Install target from url + # Now we are going to delete the normal wasm32-unknown-emscripten sysroot + # and replace it with our wasm-eh version. + # We place the "install_token" to indicate that our custom sysroot has been + # installed and which URL we got it from. result = _run( ["rustup", "which", "--toolchain", rust_toolchain, "rustc"], capture_output=True, text=True, ) + toolchain_root = Path(result.stdout).parents[1] rustlib = toolchain_root / "lib/rustlib" install_token = rustlib / "wasm32-unknown-emscripten_install-url.txt"