diff --git a/cibuildwheel/platforms/pyodide.py b/cibuildwheel/platforms/pyodide.py index 15612a85a..e0560b4a0 100644 --- a/cibuildwheel/platforms/pyodide.py +++ b/cibuildwheel/platforms/pyodide.py @@ -94,21 +94,28 @@ def ensure_node(major_version: str) -> Path: return path -def install_emscripten(tmp: Path, version: str) -> Path: - url = f"https://github.com/emscripten-core/emsdk/archive/refs/tags/{version}.zip" - installation_path = CIBW_CACHE_PATH / f"emsdk-{version}" - emsdk_path = installation_path / f"emsdk-{version}/emsdk" - emcc_path = installation_path / f"emsdk-{version}/upstream/emscripten/emcc" - with FileLock(f"{installation_path}.lock"): - if installation_path.exists(): +def install_emscripten( + env: dict[str, str], version: str, xbuildenv_cache_path: Path, pyodide_version: str +) -> Path: + """Install Emscripten via pyodide-build, which also applies Pyodide-specific patches.""" + emcc_path = ( + xbuildenv_cache_path / pyodide_version / "emsdk" / "upstream" / "emscripten" / "emcc" + ) + with FileLock(CIBW_CACHE_PATH / "emscripten.lock"): + if emcc_path.exists(): return emcc_path - emsdk_zip = tmp / "emsdk.zip" - download(url, emsdk_zip) - installation_path.mkdir() - extract_zip(emsdk_zip, installation_path) - call(emsdk_path, "install", version) - call(emsdk_path, "activate", version) - + call( + "pyodide", + "xbuildenv", + "install-emscripten", + "--version", + version, + "--path", + str(xbuildenv_cache_path), + env=env, + cwd=CIBW_CACHE_PATH, + ) + assert emcc_path.exists() return emcc_path @@ -180,12 +187,8 @@ def validate_pyodide_build_version( raise errors.FatalError(msg) -def install_xbuildenv(env: dict[str, str], pyodide_build_version: str, pyodide_version: str) -> str: +def install_xbuildenv(env: dict[str, str], xbuildenv_cache_path: Path, pyodide_version: str) -> str: """Install a particular Pyodide xbuildenv version and set a path to the Pyodide root.""" - # Since pyodide-build was unvendored from Pyodide v0.27.0, the versions of - # pyodide-build are uncoupled from the versions of Pyodide. So, we specify - # both the pyodide-build version and the Pyodide version in the temp path. - xbuildenv_cache_path = CIBW_CACHE_PATH / f"pyodide-build-{pyodide_build_version}" pyodide_root = xbuildenv_cache_path / pyodide_version / "xbuildenv" / "pyodide-root" with FileLock(CIBW_CACHE_PATH / "xbuildenv.lock"): @@ -303,15 +306,19 @@ def setup_python( pyodide_build_version=pyodide_build_version, ) + xbuildenv_cache_path = CIBW_CACHE_PATH / f"pyodide-build-{pyodide_build_version}" + + log.step(f"Installing Pyodide xbuildenv version: {pyodide_version} ...") + env["PYODIDE_ROOT"] = install_xbuildenv(env, xbuildenv_cache_path, pyodide_version) + emscripten_version = xbuildenv_info["emscripten"] - log.step(f"Installing Emscripten version: {emscripten_version} ...") - emcc_path = install_emscripten(tmp, emscripten_version) + log.step( + f"Installing Emscripten {emscripten_version} and applying Pyodide-specific patches ..." + ) + emcc_path = install_emscripten(env, emscripten_version, xbuildenv_cache_path, pyodide_version) env["PATH"] = os.pathsep.join([str(emcc_path.parent), env["PATH"]]) - log.step(f"Installing Pyodide xbuildenv version: {pyodide_version} ...") - env["PYODIDE_ROOT"] = install_xbuildenv(env, pyodide_build_version, pyodide_version) - return env