@@ -14,11 +14,11 @@ Abstract
1414========
1515
1616`Emscripten <https://emscripten.org/ >`__ is a complete open source compiler
17- toolchain which compiles C/C++ code into WebAssembly/JavaScript executables that
18- run in JavaScript runtimes including browsers and Node.js.
17+ toolchain. It compiles C/C++ code into WebAssembly/JavaScript executables,
18+ for use in JavaScript runtimes, including browsers and Node.js.
1919
2020This PEP formalizes the addition of Tier 3 for Emscripten support in Python 3.14
21- which `was approved by the steering council on October 25, 2024
21+ which `was approved by the Steering Council on October 25, 2024
2222<https://github.com/python/steering-council/issues/256> `__. The goal is to allow
2323Pyodide wheels to be uploaded to PyPI.
2424
@@ -65,7 +65,7 @@ Packaging Goals
65651. To describe Pyodide's packaging tooling
66662. To describe Pyodide's wheel abi to a similar level of detail as the manylinux
6767 PEPs
68- 3. To request that Pyodide wheels be allowed for upload to PyPI
68+ 3. For Pyodide wheels to be allowed for upload to PyPI
6969
7070
7171Emscripten Platform Information
@@ -79,11 +79,11 @@ Background on Emscripten
7979consists of a C and C++ compiler and linker based on LLVM, together with a
8080runtime based on a mildly patched musl libc.
8181
82- Emscripten is a POSIX-based platform. It uses the WebAssembly binary format,
83- specified here:
82+ Emscripten is a POSIX-based platform. It uses the ` WebAssembly binary format `_ ,
83+ and the ` WebAssembly dynamic linking section `_.
8484
85- * https://webassembly.github.io/spec/core/binary/index.html
86- * https://github.com/WebAssembly/tool-conventions/blob/main/DynamicLinking.md
85+ .. _ WebAssembly binary format : https://webassembly.github.io/spec/core/binary/index.html
86+ .. _ WebAssembly dynamic linking section : https://github.com/WebAssembly/tool-conventions/blob/main/DynamicLinking.md
8787
8888The ``emcc `` compiler is a wrapper around ``clang ``. The ``emcc `` linker is a
8989wrapper around ``wasm-ld `` (also part of the LLVM toolchain).
@@ -106,18 +106,20 @@ Emscripten executables can be linked with threading support, but it comes
106106with several limitations:
107107
108108* Enabling threading requires websites to be served with special security headers
109- that indicate acceptance of the possibility of ` Spectre < https://en.wikipedia.org/wiki/ Spectre_(security_vulnerability) >`__ -style information
109+ that indicate acceptance of the possibility of Spectre _-style information
110110 leakage. These headers are a usability hazard for users who are not intimately
111111 familiar with the web platform.
112112
113+ .. _Spectre : https://en.wikipedia.org/wiki/Spectre_(security_vulnerability)
114+
113115* If an executable is linked with both threading and a dynamic loader, Emscripten
114116 prints a warning that using dynamic loading and pthreads together is
115117 experimental. It may cause performance problems or crashes. These problems may
116118 require WebAssembly standards work to resolve.
117119
118120Because of these limitations, Pyodide standardizes a no-pthreads build of
119- Python. We will start with support for no- pthreads builds. If there is
120- sufficient demand, a pthreads build with no dynamic loader could be added later.
121+ Python. If there is sufficient demand, a pthreads build with no dynamic loader
122+ could be added later.
121123
122124Emscripten ABI Compatibility
123125----------------------------
@@ -141,20 +143,20 @@ ABI for each feature release of Python.
141143The Pyodide team also coordinates the ABI flags that Pyodide uses with the
142144Emscripten ABI that Rust supports in order to ensure that we have support for
143145the many popular Rust packages. Historically, most of the work for this has
144- been related to unwinding ABIs. See for instance `this Rust Major change
145- proposal <https://github.com/rust-lang/compiler-team/issues/801> `__.
146+ been related to unwinding ABIs. See for instance `this Rust Major Change
147+ Proposal <https://github.com/rust-lang/compiler-team/issues/801> `__.
146148
147149Development Tools
148150-----------------
149151
150152Emscripten development tools are equally well supported on Linux, Windows, and
151- macOS. Upstream tools:
153+ macOS. The upstream tools include :
152154
153- * The Emscripten Software Developer Kit (emsdk) which can be used to install the
154- Emscripten compiler toolchain (emcc).
155- * emcc is a C and C++ compiler, linker, and a sysroot with headers for the
156- system libraries. The system libraries themselves are generated on the fly
157- based on the ABI requested.
155+ * The Emscripten Software Developer Kit (:program: ` emsdk ` ) which can be used to
156+ install the Emscripten compiler toolchain (:program: ` emcc ` ).
157+ * :program: ` emcc ` is a C and C++ compiler, linker, and a sysroot with headers
158+ for the system libraries. The system libraries themselves are generated on
159+ the fly based on the ABI requested.
158160* Node.js can be used as an "emulator" to run Emscripten programs from the
159161 command line. This emulation behaves best on Linux with macOS as a runner up.
160162 Node.js is the most convenient way to test Emscripten programs.
@@ -170,7 +172,9 @@ Pyodide's tools:
170172* ``pyodide venv `` can make a virtual environment that runs in Pyodide.
171173* ``pytest-pyodide `` can test Python code against various JavaScript runtimes.
172174
173- cibuildwheel supports building wheels to target Emscripten using ``pyodide build ``.
175+ cibuildwheel __ supports building wheels to target Emscripten using ``pyodide build ``.
176+
177+ __ https://cibuildwheel.pypa.io/
174178
175179In the short term, Pyodide's packaging tooling will stay in the Pyodide
176180repository. It is an open question where Pyodide's packaging tooling should live
@@ -189,13 +193,13 @@ shut down the runtime on exit. It also includes an implementation for all of the
189193system calls, including the file system, the dynamic loader, and any logic to
190194expose additional functionality from the JavaScript runtime to C code.
191195
192- The ``.mjs `` file exports a single `` bootstrapEmscriptenExecutable() ` `
196+ The ``.mjs `` file exports a single :js:func: ` bootstrapEmscriptenExecutable() `
193197JavaScript function that bootstraps the runtime, calls the ``main() `` function,
194198and returns an API object that can be used to call C functions. Each time it is
195199called produces a complete and independent copy of the runtime with its own
196200separate address space.
197201
198- The `` bootstrapEmscriptenExecutable() ` ` takes a large number of runtime
202+ The :js:func: ` bootstrapEmscriptenExecutable() ` takes a large number of runtime
199203settings. `The full list is described in the Emscripten documentation here.
200204<https://emscripten.org/docs/api_reference/module.html#id3> `__ The most
201205important of these are as follows:
@@ -242,8 +246,8 @@ Emscripten file system. There are several possible approaches to this:
242246 uncompressed zip file allows the web server and client to apply better
243247 compression to the standard library itself. It also uses the more efficient
244248 native decompression algorithms of the browser rather than less efficient
245- WebAssembly decompression. The disadvantage of this is a higher memory
246- footprint and it breaks :py:mod: `inspect ` and various tests that do not expect the
249+ WebAssembly decompression. The disadvantages of this are a higher memory
250+ footprint and breaking :py:mod: `inspect ` & various tests that do not expect the
247251 standard library to be packaged in this way.
248252
249253* Put the standard library into an uncompressed tar archive and mount it into a
@@ -256,30 +260,30 @@ Pyodide uses the ``ZipImporter`` approach in every runtime. Python uses the
256260NODEFS approach when run with node and the ``ZipImporter `` approach for the web
257261example. We will continue with this approach.
258262
259- The ``ZipImporter `` provides a clean resolution for a bootstrapping problem: The
263+ The ``ZipImporter `` provides a clean resolution for a bootstrapping problem: the
260264Python runtime is capable of unpacking a wide variety of archive formats, but
261265the Python runtime is not ready to use until the standard library is already
262266available. Since ``zipimport.py `` is a frozen module, it avoids these problems.
263267All of the other approaches solve the bootstrapping problem by setting up the
264268standard library using JavaScript.
265269
266- Packages
267- ~~~~~~~~
270+ Third-party packages
271+ ~~~~~~~~~~~~~~~~~~~~
268272
269273It is also necessary to make any needed packages available in the Emscripten
270- file system. Currently Emscripten cpython has no support for packages. Pyodide
274+ file system. Currently Emscripten CPython has no support for packages. Pyodide
271275uses two different approaches for packages:
272276
273277* In the browser, Pyodide downloads and unpacks wheels into the MEMFS
274278 site-packages directory. It then preloads all dynamic libraries in the wheel.
275279 The work of downloading and installing all the packages is redone every time
276280 the runtime starts.
277281
278- * The Pyodide ``python `` cli entrypoint mounts all of the host file system as
282+ * The Pyodide ``python `` CLI entrypoint mounts all of the host file system as
279283 NODEFS directories before it bootstraps Python. This allows the normal virtual
280284 environment mechanism to work. Pyodide virtual environments contain a patched
281285 copy of pip and a custom ``pip.conf `` so that pip will install Pyodide wheels.
282- On startup the Pyodide ``python `` cli will preload all Emscripten dynamic
286+ On startup the Pyodide ``python `` CLI will preload all Emscripten dynamic
283287 libraries that are in the site-packages directory.
284288
285289
@@ -288,7 +292,7 @@ Console and Interactive Usage
288292
289293``stdin `` defaults to always returning ``EOF ``, while ``stdout `` and ``stderr ``
290294default to calling ``console.log `` and ``console.error `` respectively. It is
291- possible to pass handlers to `` bootstrapEmscriptenExecutable() ` ` to configure
295+ possible to pass handlers to :js:func: ` bootstrapEmscriptenExecutable() ` to configure
292296the standard streams, but no matter what the I/O devices have undesirable line
293297buffering behavior that forces a new line when flushed. To implement a well
294298behaved TTY in-browser, it is necessary to remove the default I/O devices and
@@ -394,7 +398,7 @@ exceptions. This ensures that any recoverable JavaScript error is caught before
394398it unwinds through any WebAssembly frames. All entrypoints to WebAssembly are
395399also wrapped with JavaScript try/catch blocks. Any exceptions caught there have
396400unwound WebAssembly frames and are thus considered to be fatal errors (though
397- there is a special case to handle `` exit() ` `). This requires foundational
401+ there is a special case to handle :func: ` ~sys. exit() `). This requires foundational
398402integration with the Python/JavaScript foreign function interface.
399403
400404When the Pyodide runtime catches a fatal exception, it introspects the error to
@@ -413,7 +417,7 @@ traceback.
413417
414418Because Emscripten Python currently has no JavaScript API and no foreign function
415419interface, the situation is much simpler. The Python Node.js runner wraps the call
416- to `` bootstrapEmscriptenExecutable() ` ` in a try/catch block. If an exception is
420+ to :js:func: ` bootstrapEmscriptenExecutable() ` in a try/catch block. If an exception is
417421caught, it displays the JavaScript exception and calls ``_Py_DumpTraceback() ``.
418422It then exits with code 1. We will stick with this approach until we add either
419423a JavaScript API or foreign function interface, which is out of scope for this PEP.
@@ -714,8 +718,8 @@ code duplication.
714718Eventually, we would like to upstream Pyodide's bootstrapping API. In the short
715719term, to keep things simple we will support no JavaScript API.
716720
717- FFI
718- ~~~
721+ JavaScript foreign function interface ( FFI)
722+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
719723
720724Because Emscripten supports POSIX, a significant number of tasks can be achieved
721725using the ``os `` module. However, many fundamental operations in JavaScript
0 commit comments