Skip to content

Commit e65a48e

Browse files
committed
Document WebAssembly target feature expectations
This commit is a result of the discussion on #128475 and incorporates parts of #109807 as well. This is all done as a new page of documentation for the `wasm32-unknown-unknown` target which previously did not exist. This new page goes into details about the preexisting target and additionally documents the expectations for WebAssembly features and code generation. The tl;dr is that LLVM will enable features over time after most engines have had support for awhile. Compiling without features requires `-Ctarget-cpu=mvp` to rustc plus `-Zbuild-std` to Cargo. Closes #109807 Closes #128475
1 parent e60ebb2 commit e65a48e

File tree

4 files changed

+169
-1
lines changed

4 files changed

+169
-1
lines changed

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.main-none-eabi`](platform-support/thumbv8m.main-none-eabi.md) | * | Bare Armv8-M Mainline
191191
[`thumbv8m.main-none-eabihf`](platform-support/thumbv8m.main-none-eabi.md) | * | Bare Armv8-M Mainline, hardfloat
192192
`wasm32-unknown-emscripten` | ✓ | WebAssembly via Emscripten
193-
`wasm32-unknown-unknown` | ✓ | WebAssembly
193+
[`wasm32-unknown-unknown`](platform-support/wasm32-unknown-unknown.md) | ✓ | WebAssembly
194194
`wasm32-wasi` | ✓ | WebAssembly with WASI (undergoing a [rename to `wasm32-wasip1`][wasi-rename])
195195
[`wasm32-wasip1`](platform-support/wasm32-wasip1.md) | ✓ | WebAssembly with WASI
196196
[`wasm32-wasip1-threads`](platform-support/wasm32-wasip1-threads.md) | ✓ | WebAssembly with WASI Preview 1 and threads
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,154 @@
1+
# `wasm32-unknown-unknown`
2+
3+
**Tier: 2**
4+
5+
The `wasm32-unknown-unknown` target is a WebAssembly compilation target which
6+
does not import any functions from the host for the standard library. This is
7+
the "minimal" WebAssembly in the sense of making the fewest assumptions about
8+
the host environment. This target is often used when compiling to the web or
9+
JavaScript environments as there is not standard for what functions can be
10+
imported on the web. This target can also be useful for creating minimal or
11+
bare-bones WebAssembly binaries.
12+
13+
The `wasm32-unknown-unknown` target has support for the Rust standard library
14+
but many parts of the standard library do not work and return errors. For
15+
example `println!` does nothing, `std::fs` always return errors, and
16+
`std::thread::spawn` will panic. There is no means by which this can be
17+
overridden. For a WebAssembly target that more fully supports the standard
18+
library see the [`wasm32-wasip1`](./wasm32-wasip1.md) or
19+
[`wasm32-wasip2`](./wasm32-wasip2.md) targets.
20+
21+
The `wasm32-unknown-unknown` target has full support for the `core` and `alloc`
22+
crates. It additionally supports the `HashMap` type in the `std` crate, although
23+
hash maps are not randomized like they are on other platforms.
24+
25+
One existing user of this target (please feel free to edit and expand this list
26+
too) is the [`wasm-bindgen` project](https://github.com/rustwasm/wasm-bindgen)
27+
which facilitates Rust code interoperating with JavaScript code. Note, though,
28+
that not all uses of `wasm32-unknown-unknown` are using JavaScript and the web.
29+
30+
## Target maintainers
31+
32+
When this target was added to the compiler platform-specific documentation here
33+
was not maintained at that time. This means that the list below is not
34+
exhaustive and there are more interested parties in this target. That being
35+
said since when this document was last updated those interested in maintaining
36+
this target are:
37+
38+
- Alex Crichton, https://github.com/alexcrichton
39+
40+
## Requirements
41+
42+
This target is cross-compiled. The target includes support for `std` itself,
43+
but as mentioned above many pieces of functionality that require an operating
44+
system do not work and will return errors.
45+
46+
This target currently has no equivalent in C/C++. There is no C/C++ toolchain
47+
for this target. While interop is theoretically possible it's recommended to
48+
instead use one of:
49+
50+
* `wasm32-unknown-emscripten` - for web-based use cases the Emscripten
51+
toolchain is typically chosen for running C/C++.
52+
* [`wasm32-wasip1`](./wasm32-wasip1.md) - the wasi-sdk toolchain is used to
53+
compile C/C++ on this target and can interop with Rust code. WASI works on
54+
the web so far as there's no blocker, but an implementation of WASI APIs
55+
must be either chosen or reimplemented.
56+
57+
This target has no build requirements beyond what's in-tree in the Rust
58+
repository. Linking binaries requires LLD to be enabled for the `wasm-ld`
59+
driver. This target uses the `dlmalloc` crate as the default global allocator.
60+
61+
## Building the target
62+
63+
Building this target can be done by:
64+
65+
* Configure the `wasm32-unknown-unknown` target to get built.
66+
* Configure LLD to be built.
67+
* Ensure the `WebAssembly` target backend is not disabled in LLVM.
68+
69+
These are all controlled through `config.toml` options. It should be possible
70+
to build this target on any platform.
71+
72+
## Building Rust programs
73+
74+
Rust programs can be compiled by adding this target via rustup:
75+
76+
```sh
77+
$ rustup target add wasm32-unknown-unknown
78+
```
79+
80+
and then compiling with the target:
81+
82+
```sh
83+
$ rustc foo.rs --target wasm32-unknown-unknown
84+
$ file foo.wasm
85+
```
86+
87+
## Cross-compilation
88+
89+
This target can be cross-compiled from any hosts.
90+
91+
## Testing
92+
93+
This target is not tested in CI for the rust-lang/rust repository. Many tests
94+
must be disabled to run on this target and failures are non-obvious because
95+
println doesn't work in the standard library. It's recommended to test the
96+
`wasm32-wasip1` target instead for WebAssembly compatibility.
97+
98+
## Conditionally compiling code
99+
100+
It's recommended to conditionally compile code for this target with:
101+
102+
```text
103+
#[cfg(all(target_family = "wasm", target_os = "unknown"))]
104+
```
105+
106+
Note that there is no way to tell via `#[cfg]` whether code will be running on
107+
the web or not.
108+
109+
## Enabled WebAssembly features
110+
111+
WebAssembly is an evolving standard which adds new features such as new
112+
instructions over time. This target's default set of supported WebAssembly
113+
features will additionally change over time. The `wasm32-unknown-unknown` target
114+
inherits the default settings of LLVM which typically matches the default
115+
settings of Emscripten as well.
116+
117+
Changes to WebAssembly go through a [proposals process][proposals] but reaching
118+
the final stage (stage 5) does not automatically mean that the feature will be
119+
enabled in LLVM and Rust by default. At this time the general guidance is that
120+
features must be present in most engines for a "good chunk of time" before
121+
they're enabled in LLVM by default. There is currently not exact number of
122+
months or engines that are required to enable features by default.
123+
124+
[proposals]: https://github.com/WebAssembly/proposals
125+
126+
If you're compiling WebAssembly code for an engine that does not support a
127+
feature in LLVM's default feature set then the feature must be disabled at
128+
compile time. Note, though, that enabled features may be used in the standard
129+
library or precompiled libraries shipped via rustup. This means that not only
130+
does your own code need to be compiled with the correct set of flags but the
131+
Rust standard library additionally must be recompiled.
132+
133+
Compiling all code for the initial release of WebAssembly looks like:
134+
135+
```sh
136+
$ export RUSTFLAG=-Ctarget-cpu=mvp
137+
$ cargo +nightly build -Zbuild-std=panic_abort,std --target wasm32-unknown-unknown
138+
```
139+
140+
Here the `mvp` "cpu" is a placeholder in LLVM for disabling all supported
141+
features by default. Cargo's `-Zbuild-std` feature, a Nightly Rust feature, is
142+
then used to recompile the standard library in addition to your own code. This
143+
will produce a binary that uses only the original WebAssembly features by
144+
default and no proposals since its inception.
145+
146+
To enable individual features it can be done with `-Ctarget-feature=+foo`.
147+
Available features can be found through:
148+
149+
```sh
150+
$ rustc -Ctarget-feature=help --target wasm32-unknown-unknown
151+
```
152+
153+
You'll need to consult your WebAssembly engine's documentation to learn more
154+
about the supported WebAssembly features the engine has.

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

+7
Original file line numberDiff line numberDiff line change
@@ -132,3 +132,10 @@ It's recommended to conditionally compile code for this target with:
132132

133133
Note that the `target_env = "p1"` condition first appeared in Rust 1.80. Prior
134134
to Rust 1.80 the `target_env` condition was not set.
135+
136+
## Enabled WebAssembly features
137+
138+
The default set of WebAssembly features enabled for compilation is currently the
139+
same across all WebAssembly targets. For more information on WebAssembly
140+
features see the documentation for
141+
[`wasm32-unknown-unknokwn`](./wasm32-unknown-unknown.md)

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

+7
Original file line numberDiff line numberDiff line change
@@ -61,3 +61,10 @@ It's recommended to conditionally compile code for this target with:
6161
```text
6262
#[cfg(all(target_os = "wasi", target_env = "p2"))]
6363
```
64+
65+
## Enabled WebAssembly features
66+
67+
The default set of WebAssembly features enabled for compilation is currently the
68+
same across all WebAssembly targets. For more information on WebAssembly
69+
features see the documentation for
70+
[`wasm32-unknown-unknokwn`](./wasm32-unknown-unknown.md)

0 commit comments

Comments
 (0)