11# Python WebAssembly (WASM) build
22
33** WASI support is [ tier 2] ( https://peps.python.org/pep-0011/#tier-2 ) .**
4- ** Emscripten is NOT officially supported as of Python 3.13 .**
4+ ** Emscripten support is [ tier 3 ] ( https://peps.python.org/pep-0011/#tier-3 ) .**
55
66This directory contains configuration and helpers to facilitate cross
77compilation of CPython to WebAssembly (WASM). Python supports Emscripten
@@ -27,154 +27,57 @@ It comes with a reduced and preloaded stdlib without tests and threading
2727support. The `` Emscripten/node `` target has threading enabled and can
2828access the file system directly.
2929
30- Cross compiling to the wasm32-emscripten platform needs the
31- [ Emscripten] ( https://emscripten.org/ ) SDK and a build Python interpreter.
32- Emscripten 3.1.19 or newer are recommended. All commands below are relative
33- to a repository checkout.
30+ To cross compile to the `` wasm32-emscripten `` platform you need
31+ [ the Emscripten compiler toolchain] ( https://emscripten.org/ ) ,
32+ a Python interpreter, and an installation of Node version 18 or newer. Emscripten
33+ version 3.1.42 or newer is recommended. All commands below are relative to a checkout
34+ of the Python repository.
3435
35- #### Toolchain
36+ #### Install [ the Emscripten compiler toolchain ] ( https://emscripten.org/docs/getting_started/downloads.html )
3637
37- ##### Container image
38-
39- Christian Heimes maintains a container image with Emscripten SDK, Python
40- build dependencies, WASI-SDK, wasmtime, and several additional tools.
41-
42- From within your local CPython repo clone, run one of the following commands:
43-
44- ```
45- # Fedora, RHEL, CentOS
46- podman run --rm -ti -v $(pwd):/python-wasm/cpython:Z -w /python-wasm/cpython quay.io/tiran/cpythonbuild:emsdk3
47-
48- # other
49- docker run --rm -ti -v $(pwd):/python-wasm/cpython -w /python-wasm/cpython quay.io/tiran/cpythonbuild:emsdk3
38+ You can install the Emscripten toolchain as follows:
39+ ``` shell
40+ git clone https://github.com/emscripten-core/emsdk.git --depth 1
41+ ./emsdk/emsdk install latest
42+ ./emsdk/emsdk activate latest
5043```
51-
52- ##### Manually
53-
54- ###### Install [ Emscripten SDK] ( https://emscripten.org/docs/getting_started/downloads.html )
55-
56- ** NOTE** : Follow the on-screen instructions how to add the SDK to `` PATH `` .
57-
44+ To add the Emscripten compiler to your path:
5845``` shell
59- git clone https://github.com/emscripten-core/emsdk.git /opt/emsdk
60- /opt/emsdk/emsdk install latest
61- /opt/emsdk/emsdk activate latest
46+ source ./emsdk/emsdk_env.sh
6247```
48+ This adds ` emcc ` and ` emconfigure ` to your path.
6349
64- ###### Optionally: enable ccache for EMSDK
50+ ##### Optionally: enable ccache for EMSDK
6551
6652The `` EM_COMPILER_WRAPPER `` must be set after the EMSDK environment is
6753sourced. Otherwise the source script removes the environment variable.
6854
69- ```
70- . /opt/emsdk/emsdk_env.sh
71- EM_COMPILER_WRAPPER=ccache
72- ```
73-
74- ###### Optionally: pre-build and cache static libraries
75-
76- Emscripten SDK provides static builds of core libraries without PIC
77- (position-independent code). Python builds with `` dlopen `` support require
78- PIC. To populate the build cache, run:
79-
8055``` shell
81- . /opt/emsdk/emsdk_env.sh
82- embuilder build zlib bzip2 MINIMAL_PIC
83- embuilder --pic build zlib bzip2 MINIMAL_PIC
56+ export EM_COMPILER_WRAPPER=ccache
8457```
8558
86-
8759### Compile and build Python interpreter
8860
89- From within the container, run the following command:
90-
91- ``` shell
92- ./Tools/wasm/wasm_build.py build
93- ```
94-
95- The command is roughly equivalent to:
96-
97- ``` shell
98- mkdir -p builddir/build
99- pushd builddir/build
100- ../../configure -C
101- make -j$( nproc)
102- popd
103- ```
104-
105- #### Cross-compile to wasm32-emscripten for browser
106-
107- ``` shell
108- ./Tools/wasm/wasm_build.py emscripten-browser
109- ```
110-
111- The command is roughly equivalent to:
112-
61+ You can use ` python Tools/wasm/emscripten ` to compile and build targetting
62+ Emscripten. You can do everything at once with:
11363``` shell
114- mkdir -p builddir/emscripten-browser
115- pushd builddir/emscripten-browser
116-
117- CONFIG_SITE=../../Tools/wasm/config.site-wasm32-emscripten \
118- emconfigure ../../configure -C \
119- --host=wasm32-unknown-emscripten \
120- --build=$( ../../config.guess) \
121- --with-emscripten-target=browser \
122- --with-build-python=$( pwd) /../build/python
123-
124- emmake make -j$( nproc)
125- popd
64+ python Tools/wasm/emscripten build
12665```
127-
128- Serve ` python.html ` with a local webserver and open the file in a browser.
129- Python comes with a minimal web server script that sets necessary HTTP
130- headers like COOP, COEP, and mimetypes. Run the script outside the container
131- and from the root of the CPython checkout.
132-
66+ or you can break it out into four separate steps:
13367``` shell
134- ./Tools/wasm/wasm_webserver.py
68+ python Tools/wasm/emscripten configure-build-python
69+ python Tools/wasm/emscripten make-build-python
70+ python Tools/wasm/emscripten configure-host
71+ python Tools/wasm/emscripten make-host
13572```
136-
137- and open http://localhost:8000/builddir/emscripten-browser/python.html . This
138- directory structure enables the * C/C++ DevTools Support (DWARF)* to load C
139- and header files with debug builds.
140-
141-
142- #### Cross compile to wasm32-emscripten for node
143-
73+ Extra arguments to the configure steps are passed along to configure. For
74+ instance, to do a debug build, you can use:
14475``` shell
145- ./ Tools/wasm/wasm_build.py emscripten-node-dl
76+ python Tools/wasm/emscripten build --with-py-debug
14677```
14778
148- The command is roughly equivalent to:
149-
150- ``` shell
151- mkdir -p builddir/emscripten-node-dl
152- pushd builddir/emscripten-node-dl
153-
154- CONFIG_SITE=../../Tools/wasm/config.site-wasm32-emscripten \
155- emconfigure ../../configure -C \
156- --host=wasm32-unknown-emscripten \
157- --build=$( ../../config.guess) \
158- --with-emscripten-target=node \
159- --enable-wasm-dynamic-linking \
160- --with-build-python=$( pwd) /../build/python
161-
162- emmake make -j$( nproc)
163- popd
164- ```
165-
166- ``` shell
167- node --experimental-wasm-threads --experimental-wasm-bulk-memory --experimental-wasm-bigint builddir/emscripten-node-dl/python.js
168- ```
169-
170- (`` --experimental-wasm-bigint `` is not needed with recent NodeJS versions)
171-
17279### Limitations and issues
17380
174- Emscripten before 3.1.8 has known bugs that can cause memory corruption and
175- resource leaks. 3.1.8 contains several fixes for bugs in date and time
176- functions.
177-
17881#### Network stack
17982
18083- Python's socket module does not work with Emscripten's emulated POSIX
@@ -241,8 +144,6 @@ functions.
241144 [ gh-90548 ] ( https://github.com/python/cpython/issues/90548 ) .
242145- Python's object allocator `` obmalloc `` is disabled by default.
243146- `` ensurepip `` is not available.
244- - Some `` ctypes `` features like `` c_longlong `` and `` c_longdouble `` may need
245- NodeJS option `` --experimental-wasm-bigint `` .
246147
247148#### In the browser
248149
@@ -263,15 +164,6 @@ Node builds use ``NODERAWFS``.
263164- Node RawFS allows direct access to the host file system without need to
264165 perform `` FS.mount() `` call.
265166
266- ### wasm64-emscripten
267-
268- - wasm64 requires recent NodeJS and `` --experimental-wasm-memory64 `` .
269- - `` EM_JS `` functions must return `` BigInt() `` .
270- - `` Py_BuildValue() `` format strings must match size of types. Confusing 32
271- and 64 bits types leads to memory corruption, see
272- [ gh-95876 ] ( https://github.com/python/cpython/issues/95876 ) and
273- [ gh-95878 ] ( https://github.com/python/cpython/issues/95878 ) .
274-
275167### Hosting Python WASM builds
276168
277169The simple REPL terminal uses SharedArrayBuffer. For security reasons
0 commit comments