Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Document WebAssembly target feature expectations #128511

Merged
merged 9 commits into from
Aug 23, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/doc/rustc/src/platform-support.md
Original file line number Diff line number Diff line change
Expand Up @@ -190,7 +190,7 @@ target | std | notes
[`thumbv8m.main-none-eabi`](platform-support/thumbv8m.main-none-eabi.md) | * | Bare Armv8-M Mainline
[`thumbv8m.main-none-eabihf`](platform-support/thumbv8m.main-none-eabi.md) | * | Bare Armv8-M Mainline, hardfloat
`wasm32-unknown-emscripten` | ✓ | WebAssembly via Emscripten
`wasm32-unknown-unknown` | ✓ | WebAssembly
[`wasm32-unknown-unknown`](platform-support/wasm32-unknown-unknown.md) | ✓ | WebAssembly
`wasm32-wasi` | ✓ | WebAssembly with WASI (undergoing a [rename to `wasm32-wasip1`][wasi-rename])
[`wasm32-wasip1`](platform-support/wasm32-wasip1.md) | ✓ | WebAssembly with WASI
[`wasm32-wasip1-threads`](platform-support/wasm32-wasip1-threads.md) | ✓ | WebAssembly with WASI Preview 1 and threads
Expand Down
154 changes: 154 additions & 0 deletions src/doc/rustc/src/platform-support/wasm32-unknown-unknown.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
# `wasm32-unknown-unknown`

**Tier: 2**

The `wasm32-unknown-unknown` target is a WebAssembly compilation target which
does not import any functions from the host for the standard library. This is
the "minimal" WebAssembly in the sense of making the fewest assumptions about
the host environment. This target is often used when compiling to the web or
JavaScript environments as there is not standard for what functions can be
alexcrichton marked this conversation as resolved.
Show resolved Hide resolved
imported on the web. This target can also be useful for creating minimal or
bare-bones WebAssembly binaries.

The `wasm32-unknown-unknown` target has support for the Rust standard library
but many parts of the standard library do not work and return errors. For
example `println!` does nothing, `std::fs` always return errors, and
`std::thread::spawn` will panic. There is no means by which this can be
overridden. For a WebAssembly target that more fully supports the standard
library see the [`wasm32-wasip1`](./wasm32-wasip1.md) or
[`wasm32-wasip2`](./wasm32-wasip2.md) targets.

The `wasm32-unknown-unknown` target has full support for the `core` and `alloc`
crates. It additionally supports the `HashMap` type in the `std` crate, although
hash maps are not randomized like they are on other platforms.

One existing user of this target (please feel free to edit and expand this list
too) is the [`wasm-bindgen` project](https://github.com/rustwasm/wasm-bindgen)
which facilitates Rust code interoperating with JavaScript code. Note, though,
that not all uses of `wasm32-unknown-unknown` are using JavaScript and the web.

## Target maintainers

When this target was added to the compiler platform-specific documentation here
was not maintained at that time. This means that the list below is not
exhaustive and there are more interested parties in this target. That being
said since when this document was last updated those interested in maintaining
this target are:

- Alex Crichton, https://github.com/alexcrichton

## Requirements

This target is cross-compiled. The target includes support for `std` itself,
but as mentioned above many pieces of functionality that require an operating
system do not work and will return errors.

This target currently has no equivalent in C/C++. There is no C/C++ toolchain
for this target. While interop is theoretically possible it's recommended to
instead use one of:

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

This target has no build requirements beyond what's in-tree in the Rust
repository. Linking binaries requires LLD to be enabled for the `wasm-ld`
driver. This target uses the `dlmalloc` crate as the default global allocator.

## Building the target

Building this target can be done by:

* Configure the `wasm32-unknown-unknown` target to get built.
* Configure LLD to be built.
* Ensure the `WebAssembly` target backend is not disabled in LLVM.

These are all controlled through `config.toml` options. It should be possible
to build this target on any platform.

## Building Rust programs

Rust programs can be compiled by adding this target via rustup:

```sh
$ rustup target add wasm32-unknown-unknown
```

and then compiling with the target:

```sh
$ rustc foo.rs --target wasm32-unknown-unknown
$ file foo.wasm
```

## Cross-compilation

This target can be cross-compiled from any hosts.
alexcrichton marked this conversation as resolved.
Show resolved Hide resolved

## Testing

This target is not tested in CI for the rust-lang/rust repository. Many tests
must be disabled to run on this target and failures are non-obvious because
println doesn't work in the standard library. It's recommended to test the
alexcrichton marked this conversation as resolved.
Show resolved Hide resolved
`wasm32-wasip1` target instead for WebAssembly compatibility.

## Conditionally compiling code

It's recommended to conditionally compile code for this target with:

```text
#[cfg(all(target_family = "wasm", target_os = "unknown"))]
```

Note that there is no way to tell via `#[cfg]` whether code will be running on
the web or not.

## Enabled WebAssembly features

WebAssembly is an evolving standard which adds new features such as new
instructions over time. This target's default set of supported WebAssembly
features will additionally change over time. The `wasm32-unknown-unknown` target
inherits the default settings of LLVM which typically matches the default
settings of Emscripten as well.

Changes to WebAssembly go through a [proposals process][proposals] but reaching
the final stage (stage 5) does not automatically mean that the feature will be
enabled in LLVM and Rust by default. At this time the general guidance is that
features must be present in most engines for a "good chunk of time" before
they're enabled in LLVM by default. There is currently not exact number of
alexcrichton marked this conversation as resolved.
Show resolved Hide resolved
months or engines that are required to enable features by default.

[proposals]: https://github.com/WebAssembly/proposals

If you're compiling WebAssembly code for an engine that does not support a
feature in LLVM's default feature set then the feature must be disabled at
compile time. Note, though, that enabled features may be used in the standard
library or precompiled libraries shipped via rustup. This means that not only
does your own code need to be compiled with the correct set of flags but the
Rust standard library additionally must be recompiled.

Compiling all code for the initial release of WebAssembly looks like:

```sh
$ export RUSTFLAG=-Ctarget-cpu=mvp
alexcrichton marked this conversation as resolved.
Show resolved Hide resolved
$ cargo +nightly build -Zbuild-std=panic_abort,std --target wasm32-unknown-unknown
```

Here the `mvp` "cpu" is a placeholder in LLVM for disabling all supported
features by default. Cargo's `-Zbuild-std` feature, a Nightly Rust feature, is
then used to recompile the standard library in addition to your own code. This
will produce a binary that uses only the original WebAssembly features by
default and no proposals since its inception.

To enable individual features it can be done with `-Ctarget-feature=+foo`.
Available features can be found through:

```sh
$ rustc -Ctarget-feature=help --target wasm32-unknown-unknown
```
alexcrichton marked this conversation as resolved.
Show resolved Hide resolved

You'll need to consult your WebAssembly engine's documentation to learn more
about the supported WebAssembly features the engine has.
7 changes: 7 additions & 0 deletions src/doc/rustc/src/platform-support/wasm32-wasip1.md
Original file line number Diff line number Diff line change
Expand Up @@ -132,3 +132,10 @@ It's recommended to conditionally compile code for this target with:

Note that the `target_env = "p1"` condition first appeared in Rust 1.80. Prior
to Rust 1.80 the `target_env` condition was not set.

## Enabled WebAssembly features

The default set of WebAssembly features enabled for compilation is currently the
same across all WebAssembly targets. For more information on WebAssembly
alexcrichton marked this conversation as resolved.
Show resolved Hide resolved
features see the documentation for
[`wasm32-unknown-unknokwn`](./wasm32-unknown-unknown.md)
7 changes: 7 additions & 0 deletions src/doc/rustc/src/platform-support/wasm32-wasip2.md
Original file line number Diff line number Diff line change
Expand Up @@ -61,3 +61,10 @@ It's recommended to conditionally compile code for this target with:
```text
#[cfg(all(target_os = "wasi", target_env = "p2"))]
```

## Enabled WebAssembly features

The default set of WebAssembly features enabled for compilation is currently the
same across all WebAssembly targets. For more information on WebAssembly
features see the documentation for
[`wasm32-unknown-unknokwn`](./wasm32-unknown-unknown.md)
Loading