The PyEmscripten Platform#
What is the PyEmscripten Platform?#
The PyEmscripten platform defines a binary interface for an Emscripten application. If an Emscripten application and an Emscripten shared library are both built to target this platform, then the application will be able to load and run the shared library.
To build a shared library that is compatible with a given version of Pyodide, it is necessary to identify which PyEmscripten platform that version of Pyodide uses and follow the corresponding shared library build instructions. This allows wheels to be built for Pyodide that will load and run correctly.
The Emscripten compiler makes no ABI stability guarantees between versions, and several linker flags can adjust the ABI. Therefore, Python packages built for Emscripten must match the ABI-sensitive compiler and linker flags used to build the interpreter to avoid load-time or run-time errors.
To balance ABI stability needs of package maintainers with flexibility to adopt
new platform features and bug fixes, Pyodide adopts a new PyEmscripten platform
for each feature release of Python. The platform tags take the form
pyemscripten_${YEAR}_${PATCH}_wasm32 (e.g., pyemscripten_2026_0_wasm32 for
Python 3.14).
Each PyEmscripten platform specifies:
the version of the Emscripten compiler to be used,
what libraries are statically linked to the application,
the stack unwinding ABI to be used,
how the loader handles dependency lookup, and
various additional compile and linker flags
The PyEmscripten platform definition does not include anything about Python and in particular it is agnostic to the Python version it is intended to be used with. However, for clarity we indicate in the platform documentation which Python version we plan to use each platform with.
The PyEmscripten platform is specified by PEP 783, and wheels using this
tag are supported on PyPI. Prior to PEP 783, it was called the Pyodide
platform instead of the PyEmscripten platform (and used the form
pyodide_${YEAR}_${PATCH}_wasm32).
Platform Versions#
pyemscripten_2026_0 (Python 3.14)
pyemscripten_2025_0 (Python 3.13)
pyemscripten_2024_0 (Python 3.12)
For background on why specific flags were chosen, see ABI-sensitive flags.
General#
Building for the Emscripten target#
To build C/C++ projects, use the Emscripten compiler toolchain emcc.
To build Rust projects, use rustc --target wasm32-unknown-emscripten or
cargo build --target wasm32-unknown-emscripten. When building, emcc must be
on the path or linking will fail.
Static Libraries Linked to the Main Binary#
Many libraries cannot be dynamically linked on the Emscripten platform, most frequently because they contain JavaScript code. If they are to be made available for packages to use, they must be statically linked to the interpreter. There are also a few libraries that are needed for a Python builtin module. As a part of the platform definition, we document which versions of which libraries are linked to the main binary.
Other Library Dependencies#
Other library dependencies should either be statically linked to the extension
module or built as a shared library and vendored into the wheel in a .libs
directory. Like on native platforms, the RPATH of the dependent extension module
should also be set as appropriate to ensure that the dependency is resolved
correctly.
No pthreads support#
-pthread must not be used at compile or link time. If -pthread is used, the
resulting libraries will not load.
Controlling the Set of Exported Symbols#
All symbols that form part of a binary module’s interface must be exported. It is desirable to produce the minimal list of exported symbols to keep download size and runtime to a minimum. Not exporting symbols also reduces chances of symbol collisions.
Linking a shared libraries with -sSIDE_MODULE=1 will pass -whole-archive to
wasm-ld and so force inclusion of all object files and all symbols. Linking
with -sSIDE_MODULE=2 will only include symbols that are explicitly listed with
-sEXPORTED_FUNCTIONS=<export list>. The name of each symbol in the list must
be prefixed with an underscore. For the smallest result, it is recommended to
link with:
-sSIDE_MODULE=2 -sEXPORTED_FUNCTIONS=["_PyInit_MyCModule1", "_PyInit_MyCModule2]