pyemscripten_2025_0#

By default, all builds of the Pyodide runtime with Python 3.13 will use the pyemscripten_2025_0 platform.

Note

Prior to PEP 783, the platform was referenced as pyodide_2025_0.

Platform Specification#

CPython and Emscripten Version#

  • CPython: 3.13

  • Emscripten: 4.0.9

Unwinding ABIs#

C++ libraries are built with WebAssembly exception handling (-fwasm-exceptions) and WebAssembly-based setjmp/longjmp (-sSUPPORT_LONGJMP=wasm). To enable exceptions and setjmp/longjmp, -fwasm-exceptions must be passed at compile time and link time.

The flag -Z emscripten-wasm-eh must be passed to Rust. It is necessary to use a Rust nightly after January 15th, 2025, when the -Z emscripten-wasm-eh flag was added. All -Z flags are gated nightly-only. The -Z emscripten-wasm-eh flag will never be stabilized but eventually it will switch to being on by default and then be removed. See the Rust Major Change Proposal for more information.

The Rust sysroot#

Rust ships with an Emscripten sysroot built without the -Z emscripten-wasm-eh flag so using the standard sysroot will lead to linker errors due to mismatched unwinding ABIs.

Some crates can be built with

RUSTFLAGS=-Zemscripten-wasm-eh cargo build -Zbuild-std

If the crate uses panic=abort it may be possible to build with

cargo build -Z build-std=std,panic_abort -Z build-std-features=panic_immediate_abort

but it won’t work with any crates that use cargo vendor and there seem to be various bugs. Also, when building a large number of packages -Zbuild-std inefficiently rebuilds the standard library for each crate.

If not building with -Zbuild-std, it is possible to get a compatible sysroot from pyodide/rust-emscripten-wasm-eh-sysroot. This is only distributed for Rust nightly-2025-02-01. To use a different Rust nightly, it is possible to clone the pyodide/rust-emscripten-wasm-eh-sysroot repository and follow the instructions in the README to build a compatible sysroot. To install the Emscripten sysroot use:

rustup toolchain install nightly-2025-02-01
TOOLCHAIN_ROOT=$(rustup run nightly-2025-02-01 rustc --print sysroot)
RUSTLIB=$TOOLCHAIN_ROOT/lib/rustlib
wget https://github.com/pyodide/rust-emscripten-wasm-eh-sysroot/releases/download/emcc-4.0.9_nightly-2025-02-01/emcc-4.0.9_nightly-2025-02-01.tar.bz2
tar -xf emcc-4.0.9_nightly-2025-02-01.tar.bz2 --directory=$RUSTLIB

Note that this is all necessary even if the crate uses -Cpanic=abort because the Rust standard library is not built with -Cpanic=abort and so there will be linker errors due to pulling in symbols from the standard library that use the wrong unwinding ABI.

Rust Toolchain#

A Rust nightly after January 15th, 2025 is required, in order to use the -Z emscripten-wasm-eh flag. The recommended toolchain is nightly-2025-02-01 if using the prebuilt sysroot from pyodide/rust-emscripten-wasm-eh-sysroot.

Runtime Library Loading Path#

There is full support for RPATH. The dynamic loader will only load dependencies that are properly specified on the RPATH, just being in /lib/python3.13/site-packages/wheel_name.libs is not sufficient.

Libraries Linked to the Main Binary#

The following libraries are statically linked to the binary:

  • libegl.js

  • libeventloop.js

  • libGL

  • libhtml5_webgl.js

  • libhtml5.js

  • liblz4

  • libsdl.js

  • libwebgl.js

  • libwebsocket.js

  • bzip2

  • zlib

All of these come from Emscripten ports and the versions of these libraries are determined by the version of Emscripten we build with. Any symbols from these static libraries may be used by shared libraries.

Changes from pyemscripten_2024_0#

Emscripten version#

Emscripten was upgraded from 3.1.58 to 4.0.9.

WASM_BIGINT is now the default#

In pyemscripten_2024_0, -sWASM_BIGINT had to be passed explicitly. Since Emscripten 4.0.0, it is the default. No action is required — explicitly passing the flag still works but is no longer necessary.

Unwinding ABI changed from JavaScript exceptions to WebAssembly exceptions#

pyemscripten_2024_0 used JavaScript-based exception handling (-fexceptions). pyemscripten_2025_0 uses WebAssembly exception handling (-fwasm-exceptions and -sSUPPORT_LONGJMP=wasm).

For Rust, the -Z emscripten-wasm-eh flag must now be passed to rustc, and a compatible sysroot is required (see The Rust sysroot above).

RPATH is now fully supported#

In pyemscripten_2024_0, RPATH was not supported and the dynamic loader used a patched heuristic based on wheel_name.libs. In pyemscripten_2025_0, there is full RPATH support and dependencies must be properly specified on the RPATH.