Skip to content

Commit 0804d1b

Browse files
juntyrhoodmanealexcrichtonkleisauke
committed
Add wasm32-unknown-emscripten platform support document
Co-authored-by: Hood Chatham <[email protected]> Co-authored-by: Alex Crichton <[email protected]> Co-authored-by: Kleis Auke Wolthuizen <[email protected]>
1 parent fb20e4d commit 0804d1b

File tree

4 files changed

+172
-3
lines changed

4 files changed

+172
-3
lines changed

src/doc/rustc/src/SUMMARY.md

+1
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,7 @@
8484
- [wasm32-wasip1](platform-support/wasm32-wasip1.md)
8585
- [wasm32-wasip1-threads](platform-support/wasm32-wasip1-threads.md)
8686
- [wasm32-wasip2](platform-support/wasm32-wasip2.md)
87+
- [wasm32-unknown-emscripten](platform-support/wasm32-unknown-emscripten.md)
8788
- [wasm32-unknown-unknown](platform-support/wasm32-unknown-unknown.md)
8889
- [wasm64-unknown-unknown](platform-support/wasm64-unknown-unknown.md)
8990
- [\*-win7-windows-msvc](platform-support/win7-windows-msvc.md)

src/doc/rustc/src/platform-support.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -190,7 +190,7 @@ target | std | notes
190190
[`thumbv8m.base-none-eabi`](platform-support/thumbv8m.base-none-eabi.md) | * | Bare Armv8-M Baseline
191191
[`thumbv8m.main-none-eabi`](platform-support/thumbv8m.main-none-eabi.md) | * | Bare Armv8-M Mainline
192192
[`thumbv8m.main-none-eabihf`](platform-support/thumbv8m.main-none-eabi.md) | * | Bare Armv8-M Mainline, hardfloat
193-
`wasm32-unknown-emscripten` | ✓ | WebAssembly via Emscripten
193+
[`wasm32-unknown-emscripten`](platform-support/wasm32-unknown-emscripten.md) | ✓ | WebAssembly via Emscripten
194194
[`wasm32-unknown-unknown`](platform-support/wasm32-unknown-unknown.md) | ✓ | WebAssembly
195195
`wasm32-wasi` | ✓ | WebAssembly with WASI (undergoing a [rename to `wasm32-wasip1`][wasi-rename])
196196
[`wasm32-wasip1`](platform-support/wasm32-wasip1.md) | ✓ | WebAssembly with WASI
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,168 @@
1+
# `wasm32-unknown-emscripten`
2+
3+
**Tier: 2**
4+
5+
The `wasm32-unknown-emscripten` target is a WebAssembly compilation target which
6+
uses the [Emscripten](https://emscripten.org/) compiler toolchain. Emscripten is
7+
a C/C++ toolchain designed to make it as easy as possible to port C/C++ code
8+
written for Linux to run on the web or in other JavaScript runtimes such as Node.
9+
It thus provides POSIX-compatible (musl) `libc` and `libstd` implementations and
10+
many Linux APIs, access to the OpenGL and SDL APIs, and the ability to run arbitrary
11+
JavaScript code, all based on web APIs using JS glue code. With the
12+
`wasm32-unknown-emscripten` target, Rust code can interoperate with Emscripten's
13+
ecosystem, C/C++ and JS code, and web APIs.
14+
15+
One existing user of this target is the
16+
[`pyodide` project](https://pyodide.org/) which provides a Python runtime in
17+
WebAssembly using Emscripten and compiles Python extension modules written in Rust
18+
to the `wasm32-unknown-emscripten` target.
19+
20+
If you want to generate a standalone WebAssembly binary that does not require
21+
access to the web APIs or the Rust standard library, the
22+
[`wasm32-unknown-unknown`](./wasm32-unknown-unknown.md) target may be better
23+
suited for you. However, [`wasm32-unknown-unknown`](./wasm32-unknown-unknown.md)
24+
does not (easily) support interop with C/C++ code. Please refer to the
25+
[wasm-bindgen](https://crates.io/crates/wasm-bindgen) crate in case you want to
26+
interoperate with JavaScript with this target.
27+
28+
Like Emscripten, the WASI targets [`wasm32-wasip1`](./wasm32-wasip1.md) and
29+
[`wasm32-wasip2`](./wasm32-wasip2.md) also provide access to the host environment,
30+
support interop with C/C++ (and other languages), and support most of the Rust
31+
standard library. While the WASI targets are portable across different hosts
32+
(web and non-web), WASI has no standard way of accessing web APIs, whereas
33+
Emscripten has the ability to run arbitrary JS from WASM and access many web APIs.
34+
If you are only targeting the web and need to access web APIs, the
35+
`wasm32-unknown-emscripten` target may be preferable.
36+
37+
## Target maintainers
38+
39+
- Hood Chatham, https://github.com/hoodmane
40+
- Juniper Tyree, https://github.com/juntyr
41+
42+
## Requirements
43+
44+
This target is cross-compiled. The Emscripten compiler toolchain `emcc` must be
45+
installed to link WASM binaries for this target. You can install `emcc` using:
46+
47+
```sh
48+
git clone https://github.com/emscripten-core/emsdk.git --depth 1
49+
./emsdk/emsdk install 3.1.68
50+
./emsdk/emsdk activate 3.1.68
51+
source ./emsdk/emsdk_env.sh
52+
```
53+
54+
Please refer to <https://emscripten.org/docs/getting_started/downloads.html> for
55+
further details and instructions.
56+
57+
## Building the target
58+
59+
Building this target can be done by:
60+
61+
* Configure the `wasm32-unknown-emscripten` target to get built.
62+
* Ensure the `WebAssembly` target backend is not disabled in LLVM.
63+
64+
These are all controlled through `config.toml` options. It should be possible
65+
to build this target on any platform. A minimal example configuration would be:
66+
67+
```toml
68+
[llvm]
69+
targets = "WebAssembly"
70+
71+
[build]
72+
build-stage = 1
73+
target = ["wasm32-unknown-emscripten"]
74+
```
75+
76+
## Building Rust programs
77+
78+
Rust programs can be compiled by adding this target via rustup:
79+
80+
```sh
81+
$ rustup target add wasm32-unknown-emscripten
82+
```
83+
84+
and then compiling with the target:
85+
86+
```sh
87+
$ rustc foo.rs --target wasm32-unknown-emscripten
88+
$ file foo.wasm
89+
```
90+
91+
## Cross-compilation
92+
93+
This target can be cross-compiled from any host.
94+
95+
## Emscripten ABI Compatibility
96+
97+
The Emscripten compiler toolchain does not follow a semantic versioning scheme
98+
that clearly indicates when breaking changes to the ABI can be made. Additionally,
99+
Emscripten offers many different ABIs even for a single version of Emscripten
100+
depending on the linker flags used, e.g. `-fexceptions` and `-sWASM_BIGINT`. If
101+
the ABIs mismatch, your code may exhibit undefined behaviour.
102+
103+
To ensure that the ABIs of your Rust code, of the Rust standard library, and of
104+
other code compiled for Emscripten all match, you should rebuild the Rust standard
105+
library with your local Emscripten version and settings using:
106+
107+
```sh
108+
cargo +nightly -Zbuild-std build
109+
```
110+
111+
If you still want to use the pre-compiled `std` from rustup, you should ensure
112+
that your local Emscripten matches the version used by Rust and be careful about
113+
any `-C link-arg`s that you compiled your Rust code with.
114+
115+
## Testing
116+
117+
This target is not extensively tested in CI for the rust-lang/rust repository. It
118+
can be tested locally, for example, with:
119+
120+
```sh
121+
./x.py test --target wasm32-unknown-emscripten --skip src/tools/linkchecker
122+
```
123+
124+
To run these tests, both `emcc` and `node` need to be in your `$PATH`. You can
125+
install `node`, for example, using `nvm` by following the instructions at
126+
<https://github.com/nvm-sh/nvm#install--update-script>.
127+
128+
If you need to test WebAssembly compatibility *in general*, it is recommended
129+
to test the [`wasm32-wasip1`](./wasm32-wasip1.md) target instead.
130+
131+
## Conditionally compiling code
132+
133+
It's recommended to conditionally compile code for this target with:
134+
135+
```text
136+
#[cfg(target_os = "emscripten")]
137+
```
138+
139+
It may sometimes be necessary to conditionally compile code for WASM targets
140+
which do *not* use emscripten, which can be achieved with:
141+
142+
```text
143+
#[cfg(all(target_family = "wasm", not(target_os = "emscripten)))]
144+
```
145+
146+
## Enabled WebAssembly features
147+
148+
WebAssembly is an evolving standard which adds new features such as new
149+
instructions over time. This target's default set of supported WebAssembly
150+
features will additionally change over time. The `wasm32-unknown-emscripten` target
151+
inherits the default settings of LLVM which typically, but not necessarily, matches
152+
the default settings of Emscripten as well. At link time, `emcc` configures the
153+
linker to use Emscripten's settings.
154+
155+
Please refer to the [`wasm32-unknown-unknown`](./wasm32-unknown-unknown.md)
156+
target's documentation on which WebAssembly features Rust enables by default, how
157+
features can be disabled, and how Rust code can be conditionally compiled based on
158+
which features are enabled.
159+
160+
Note that Rust code compiled for `wasm32-unknown-emscripten` currently enables
161+
`-fexceptions` (JS exceptions) by default unless the Rust code is compiled with
162+
`-Cpanic=abort`. `-fwasm-exceptions` (WASM exceptions) is not yet currently supported,
163+
see <https://github.com/rust-lang/rust/issues/112195>.
164+
165+
Please refer to the [Emscripten ABI compatibility](#emscripten-abi-compatibility)
166+
section to ensure that the features that are enabled do not cause an ABI mismatch
167+
between your Rust code, the pre-compiled Rust standard library, and other code compiled
168+
for Emscripten.

src/doc/rustc/src/platform-support/wasm32-unknown-unknown.md

+2-2
Original file line numberDiff line numberDiff line change
@@ -46,8 +46,8 @@ This target currently has no equivalent in C/C++. There is no C/C++ toolchain
4646
for this target. While interop is theoretically possible it's recommended to
4747
instead use one of:
4848

49-
* `wasm32-unknown-emscripten` - for web-based use cases the Emscripten
50-
toolchain is typically chosen for running C/C++.
49+
* [`wasm32-unknown-emscripten`](./wasm32-unknown-emscripten.md) - for web-based
50+
use cases the Emscripten toolchain is typically chosen for running C/C++.
5151
* [`wasm32-wasip1`](./wasm32-wasip1.md) - the wasi-sdk toolchain is used to
5252
compile C/C++ on this target and can interop with Rust code. WASI works on
5353
the web so far as there's no blocker, but an implementation of WASI APIs

0 commit comments

Comments
 (0)