How pyodide-build Works#
This page explains how pyodide-build cross compiles normal Linux-compatible Python packages into wheels that can be used with Pyodide.
The build pipeline#
When you run pyodide build ., the following happens:
┌────────────────┐
│ pyodide-build │ CLI entry point
└───────┬────────┘
│
▼
┌────────────────┐
│ Environment │ Install cross-build environment (if needed)
│ setup │ Set up headers, env vars
└───────┬────────┘
│
▼
┌────────────────┐
│ pypa/build │ Standard PEP 517 build frontend
│ │ Invokes your build backend (setuptools, meson-python, etc.)
└───────┬────────┘
│ Build backend calls gcc, g++, cmake, meson, cargo...
▼
┌────────────────┐
│ pywasmcross │ Compiler wrapper — intercepts all tool calls
│ │ Redirects to Emscripten (emcc, em++, emar, etc.)
│ │ Filters incompatible flags, adds Wasm flags
└───────┬────────┘
│
▼
┌────────────────┐
│ Emscripten │ Compiles C/C++ → WebAssembly (.o, .a, .so)
│ (emcc/em++) │ Links as SIDE_MODULE
└───────┬────────┘
│
▼
┌────────────────┐
│ Wheel output │ .so files (Wasm) + Python files → .whl
│ │ Tagged: pyemscripten_YYYY_P_wasm32
└────────────────┘
The compiler wrapper#
The core of pyodide-build is a compiler wrapper that transparently redirects native compiler calls to Emscripten.
How it works#
When pyodide-build sets up the build environment, it adds overrides for gcc and other compiler toolchain tools to the beginning of the path.
Tool |
override |
|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
When the compiler wrapper is invoked:
Detects which tool it’s impersonating
Rewrites the command line for Emscripten
Filters out native flags that emcc cannot handle
Adds WebAssembly-specific flags
Executes the real Emscripten tool
When pyodide build runs:
Set compiler flags, paths, and environment variables
The
sysconfigmodule is patched to return target-platform values instead of host valuesPATHis modified so compiler wrappers take priority over native compilersEnvironment variables (
CMAKE_TOOLCHAIN_FILE,MESON_CROSS_FILE, etc.) are set
Build isolation#
By default, pyodide build uses pypa/build in isolated mode — just like python -m build. This means:
A temporary virtual environment is created
Build dependencies from
[build-system].requiresare installedThe build backend is invoked
The virtual environment is discarded
The --no-isolation flag skips this and uses the current environment, which is useful for complex builds where you need to manage dependencies yourself.
Further reading#
Emscripten documentation — the underlying compiler toolchain
PEP 517 — Python build system interface
PEP 783 — Emscripten Packaging
PEP 776 — Emscripten Support for Python