Skip to content

Commit e7c1b37

Browse files
committed
Add a new wasm32-wasi-preview1 target to rustc
This commit adds a new target called `wasm32-wasi-preview1` to rustc. This new target is explained in these two MCPs: * rust-lang/compiler-team#607 * rust-lang/compiler-team#695 In short, the previous `wasm32-wasi` target is going to be renamed to `wasm32-wasi-preview1` to better live alongside the [new `wasm32-wasi-preview2` target](#119616). This new target is added alongside the `wasm32-wasi` target and has the exact same definition as the previous target. This PR is effectively a rename of `wasm32-wasi` to `wasm32-wasi-preview1`. Note, however, that as explained in rust-lang/compiler-team#695 the previous `wasm32-wasi` target is not being removed at this time. This change will reach stable Rust before even a warning about the rename will be printed. At this time this change is just the start where a new target is introduced and users can start migrating if they support only Nightly for example.
1 parent cb4d9a1 commit e7c1b37

File tree

14 files changed

+210
-123
lines changed

14 files changed

+210
-123
lines changed

compiler/rustc_target/src/spec/mod.rs

+1
Original file line numberDiff line numberDiff line change
@@ -1574,6 +1574,7 @@ supported_targets! {
15741574
("wasm32-unknown-emscripten", wasm32_unknown_emscripten),
15751575
("wasm32-unknown-unknown", wasm32_unknown_unknown),
15761576
("wasm32-wasi", wasm32_wasi),
1577+
("wasm32-wasi-preview1", wasm32_wasi_preview1),
15771578
("wasm32-wasi-preview1-threads", wasm32_wasi_preview1_threads),
15781579
("wasm64-unknown-unknown", wasm64_unknown_unknown),
15791580

Original file line numberDiff line numberDiff line change
@@ -1,119 +1,11 @@
1-
//! The `wasm32-wasi` target is a new and still (as of April 2019) an
2-
//! experimental target. The definition in this file is likely to be tweaked
3-
//! over time and shouldn't be relied on too much.
1+
//! NB: This target is in the process of being renamed to
2+
//! `wasm32-wasi-preview1`. For more information see:
43
//!
5-
//! The `wasi` target is a proposal to define a standardized set of syscalls
6-
//! that WebAssembly files can interoperate with. This set of syscalls is
7-
//! intended to empower WebAssembly binaries with native capabilities such as
8-
//! filesystem access, network access, etc.
9-
//!
10-
//! You can see more about the proposal at <https://wasi.dev>.
11-
//!
12-
//! The Rust target definition here is interesting in a few ways. We want to
13-
//! serve two use cases here with this target:
14-
//!
15-
//! * First, we want Rust usage of the target to be as hassle-free as possible,
16-
//! ideally avoiding the need to configure and install a local wasm32-wasi
17-
//! toolchain.
18-
//!
19-
//! * Second, one of the primary use cases of LLVM's new wasm backend and the
20-
//! wasm support in LLD is that any compiled language can interoperate with
21-
//! any other. To that the `wasm32-wasi` target is the first with a viable C
22-
//! standard library and sysroot common definition, so we want Rust and C/C++
23-
//! code to interoperate when compiled to `wasm32-unknown-unknown`.
24-
//!
25-
//! You'll note, however, that the two goals above are somewhat at odds with one
26-
//! another. To attempt to solve both use cases in one go we define a target
27-
//! that (ab)uses the `crt-static` target feature to indicate which one you're
28-
//! in.
29-
//!
30-
//! ## No interop with C required
31-
//!
32-
//! By default the `crt-static` target feature is enabled, and when enabled
33-
//! this means that the bundled version of `libc.a` found in `liblibc.rlib`
34-
//! is used. This isn't intended really for interoperation with a C because it
35-
//! may be the case that Rust's bundled C library is incompatible with a
36-
//! foreign-compiled C library. In this use case, though, we use `rust-lld` and
37-
//! some copied crt startup object files to ensure that you can download the
38-
//! wasi target for Rust and you're off to the races, no further configuration
39-
//! necessary.
40-
//!
41-
//! All in all, by default, no external dependencies are required. You can
42-
//! compile `wasm32-wasi` binaries straight out of the box. You can't, however,
43-
//! reliably interoperate with C code in this mode (yet).
44-
//!
45-
//! ## Interop with C required
46-
//!
47-
//! For the second goal we repurpose the `target-feature` flag, meaning that
48-
//! you'll need to do a few things to have C/Rust code interoperate.
49-
//!
50-
//! 1. All Rust code needs to be compiled with `-C target-feature=-crt-static`,
51-
//! indicating that the bundled C standard library in the Rust sysroot will
52-
//! not be used.
53-
//!
54-
//! 2. If you're using rustc to build a linked artifact then you'll need to
55-
//! specify `-C linker` to a `clang` binary that supports
56-
//! `wasm32-wasi` and is configured with the `wasm32-wasi` sysroot. This
57-
//! will cause Rust code to be linked against the libc.a that the specified
58-
//! `clang` provides.
59-
//!
60-
//! 3. If you're building a staticlib and integrating Rust code elsewhere, then
61-
//! compiling with `-C target-feature=-crt-static` is all you need to do.
62-
//!
63-
//! You can configure the linker via Cargo using the
64-
//! `CARGO_TARGET_WASM32_WASI_LINKER` env var. Be sure to also set
65-
//! `CC_wasm32-wasi` if any crates in the dependency graph are using the `cc`
66-
//! crate.
67-
//!
68-
//! ## Remember, this is all in flux
69-
//!
70-
//! The wasi target is **very** new in its specification. It's likely going to
71-
//! be a long effort to get it standardized and stable. We'll be following it as
72-
//! best we can with this target. Don't start relying on too much here unless
73-
//! you know what you're getting in to!
4+
//! * <https://github.com/rust-lang/compiler-team/issues/607>
5+
//! * <https://github.com/rust-lang/compiler-team/issues/695>
746
75-
use crate::spec::crt_objects;
76-
use crate::spec::LinkSelfContainedDefault;
77-
use crate::spec::{base, Cc, LinkerFlavor, Target};
7+
use crate::spec::Target;
788

799
pub fn target() -> Target {
80-
let mut options = base::wasm::options();
81-
82-
options.os = "wasi".into();
83-
options.add_pre_link_args(LinkerFlavor::WasmLld(Cc::Yes), &["--target=wasm32-wasi"]);
84-
85-
options.pre_link_objects_self_contained = crt_objects::pre_wasi_self_contained();
86-
options.post_link_objects_self_contained = crt_objects::post_wasi_self_contained();
87-
88-
// FIXME: Figure out cases in which WASM needs to link with a native toolchain.
89-
options.link_self_contained = LinkSelfContainedDefault::True;
90-
91-
// Right now this is a bit of a workaround but we're currently saying that
92-
// the target by default has a static crt which we're taking as a signal
93-
// for "use the bundled crt". If that's turned off then the system's crt
94-
// will be used, but this means that default usage of this target doesn't
95-
// need an external compiler but it's still interoperable with an external
96-
// compiler if configured correctly.
97-
options.crt_static_default = true;
98-
options.crt_static_respected = true;
99-
100-
// Allow `+crt-static` to create a "cdylib" output which is just a wasm file
101-
// without a main function.
102-
options.crt_static_allows_dylibs = true;
103-
104-
// WASI's `sys::args::init` function ignores its arguments; instead,
105-
// `args::args()` makes the WASI API calls itself.
106-
options.main_needs_argc_argv = false;
107-
108-
// And, WASI mangles the name of "main" to distinguish between different
109-
// signatures.
110-
options.entry_name = "__main_void".into();
111-
112-
Target {
113-
llvm_target: "wasm32-wasi".into(),
114-
pointer_width: 32,
115-
data_layout: "e-m:e-p:32:32-p10:8:8-p20:8:8-i64:64-n32:64-S128-ni:1:10:20".into(),
116-
arch: "wasm32".into(),
117-
options,
118-
}
10+
super::wasm32_wasi_preview1::target()
11911
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
//! The `wasm32-wasi-preview1` enables compiling to WebAssembly using the first
2+
//! version of the WASI standard, called "preview1". This version of the
3+
//! standard was never formally specified and WASI has since evolved to a
4+
//! "preview2". This target in rustc uses the previous version of the proposal.
5+
//!
6+
//! This target uses the syscalls defined at
7+
//! <https://github.com/WebAssembly/WASI/tree/main/legacy/preview1>.
8+
//!
9+
//! Note that this target was historically called `wasm32-wasi` originally and
10+
//! was since renamed to `wasm32-wasi-preview1` after the preview2 target was
11+
//! introduced.
12+
13+
use crate::spec::crt_objects;
14+
use crate::spec::LinkSelfContainedDefault;
15+
use crate::spec::{base, Cc, LinkerFlavor, Target};
16+
17+
pub fn target() -> Target {
18+
let mut options = base::wasm::options();
19+
20+
options.os = "wasi".into();
21+
options.add_pre_link_args(LinkerFlavor::WasmLld(Cc::Yes), &["--target=wasm32-wasi"]);
22+
23+
options.pre_link_objects_self_contained = crt_objects::pre_wasi_self_contained();
24+
options.post_link_objects_self_contained = crt_objects::post_wasi_self_contained();
25+
26+
// FIXME: Figure out cases in which WASM needs to link with a native toolchain.
27+
options.link_self_contained = LinkSelfContainedDefault::True;
28+
29+
// Right now this is a bit of a workaround but we're currently saying that
30+
// the target by default has a static crt which we're taking as a signal
31+
// for "use the bundled crt". If that's turned off then the system's crt
32+
// will be used, but this means that default usage of this target doesn't
33+
// need an external compiler but it's still interoperable with an external
34+
// compiler if configured correctly.
35+
options.crt_static_default = true;
36+
options.crt_static_respected = true;
37+
38+
// Allow `+crt-static` to create a "cdylib" output which is just a wasm file
39+
// without a main function.
40+
options.crt_static_allows_dylibs = true;
41+
42+
// WASI's `sys::args::init` function ignores its arguments; instead,
43+
// `args::args()` makes the WASI API calls itself.
44+
options.main_needs_argc_argv = false;
45+
46+
// And, WASI mangles the name of "main" to distinguish between different
47+
// signatures.
48+
options.entry_name = "__main_void".into();
49+
50+
Target {
51+
llvm_target: "wasm32-wasi".into(),
52+
pointer_width: 32,
53+
data_layout: "e-m:e-p:32:32-p10:8:8-p20:8:8-i64:64-n32:64-S128-ni:1:10:20".into(),
54+
arch: "wasm32".into(),
55+
options,
56+
}
57+
}

config.example.toml

+3-3
Original file line numberDiff line numberDiff line change
@@ -816,9 +816,9 @@
816816
# The full path to the musl libdir.
817817
#musl-libdir = musl-root/lib
818818

819-
# The root location of the `wasm32-wasi` sysroot. Only used for the
820-
# `wasm32-wasi` target. If you are building wasm32-wasi target, make sure to
821-
# create a `[target.wasm32-wasi]` section and move this field there.
819+
# The root location of the `wasm32-wasi-preview1` sysroot. Only used for WASI
820+
# related targets. Make sure to create a `[target.wasm32-wasi-preview1]`
821+
# section and move this field there (or equivalent for the target being built).
822822
#wasi-root = <none> (path)
823823

824824
# Used in testing for configuring where the QEMU images are located, you

src/ci/docker/host-x86_64/dist-various-2/Dockerfile

+3-1
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,7 @@ ENV TARGETS=x86_64-unknown-fuchsia
112112
ENV TARGETS=$TARGETS,aarch64-unknown-fuchsia
113113
ENV TARGETS=$TARGETS,wasm32-unknown-unknown
114114
ENV TARGETS=$TARGETS,wasm32-wasi
115+
ENV TARGETS=$TARGETS,wasm32-wasi-preview1
115116
ENV TARGETS=$TARGETS,wasm32-wasi-preview1-threads
116117
ENV TARGETS=$TARGETS,sparcv9-sun-solaris
117118
ENV TARGETS=$TARGETS,x86_64-pc-solaris
@@ -135,7 +136,8 @@ ENV TARGETS=$TARGETS,x86_64-unknown-uefi
135136
RUN ln -s /usr/include/x86_64-linux-gnu/asm /usr/local/include/asm
136137

137138
ENV RUST_CONFIGURE_ARGS --enable-extended --enable-lld --disable-docs \
138-
--set target.wasm32-wasi.wasi-root=/wasm32-wasi \
139+
--set target.wasm32-wasi.wasi-root=/wasm32-wasi-preview1 \
140+
--set target.wasm32-wasi-preview1.wasi-root=/wasm32-wasi-preview1 \
139141
--set target.wasm32-wasi-preview1-threads.wasi-root=/wasm32-wasi-preview1-threads \
140142
--musl-root-armv7=/musl-armv7
141143

src/ci/docker/host-x86_64/dist-various-2/build-wasi-toolchain.sh

+1-1
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ make -j$(nproc) \
1515
CC="$bin/clang" \
1616
NM="$bin/llvm-nm" \
1717
AR="$bin/llvm-ar" \
18-
INSTALL_DIR=/wasm32-wasi \
18+
INSTALL_DIR=/wasm32-wasi-preview1 \
1919
install
2020

2121
cd ..

src/doc/rustc/src/SUMMARY.md

+1
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@
5858
- [\*-unknown-netbsd\*](platform-support/netbsd.md)
5959
- [*-unknown-openbsd](platform-support/openbsd.md)
6060
- [\*-unknown-uefi](platform-support/unknown-uefi.md)
61+
- [wasm32-wasi-preview1](platform-support/wasm32-wasi-preview1.md)
6162
- [wasm32-wasi-preview1-threads](platform-support/wasm32-wasi-preview1-threads.md)
6263
- [wasm64-unknown-unknown](platform-support/wasm64-unknown-unknown.md)
6364
- [\*-win7-windows-msvc](platform-support/win7-windows-msvc.md)

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

+3-1
Original file line numberDiff line numberDiff line change
@@ -190,7 +190,8 @@ target | std | notes
190190
[`thumbv8m.main-none-eabihf`](platform-support/arm-none-eabi.md) | * | Bare ARMv8-M Mainline, hardfloat
191191
`wasm32-unknown-emscripten` | ✓ | WebAssembly via Emscripten
192192
`wasm32-unknown-unknown` | ✓ | WebAssembly
193-
`wasm32-wasi` | ✓ | WebAssembly with WASI
193+
`wasm32-wasi` | ✓ | WebAssembly with WASI (undergoing a [rename to `wasm32-wasi-preview1`][wasi-rename])
194+
[`wasm32-wasi-preview1`](platform-support/wasm32-wasi-preview1.md) | ✓ | WebAssembly with WASI
194195
[`wasm32-wasi-preview1-threads`](platform-support/wasm32-wasi-preview1-threads.md) | ✓ | | WebAssembly with WASI Preview 1 and threads
195196
`x86_64-apple-ios` | ✓ | 64-bit x86 iOS
196197
[`x86_64-fortanix-unknown-sgx`](platform-support/x86_64-fortanix-unknown-sgx.md) | ✓ | [Fortanix ABI] for 64-bit Intel SGX
@@ -204,6 +205,7 @@ target | std | notes
204205
[`x86_64-unknown-uefi`](platform-support/unknown-uefi.md) | * | 64-bit UEFI
205206

206207
[^x86_32-floats-x87]: Floating-point support on `i586` targets is non-compliant: the `x87` registers and instructions used for these targets do not provide IEEE-754-compliant behavior, in particular when it comes to rounding and NaN payload bits. See [issue #114479][x86-32-float-issue].
208+
[wasi-rename]: https://github.com/rust-lang/compiler-team/issues/607
207209

208210
[Fortanix ABI]: https://edp.fortanix.com/
209211

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
# `wasm32-wasi-preview1`
2+
3+
**Tier: 2**
4+
5+
The `wasm32-wasi-preview1` target is a WebAssembly compilation target which
6+
assumes that the [WASI Preview1] set of "syscalls" are available for use in the
7+
standard library. Historically this target in the Rust compiler was one of the
8+
first for WebAssembly where Rust and C code are explicitly intended to
9+
interoperate as well.
10+
11+
There's a bit of history to the target and current development which is also
12+
worth explaining before going much further. Historically this target was
13+
originally called `wasm32-wasi` in both rustc and Clang. This was first added
14+
to Rust in 2019. In the intervening years leading up to 2024 the WASI standard
15+
continued to be developed and was eventually "rebased" on top of the [Component
16+
Model]. This was a large change to the WASI specification and was released as
17+
0.2.0 ("preview 2" colloquially) in January 2024. The previous target's name in
18+
rustc, `wasm32-wasi`, was then renamed to `wasm32-wasi-preview1`, to avoid
19+
confusion with this new target to be added to rustc as `wasm32-wasi-preview2`.
20+
Some more context can be found in these MCPs:
21+
22+
* [Rename wasm32-wasi target to wasm32-wasi-preview1](https://github.com/rust-lang/compiler-team/issues/607)
23+
* [Smooth the renaming transition of wasm32-wasi](https://github.com/rust-lang/compiler-team/issues/695)
24+
25+
At this point the `wasm32-wasi-preview1` target is intended for historical
26+
compatibility with the first version of the WASI standard. As of now (January
27+
2024) the 0.2.0 target of WASI ("preview2") is relatively new. The state of
28+
WASI will likely change in few years after which point this documentation will
29+
probably receive another update.
30+
31+
[WASI Preview1]: https://github.com/WebAssembly/WASI/tree/main/legacy/preview1
32+
[Component Model]: https://github.com/webassembly/component-model
33+
34+
Today the `wasm32-wasi-preview1` target will generate core WebAssembly modules
35+
which will import functions from the `wasi_snapshot_preview1` module for
36+
OS-related functionality (e.g. printing).
37+
38+
## Target maintainers
39+
40+
When this target was added to the compiler platform-specific documentation here
41+
was not maintained at that time. This means that the list below is not
42+
exhaustive and there are more interested parties in this target. That being
43+
said since when this document was last updated those interested in maintaining
44+
this target are:
45+
46+
- Alex Crichton, https://github.com/alexcrichton
47+
48+
## Requirements
49+
50+
This target is cross-compiled. The target includes support for `std` itself,
51+
but not all of the standard library works. For example spawning a thread will
52+
always return an error (see the `wasm32-wasi-preview1-threads` target for
53+
example). Another example is that spawning a process will always return an
54+
error. Operations such as opening a file, however, will be implemented by
55+
calling WASI-defined APIs.
56+
57+
The WASI targets for Rust are explicitly intended to interoperate with other
58+
languages compiled to WebAssembly, for example C/C++. Any ABI differences or
59+
mismatches are considered bugs that need to be fixed.
60+
61+
By default the WASI targets in Rust ship in rustup with a precompiled copy of
62+
[`wasi-libc`] meaning that a WebAssembly-targetting-Clang is not required to
63+
use the WASI targets from Rust. If there is no actual interoperation with C
64+
then `rustup target add wasm32-wasi-preview1` is all that's needed to get
65+
started with WASI.
66+
67+
Note that this behavior can be controlled with `-Clinker` and
68+
`-Clink-self-contained`, however. By specifying `clang` as a linker and
69+
disabling the `link-self-contained` option an external version of `libc.a` can
70+
be used instead.
71+
72+
[`wasi-libc`]: https://github.com/WebAssembly/wasi-libc
73+
74+
## Building the target
75+
76+
To build this target a compiled version of [`wasi-libc`] is required to be
77+
present at build time. This can be installed through
78+
[`wasi-sdk`](https://github.com/WebAssembly/wasi-sdk) as well. This is the
79+
configured with:
80+
81+
```toml
82+
[target.wasm32-wasi-preview1]
83+
wasi-root = ".../wasi-libc/sysroot"
84+
```
85+
86+
Additionally users will need to enable LLD when building Rust from source as
87+
LLVM's `wasm-ld` driver for LLD is required when linking WebAssembly code
88+
together.
89+
90+
## Building Rust programs
91+
92+
The `wasm32-wasi-preview1` target is shipped with rustup so users can install
93+
the target with:
94+
95+
```text
96+
rustup target add wasm32-wasi-preview1
97+
```
98+
99+
> **Note**: the `wasm32-wasi-preview1` target is new and may only be available
100+
> on nightly by the time you're reading this. If `wasm32-wasi-preview1` isn't
101+
> available on stable Rust then `wasm32-wasi` should be available instead.
102+
103+
Rust programs can be built for that target:
104+
105+
```text
106+
rustc --target wasm32-wasi-preview1 your-code.rs
107+
```
108+
109+
## Cross-compilation
110+
111+
This target can be cross-compiled from any hosts.
112+
113+
## Testing
114+
115+
Currently the WASI target is not tested in rust-lang/rust CI. This means that
116+
tests in the repository are not guaranteed to pass. This is theoretically
117+
possibly by installing a standalone WebAssembly runtime and using it as a
118+
"runner" for all tests, but there are various failures that will need to be
119+
waded through to adjust tests to work on the WASI target.

src/tools/build-manifest/src/main.rs

+1
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,7 @@ static TARGETS: &[&str] = &[
145145
"wasm32-unknown-emscripten",
146146
"wasm32-unknown-unknown",
147147
"wasm32-wasi",
148+
"wasm32-wasi-preview1",
148149
"wasm32-wasi-preview1-threads",
149150
"x86_64-apple-darwin",
150151
"x86_64-apple-ios",

0 commit comments

Comments
 (0)