# Support WASM wheels on PyPI

**URL:** <https://discuss.python.org/t/support-wasm-wheels-on-pypi/21924>\
**Category:** Packaging\
**Created:** [December 14, 2022, 4:25pm UTC](https://discuss.python.org/t/support-wasm-wheels-on-pypi/21924 "2022-12-14T16:25:48Z")\
**Posts on this page:** 12\
**Page:** 1

<div class="post-metadata">

**Author:** ![antocuni](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/antocuni/32/35138_2.png) [@antocuni](https://discuss.python.org/u/antocuni)\
**Post date:** [December 14, 2022, 4:25pm UTC](https://discuss.python.org/t/support-wasm-wheels-on-pypi/21924/1 "2022-12-14T16:25:48Z")

</div>

Hello,  
this is a spin-off of a discussion which originated in the #WebAssembly category:

> [@Make WASM a 1st class platform in the Python ecosystem](https://discuss.python.org/t/make-wasm-a-1st-class-platform-in-the-python-ecosystem/21798/1):
>
> Hello from the Paris JuypterLite workshop. In the past three days many people who are involved at various levels in the Python/WASM ecosystem were in the same room: we had representatives from Pyodide, emscripten-forge, JupyterLite, PyScript, Basthon and other projects (sorry if I forgot any). Among the many interesting conversations that we had, we discussed one point which I think it’s good to share with the broader Python community: what can we do to make WASM a 1st class platform in t…

Among the other things in that thread we also talked about the possibility of publishing WASM wheels on PyPI. To quote myself:

> [@Make WASM a 1st class platform in the Python ecosystem](https://discuss.python.org/t/make-wasm-a-1st-class-platform-in-the-python-ecosystem/21798/1):
>
> 1. it should be easy for library authors to test their code on WASM: ideally,  
> they should be able to do something like `python-wasm -m pip install ...`,  
> `python-wasm -m pytest`, etc. The good news here is that both [Pyodide](https://pypi.org/project/pyodide-build/) and  
> emscripten-forge have written tools which go in this direction. Note that for many usages, it is not even required to run them in  
> the browser: it is totally possible to run and test the code inside node,  
> from the command line.
> 2. It should be easy to build and deploy packages. Ideally, it should be  
> possible to upload WASM-specific binaries to PyPI and conda-forge.
> 3. It should be easy to do the steps above in CI.
> 
> [cut]
> 
> I think that these points are extremenly important for the long term  
> sustainability of the effort: currently, pyodide and emscripten-forge maintain  
> a big set of patches to be able to build a selected set of packages to WASM,  
> but if we make it possible to easily test it on CI, I can imagine that as a  
> community we can start to send these patches upstream.

This seems to be technically possible: Pyodide is a Python/WASM distribution which compiles the core interpreter and a (big) set of extension modules. The extension modules are distributed in the form of wheels using their own CDN, and installed by their own tool called `micropip`.

There is another project doing something similar: emscripten-forge is a “conda-style” python distribution based on mamba, which compiles its own python and various extension modules.

Recently we tried to load an extension module compiled by/for emscripten-forge, repackage it as wheel and install/import it into pyodide: it “just worked”. IMHO this proves that the current technology behind WASM/emscripten/dynamic linking is mature enough that you can reliably build and distribute 3rd-party extension modules.

So, to put it more concretely:

1. does the packaging sub-community think it would be a good idea to support WASM wheels on PyPI?
2. what does it need to happen to make it so?

/cc @rth and @hoodmane (pyodide devs)

---

<div class="post-metadata">

**Author:** ![dholth](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/dholth/32/952_2.png) [@dholth](https://discuss.python.org/u/dholth)\
**Post date:** [December 14, 2022, 5:10pm UTC](https://discuss.python.org/t/support-wasm-wheels-on-pypi/21924/2 "2022-12-14T17:10:06Z")

</div>

That sounds interesting. They must have assigned reasonable abi / platform tags already?

How does WASM binary compatibility work? Is it any better than Linux ABI compatibility?

---

<div class="post-metadata">

**Author:** ![dustin](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/dustin/32/149_2.png) [@dustin](https://discuss.python.org/u/dustin)\
**Post date:** [December 14, 2022, 5:25pm UTC](https://discuss.python.org/t/support-wasm-wheels-on-pypi/21924/3 "2022-12-14T17:25:02Z")

</div>

> [@antocuni](#):
>
> does the packaging sub-community think it would be a good idea to support WASM wheels on PyPI?

In my opinion, yes!

> [@antocuni](#):
>
> what does it need to happen to make it so?

A well-specified PEP that describes the ABI/Platform tags for the wheels that @dholth mentioned.

---

<div class="post-metadata">

**Author:** ![konstin](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/konstin/32/20207_2.png) [@konstin](https://discuss.python.org/u/konstin)\
**Post date:** [December 14, 2022, 8:19pm UTC](https://discuss.python.org/t/support-wasm-wheels-on-pypi/21924/4 "2022-12-14T20:19:55Z")

</div>

I’ve implemented support for shipping rust binaries as wasm/wasi in [maturin](https://github.com/pyo3/maturin) when compiling with `maturin build --target wasm32-wasi`. Currently this is done by depending on [wasmtime-py](https://github.com/bytecodealliance/wasmtime-py) and a small launcher script, but i’d be really interest in getting support for first-class wasm wheels, both binaries and extension modules.

---

<div class="post-metadata">

**Author:** ![dholth](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/dholth/32/952_2.png) [@dholth](https://discuss.python.org/u/dholth)\
**Post date:** [December 14, 2022, 8:27pm UTC](https://discuss.python.org/t/support-wasm-wheels-on-pypi/21924/5 "2022-12-14T20:27:31Z")

</div>

@konstin this may need a new thread, but what are you doing with the rust binaries as wasm/wasi? Do they interact with a WASI or native CPython interpreter? Or are they run like standalone programs? If they’re simple data that the Python code pipes through wasmtime, they might not affect the wheel tags at all and could go into a none-any wheel.

---

<div class="post-metadata">

**Author:** ![konstin](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/konstin/32/20207_2.png) [@konstin](https://discuss.python.org/u/konstin)\
**Post date:** [December 14, 2022, 11:02pm UTC](https://discuss.python.org/t/support-wasm-wheels-on-pypi/21924/6 "2022-12-14T23:02:24Z")

</div>

They are just simple standalone scripts, essentially an abstraction over `wasmtime hello-world.wasm`. They do currently use none-any tags, but they depend on wasmtime which reduces platform support quite a bit. It’s more of technical demo if we can conveniently ship wasm wheels. I’d be super interested though into extending this into something that can actually interact with python code, e.g. could pyo3 or cffi target pyodide and maturin build hypothetical `py38-emscripten-wasm` wheels?

---

<div class="post-metadata">

**Author:** ![dholth](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/dholth/32/952_2.png) [@dholth](https://discuss.python.org/u/dholth)\
**Post date:** [December 15, 2022, 2:40am UTC](https://discuss.python.org/t/support-wasm-wheels-on-pypi/21924/7 "2022-12-15T02:40:52Z")

</div>

I suppose it would be possible to expose the [https://hpyproject.org/](https://hpyproject.org/) API to WASM, loading WASM extension modules into CPython’s from various architectures. Not sure if it would be worth the trouble.

---

<div class="post-metadata">

**Author:** ![rth](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/rth/32/7162_2.png) [@rth](https://discuss.python.org/u/rth)\
**Post date:** [December 19, 2022, 10:24am UTC](https://discuss.python.org/t/support-wasm-wheels-on-pypi/21924/8 "2022-12-19T10:24:23Z")

</div>

> could pyo3 or cffi target pyodide and maturin build hypothetical `py38-emscripten-wasm` wheels

emscripten/wasm32 wheels creation via Pyodide is already part of the [mathurin CI](https://github.com/PyO3/maturin/blob/4ba4bf1b9d2ee435003837a8cfe6aecb99242390/.github/workflows/test.yml#L245)

> WASM binary compatibility work? Is it any better than Linux ABI compatibility?

In the case of Emscripten, it’s both the build toolchain and the OS. There is no backward compatibility guarantee, so the plan so far in Pyodide is to fix the Emscripten version for a given Python version. We also agreed that this Emscripten version would be used both by Pyodide and emscripten-forge, so that the produced packages are compatible.

If you do fix the Emscripten version, it means you also fully control the runtime environment, which makes a lot of things easier compatibility-wise. One thing that needs to be specified is what libraries are linked into the interpreter and provided as part of Emscripten main module though.

There has been work on developing wheel auditing tool similar to auditwheel in [ryanking13/auditwheel-emscripten](https://github.com/ryanking13/auditwheel-emscripten) and there are plans for integration into [pypa/cibuildwheel#1002](https://github.com/pypa/cibuildwheel/issues/1002).

Anyway, the next steps are clear: we need to write a PEP.

---

<div class="post-metadata">

**Author:** ![konstin](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/konstin/32/20207_2.png) [@konstin](https://discuss.python.org/u/konstin)\
**Post date:** [December 19, 2022, 2:06pm UTC](https://discuss.python.org/t/support-wasm-wheels-on-pypi/21924/9 "2022-12-19T14:06:20Z")

</div>

> [@rth](#):
>
> emscripten/wasm32 wheels creation via Pyodide is already part of the [mathurin CI](https://github.com/PyO3/maturin/blob/4ba4bf1b9d2ee435003837a8cfe6aecb99242390/.github/workflows/test.yml#L245)

Oh that’s cool, totally missed that this is this far already. Do you know of any examples where this is used/where i could try this out as a user?

---

<div class="post-metadata">

**Author:** ![rth](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/rth/32/7162_2.png) [@rth](https://discuss.python.org/u/rth)\
**Post date:** [December 19, 2022, 2:32pm UTC](https://discuss.python.org/t/support-wasm-wheels-on-pypi/21924/10 "2022-12-19T14:32:50Z")

</div>

There are docs about it [here](https://pyodide.org/en/latest/development/new-packages.html#rust-pyo3-packages). As far as I know for now the only Python package with Rust extensions we build is cryptography (but that uses setuptools-rust). There was some work on building `tokenizers` with mathurin in [pyodide#2816](https://github.com/pyodide/pyodide/issues/2816). @hoodmane who worked on this, might know more.

---

<div class="post-metadata">

**Author:** ![hoodmane](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/hoodmane/32/4037_2.png) [@hoodmane](https://discuss.python.org/u/hoodmane)\
**Post date:** [December 19, 2022, 4:46pm UTC](https://discuss.python.org/t/support-wasm-wheels-on-pypi/21924/11 "2022-12-19T16:46:04Z")

</div>

In Pyodide we have two rust wheels `cryptography` and `bcrypt`. Rust packages with no C code generally seem to be significantly easier to build than normal C code. There is more work to be done here though: maturin has 23 test crates and they are only testing 2 of them against Pyodide. It would be better if we could enable more of those.

---

<div class="post-metadata">

**Author:** ![messense](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/messense/32/3532_2.png) [@messense](https://discuss.python.org/u/messense)\
**Post date:** [January 5, 2023, 7:01am UTC](https://discuss.python.org/t/support-wasm-wheels-on-pypi/21924/12 "2023-01-05T07:01:02Z")

</div>

pydantic-core is using it: [pydantic-core/ci.yml at d6e7890b36ef21cb28180a7f5b1479da2319012d · pydantic/pydantic-core · GitHub](https://github.com/pydantic/pydantic-core/blob/d6e7890b36ef21cb28180a7f5b1479da2319012d/.github/workflows/ci.yml#L225-L269)

Demo: [pydantic-core unit tests](https://githubproxy.samuelcolvin.workers.dev/pydantic/pydantic-core/blob/main/wasm-preview/index.html)
