Browse Source
* Update Wasmtime's tier stability documentation Move some items between tiers and add a few misc items here and there. * Update platform support documentation Re-word lots of this since it was originally written, link to the tiers of support page, and rewrite the section on `no_std`. * Update the `min-platform` example with no_std This commit updates the preexisting `min-platform` example to no longer require Nightly Rust and instead use the `no_std` support now added to Wasmtime. This involved: * Change the build process to produce a staticlib which is then manually converted via `cc` into a shared library for the native Linux platform. * Compile the modules outside of the embedding and only `deserialize` within the embedding. * Update the `indexmap` dependency to pick up a bug fix required in `no_std` mode (apparently, it fails on indexmap@2.0.0 and passes at 2.2.6, I didn't dig much further). This commit additionally makes the `wasmtime-platform.h` header file generated by the example a release artifact for Wasmtime itself. The header itself is touched up a bit by configuring some more `cbindgen` options as well. * Fix clippy build prtest:full * Review comments * Pass gc-sections to linking the librarypull/8559/head
Alex Crichton
6 months ago
committed by
GitHub
17 changed files with 396 additions and 290 deletions
@ -1,139 +1,81 @@ |
|||
# Platform Support |
|||
|
|||
The `wasmtime` project is a configurable and lightweight runtime for WebAssembly |
|||
which has a number of ways it can be configured. Not all features are supported |
|||
on all platforms, but it is intended that `wasmtime` can run in some capacity on |
|||
almost all platforms! The matrix of what's being tested, what works, and what's |
|||
supported where is evolving over time, and this document hopes to capture a |
|||
snapshot of what the current state of the world looks like. |
|||
|
|||
All features of `wasmtime` should work on the following platforms: |
|||
|
|||
* Linux x86\_64 |
|||
* Linux aarch64 |
|||
* macOS x86\_64 |
|||
This page is intended to give a high-level overview of Wasmtime's platform |
|||
support along with some aspirations of Wasmtime. For more details see the |
|||
documentation on [tiers of stability](./stability-tiers.md) which has specific |
|||
information about what's supported in Wasmtime on a per-matrix-combination |
|||
basis. |
|||
|
|||
Wasmtime strives to support hardware that anyone wants to run WebAssembly on. |
|||
Maintainers of Wasmtime support a number of "major" platforms themselves but |
|||
porting work may be required to support platforms that maintainers are not |
|||
themselves familiar with. Out-of-the box Wasmtime supports: |
|||
|
|||
* Linux x86\_64, aarch64, s390x, and riscv64 |
|||
* macOS x86\_64, aarch64 |
|||
* Windows x86\_64 |
|||
|
|||
For more detailed information about supported platforms, please check out the |
|||
sections below! |
|||
Other platforms such as Android, iOS, and the BSD family of OSes are not |
|||
built-in yet. PRs for porting are welcome and maintainers are happy to add more |
|||
entries to the CI matrix for these platforms. |
|||
|
|||
## JIT compiler support |
|||
## Compiler Support |
|||
|
|||
The JIT compiler, backed by Cranelift, supports the x86\_64 and aarch64 |
|||
architectures at this time. Support for at least ARM and x86 is planned as well. |
|||
Cranelift supports x86\_64, aarch64, s390x, and riscv64. No 32-bit platform is |
|||
currently supported. Building a new backend for Cranelift is a relatively large |
|||
undertaking which maintainers are willing to help with but it's recommended to |
|||
reach out to Cranelift maintainers first to discuss this. |
|||
|
|||
Usage of the JIT compiler will require a host operating system which supports |
|||
creating executable memory pages on-the-fly. In Rust terms this generally means |
|||
that `std` needs to be supported on this platform. |
|||
Winch supports x86\_64. The aarch64 backend is in development. Winch is built on |
|||
Cranelift's support for emitting instructions so Winch's possible backend list |
|||
is currently limited to what Cranelift supports. |
|||
|
|||
Usage of the Cranelift or Winch requires a host operating system which supports |
|||
creating executable memory pages on-the-fly. Support for statically linking in a |
|||
single precompiled module is not supported at this time. |
|||
|
|||
Both Cranelift and Winch can be used either in AOT or JIT mode. In AOT mode one |
|||
process precompiles a module/component and then loads it into another process. |
|||
In JIT mode this is all done within the same process. |
|||
|
|||
Neither Cranelift nor Winch support tiering at this time in the sense of having |
|||
a WebAssembly module start from a Winch compilation and automatically switch to |
|||
a Cranelift compilation. Modules are either entirely compiled with Winch or |
|||
Cranelift. |
|||
|
|||
## Interpreter support |
|||
|
|||
At this time `wasmtime` does not have a mode in which it simply interprets |
|||
WebAssembly code. It is planned to add support for an interpreter, however, and |
|||
WebAssembly code. It is desired to add support for an interpreter, however, and |
|||
this will have minimal system dependencies. It is planned that the system will |
|||
need to support some form of dynamic memory allocation, but other than that not |
|||
much else will be needed. |
|||
|
|||
## What about `#[no_std]`? |
|||
|
|||
The `wasmtime` project does not currently use `#[no_std]` for its crates, but |
|||
this is not because it won't support it! For information on building Wasmtime |
|||
for a custom target see [the minimal build |
|||
documentation](./examples-minimal.md). Please [open an |
|||
issue](https://github.com/bytecodealliance/wasmtime/issues/new) on the |
|||
`wasmtime` repository to request support for a specific platform. |
|||
|
|||
This is a common question we are asked, however, so to provide some more context |
|||
on why Wasmtime is the way it is, here's some responses to frequent points |
|||
raised about `#![no_std]`: |
|||
|
|||
* **What if my platform doesn't have `std`?** - For platforms without support |
|||
for the Rust standard library the JIT compiler of Wasmtime often won't run on |
|||
the platform as well. The JIT compiler requires `mmap` (or an equivalent), and |
|||
presence of `mmap` often implies presence of a libc which means Rust's `std` |
|||
library works. |
|||
|
|||
Cargo's [`-Z build-std` feature][zbuild-std] feature is also intended to help |
|||
easily build the standard library for all platforms. With this feature you can |
|||
recompile the standard library (using Nightly Rust for now) with a [custom |
|||
target specification][custom-target] if necessary. Additionally the intention |
|||
at this time is to get `std` building for all platforms, regardless of what |
|||
the platform actually supports. This change is taking time to implement, but |
|||
[rust-lang/rust#74033] is an example of this support growing over time. |
|||
|
|||
We're also interested in running Wasmtime without a JIT compiler in the |
|||
future, but that is not implemented at this time. Implementing this will |
|||
require a lot more work than tagging crates `#![no_std]`. The Wasmtime |
|||
developers are also very interested in supporting as many targets as possible, |
|||
so if Wasmtime doesn't work on your platform yet we'd love to learn why and |
|||
what we can do to support that platform, but the conversation here is |
|||
typically more nuanced than simply making `wasmtime` compile without `std`. |
|||
|
|||
* **Doesn't `#![no_std]` have smaller binary sizes?** - There's a lot of factors |
|||
that affect binary size in Rust. Compilation options are a huge one but beyond |
|||
that idioms and libraries linked matter quite a lot as well. Code is not |
|||
inherently large when using `std` instead of `core`, it's just that often code |
|||
using `std` has more dependencies (like `std::thread`) which requires code to |
|||
bind. Code size improvements can be made to code using `std` and `core` |
|||
equally, and switching to `#![no_std]` is not a silver bullet for compile |
|||
sizes. |
|||
|
|||
* **The patch to switch to `#![no_std]` is small, why not accept it?** - PRs to |
|||
switch to `#![no_std]` are often relatively small or don't impact too many |
|||
parts of the system. There's a lot more to developing a `#![no_std]` |
|||
WebAssembly runtime than switching a few crates, however. Maintaining a |
|||
`#![no_std]` library over time has a number of costs associated with it: |
|||
|
|||
* Rust has no stable way to diagnose `no_std` errors in an otherwise `std` |
|||
build, which means that to support this feature it must be tested on CI with |
|||
a `no_std` target. This is costly in terms of CI time, CI maintenance, and |
|||
developers having to do extra builds to avoid CI errors. Note that this |
|||
isn't *more* costly than any other platform supported by Wasmtime, but it's |
|||
a cost nonetheless. |
|||
|
|||
* Idioms in `#![no_std]` are quite different than normal Rust code. You'll |
|||
import from different crates (`core` instead of `std`) and data structures |
|||
have to all be manually imported from `alloc`. These idioms are difficult to |
|||
learn for newcomers to the project and are not well documented in the |
|||
ecosystem. This cost of development and maintenance is not unique to |
|||
Wasmtime but in general affects the `#![no_std]` ecosystem at large, |
|||
unfortunately. |
|||
|
|||
* Currently Wasmtime does not have a target use case which requires |
|||
`#![no_std]` support, so it's hard to justify these costs of development. |
|||
We're very interested in supporting as many use cases and targets as |
|||
possible, but the decision to support a target needs to take into account |
|||
the costs associated so we can plan accordingly. Effectively we need to have |
|||
a goal in mind instead of taking on the costs of `#![no_std]` blindly. |
|||
|
|||
* At this time it's not clear whether `#![no_std]` will be needed long-term, |
|||
so eating short-term costs may not pay off in the long run. Features like |
|||
Cargo's [`-Z build-std`][zbuild-std] may mean that `#![no_std]` is less and |
|||
less necessary over time. |
|||
|
|||
* **How can Wasmtime support `#![no_std]` if it uses X?** - Wasmtime as-is today |
|||
is not suitable for many `#![no_std]` contexts. For example it might use |
|||
`mmap` for allocating JIT code memory, leverage threads for caching, or use |
|||
thread locals when calling into JIT code. These features are difficult to |
|||
support in their full fidelity on all platforms, but the Wasmtime developers |
|||
are very much aware of this! Wasmtime is intended to be configurable where |
|||
many of these features are compile-time or runtime options. For example caches |
|||
can be disabled, JITs can be removed and replaced with interpreters, or users |
|||
could provide a callback to allocate memory instead of using the OS. |
|||
This is sort of a long-winded way of saying that Wasmtime on the surface may |
|||
today look like it won't support `#![no_std]`, but this is almost always |
|||
simply a matter of time and development priorities rather than a fundamental |
|||
reason why Wasmtime *couldn't* support `#![no_std]`. |
|||
|
|||
Note that at this time these guidelines apply not only to Wasmtime but also to |
|||
some of its dependencies developed by the Bytecode Alliance such as the |
|||
[wasm-tools repository](https://github.com/bytecodealliance/wasm-tools). These |
|||
projects don't have the same runtime requirements as Wasmtime (e.g. `wasmparser` |
|||
doesn't need `mmap`), but we're following the same guidelines above at this |
|||
time. Patches to add `#![no_std]`, while possibly small, incur many of the same |
|||
costs and also have an unclear longevity as features like [`-Z |
|||
build-std`][zbuild-std] evolve. |
|||
|
|||
[zbuild-std]: https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#build-std |
|||
[custom-target]: https://doc.rust-lang.org/rustc/targets/custom.html |
|||
[rust-lang/rust#74033]: https://github.com/rust-lang/rust/pull/74033 |
|||
## Support for `#![no_std]` |
|||
|
|||
The `wasmtime` crate supports being build on no\_std platforms in Rust, but |
|||
only for a subset of its compile-time Cargo features. Currently supported |
|||
Cargo features are: |
|||
|
|||
* `runtime` |
|||
* `gc` |
|||
* `component-model` |
|||
|
|||
This notably does not include the `default` feature which means that when |
|||
depending on Wasmtime you'll need to specify `default-features = false`. This |
|||
also notably does not include Cranelift or Winch at this time meaning that |
|||
no\_std platforms must be used in AOT mode where the module is precompiled |
|||
elsewhere. |
|||
|
|||
Wasmtime's support for no\_std requires the embedder to implement the equivalent |
|||
of a C header file to indicate how to perform basic OS operations such as |
|||
allocating virtual memory. This API can be found as `wasmtime-platform.h` in |
|||
Wasmtime's release artifacts or at |
|||
`examples/min-platform/embedding/wasmtime-platform.h` in the source tree. Note |
|||
that this API is not guaranteed to be stable at this time, it'll need to be |
|||
updated when Wasmtime is updated. |
|||
|
|||
Wasmtime's runtime will use the symbols defined in this file meaning that if |
|||
they're not defined then a link-time error will be generated. Embedders are |
|||
required to implement these functions in accordance with their documentation to |
|||
enable Wasmtime to run on custom platforms. |
|||
|
@ -1 +1,2 @@ |
|||
libwasmtime-platform.so |
|||
libembedding.so |
|||
|
@ -1,18 +0,0 @@ |
|||
{ |
|||
"arch": "aarch64", |
|||
"data-layout": "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128", |
|||
"dynamic-linking": true, |
|||
"has-thread-local": true, |
|||
"is-builtin": false, |
|||
"llvm-target": "aarch64-unknown-linux-gnu", |
|||
"max-atomic-width": 64, |
|||
"os": "minwasmtime", |
|||
"position-independent-executables": true, |
|||
"panic-strategy": "abort", |
|||
"frame-pointer": "always", |
|||
"relro-level": "full", |
|||
"stack-probes": { |
|||
"kind": "inline" |
|||
}, |
|||
"target-pointer-width": "64" |
|||
} |
@ -0,0 +1,20 @@ |
|||
language = "C" |
|||
include_guard = "_WASMTIME_PLATFORM_H" |
|||
include_version = true |
|||
cpp_compat = true |
|||
|
|||
header = """ |
|||
// Platform support for Wasmtime's `no_std` build. |
|||
// |
|||
// This header file is what Wasmtime will rely on when it does not otherwise |
|||
// have support for the native platform. This can happen with `no_std` binaries |
|||
// for example where the traditional Unix-or-Windows implementation is not |
|||
// suitable. |
|||
// |
|||
// Embedders are expected to implement the symbols defined in this header file. |
|||
// These symbols can be defined either in C/C++ or in Rust (using |
|||
// `#[no_mangle]`). |
|||
// |
|||
// Some more information about this header can additionally be found at |
|||
// <https://docs.wasmtime.dev/stability-platform-support.html>. |
|||
""" |
@ -0,0 +1,12 @@ |
|||
#![cfg(not(unix))] // gets `cargo clippy` working
|
|||
|
|||
use core::panic::PanicInfo; |
|||
|
|||
#[panic_handler] |
|||
fn handler(_info: &PanicInfo) -> ! { |
|||
// NB: should ideally print something here but for this example this is left
|
|||
// out. A more complete embedding would likely turn `info` into a
|
|||
// stack-allocated string and then pass that as a message to the outer
|
|||
// system to get printed and trigger a failure.
|
|||
loop {} |
|||
} |
@ -1,20 +0,0 @@ |
|||
{ |
|||
"arch": "x86_64", |
|||
"cpu": "x86-64", |
|||
"data-layout": "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128", |
|||
"features": "+sse4.2,+avx,+fma,+popcnt", |
|||
"dynamic-linking": true, |
|||
"has-thread-local": true, |
|||
"is-builtin": false, |
|||
"llvm-target": "x86_64-unknown-linux-gnu", |
|||
"max-atomic-width": 64, |
|||
"os": "minwasmtime", |
|||
"position-independent-executables": true, |
|||
"panic-strategy": "abort", |
|||
"frame-pointer": "always", |
|||
"relro-level": "full", |
|||
"stack-probes": { |
|||
"kind": "inline" |
|||
}, |
|||
"target-pointer-width": "64" |
|||
} |
Loading…
Reference in new issue