# 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](https://github.com/rust-lang/compiler-team/issues/801)
for more information.

(the-rust-sysroot)=

#### 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](https://github.com/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:

```sh
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](https://github.com/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](#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`.
