Skip to content

Commit

Permalink
Update WASI bindings to 0.2.0 and the component model (#72)
Browse files Browse the repository at this point in the history
* Remove old wasi-ephemeral/witx-bindgen crates

* Copy WIT files from Wasmtime

* Update to WASI 0.2.0 bindings

* Update some manifest fields

* Add a small example

* CI tweaks

* Install wit-bindgen on CI

* Specify versions of wasmtime/wasm-tools on CI

* Fix wit-bindgen-cli install

* Flag wit/deps as generated as well

* Fix yml syntax

* Fix wasmtime tag

* Update README
  • Loading branch information
alexcrichton authored Feb 8, 2024
1 parent 9ec04a7 commit d2ba9f4
Show file tree
Hide file tree
Showing 54 changed files with 19,156 additions and 3,385 deletions.
5 changes: 5 additions & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# This is generated by `wit-bindgen`
src/bindings.rs linguist-generated=true

# This is copied from other repos so diffs aren't super interesting by default
wit/deps linguist-generated=true
32 changes: 20 additions & 12 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,36 +9,44 @@ jobs:
matrix:
rust: [stable, beta, nightly]
steps:
- uses: actions/checkout@v1
with:
submodules: true
- uses: actions/checkout@v4
- name: Install Rust
run: rustup update ${{ matrix.rust }} && rustup default ${{ matrix.rust }} && rustup component add rustfmt
- run: rustup target add wasm32-wasi
- run: cargo build
- run: cargo build --no-default-features
- run: cargo build --target wasm32-wasi
- run: cargo build --target wasm32-wasi --no-default-features
- run: cargo build -p wasi-ephemeral
- name: Install Wasmtime
uses: bytecodealliance/actions/wasmtime/setup@v1
with:
version: "v17.0.0"
- name: Install wasm-tools
uses: bytecodealliance/actions/wasm-tools/setup@v1
with:
version: "1.0.57"
- run: cargo build --examples --target wasm32-wasi
- run: curl -LO https://github.com/bytecodealliance/wasmtime/releases/download/v17.0.0/wasi_snapshot_preview1.command.wasm
- run: wasm-tools component new ./target/wasm32-wasi/debug/examples/hello-world.wasm --adapt ./wasi_snapshot_preview1.command.wasm -o component.wasm
- run: wasmtime run component.wasm


rustfmt:
name: Rustfmt
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v1
with:
submodules: true
- uses: actions/checkout@v4
- name: Install Rust
run: rustup update stable && rustup default stable && rustup component add rustfmt
- run: cargo fmt -- --check

generate:
name: Test Generated Code
name: Ensure generated code up-to-date
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v1
with:
submodules: true
- uses: actions/checkout@v4
- name: Install Rust
run: rustup update stable && rustup default stable
- run: cargo test -p witx-bindgen
- run: cargo install wit-bindgen-cli@0.16.0
- run: ./ci/regenerate.sh
- run: git diff --exit-code
3 changes: 0 additions & 3 deletions .gitmodules
Original file line number Diff line number Diff line change
@@ -1,3 +0,0 @@
[submodule "crates/witx-bindgen/WASI"]
path = crates/witx-bindgen/WASI
url = https://github.com/WebAssembly/WASI
11 changes: 5 additions & 6 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,20 +1,19 @@
[package]
name = "wasi"
version = "0.11.0+wasi-snapshot-preview1"
version = "0.12.0+wasi-0.2.0"
authors = ["The Cranelift Project Developers"]
license = "Apache-2.0 WITH LLVM-exception OR Apache-2.0 OR MIT"
description = "Experimental WASI API bindings for Rust"
edition = "2018"
description = "WASI API bindings for Rust"
edition = "2021"
categories = ["no-std", "wasm"]
keywords = ["webassembly", "wasm"]
repository = "https://github.com/bytecodealliance/wasi"
readme = "README.md"
documentation = "https://docs.rs/wasi"

[workspace]
members = ['crates/witx-bindgen', 'crates/wasi-ephemeral']

[dependencies]
wit-bindgen = { version = "0.16", default-features = false, features = ['realloc'] }

# When built as part of libstd
compiler_builtins = { version = "0.1", optional = true }
core = { version = "1.0", optional = true, package = "rustc-std-workspace-core" }
Expand Down
88 changes: 51 additions & 37 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,74 +14,88 @@
</p>
</div>

This crate contains API bindings for [WASI](https://github.com/WebAssembly/WASI)
system calls in Rust, and currently reflects the `wasi_snapshot_preview1`
module. This crate is quite low-level and provides conceptually a "system call"
interface. In most settings, it's better to use the Rust standard library, which
has WASI support.
This crate contains bindings for [WASI](https://github.com/WebAssembly/WASI)
APIs for the worlds:

The `wasi` crate is also entirely procedurally generated from the `*.witx` files
describing the WASI apis. While some conveniences are provided the bindings here
are intentionally low-level!
* [`wasi:cli/command`]
* [`wasi:http/proxy`]

This crate is procedurally generated from [WIT] files using [`wit-bindgen`].

[`wasi:cli/command`]: https://github.com/WebAssembly/wasi-cli
[`wasi:http/proxy`]: https://github.com/WebAssembly/wasi-http
[WIT]: https://component-model.bytecodealliance.org/design/wit.html
[`wit-bindgen`]: https://github.com/bytecodealliance/wit-bindgen
[components]: https://component-model.bytecodealliance.org/
[`wasm-tools`]: https://github.com/bytecodealliance/wasm-tools

# Usage

First you can depend on this crate via `Cargo.toml`:

```toml
[dependencies]
wasi = "0.8.0"
wasi = "0.12.0"
```

Next you can use the APIs in the root of the module like so:

```rust
fn main() {
let stdout = 1;
let message = "Hello, World!\n";
let data = [wasi::Ciovec {
buf: message.as_ptr(),
buf_len: message.len(),
}];
wasi::fd_write(stdout, &data).unwrap();
let stdout = wasi::cli::stdout::get_stdout();
stdout.blocking_write_and_flush(b"Hello, world!\n").unwrap();
}
```

Next you can use a tool like [`cargo
wasi`](https://github.com/bytecodealliance/cargo-wasi) to compile and run your
project:
This crate is intended to target [components] but today you need to go through
the intermediate build step of a core WebAssembly module using the `wasm32-wasi`
target:

To compile Rust projects to wasm using WASI, use the `wasm32-wasi` target,
like this:
```
$ cargo build --target wasm32-wasi
```

Next you'll want an "adapter" to convert the Rust standard library's usage of
`wasi_snapshot_preview1` to the component model. An example adapter can be found
from [Wasmtime's release page](https://github.com/bytecodealliance/wasmtime/releases/download/v17.0.0/wasi_snapshot_preview1.command.wasm).

```
$ cargo wasi run
Compiling wasi v0.8.0+wasi-snapshot-preview1
Compiling wut v0.1.0 (/code)
Finished dev [unoptimized + debuginfo] target(s) in 0.34s
Running `/.cargo/bin/cargo-wasi target/wasm32-wasi/debug/wut.wasm`
Running `target/wasm32-wasi/debug/wut.wasm`
Hello, World!
$ curl -LO https://github.com/bytecodealliance/wasmtime/releases/download/v17.0.0/wasi_snapshot_preview1.command.wasm
```

# Development
Next to create a component you'll use the [`wasm-tools`] CLI to create a
component:

The bulk of the `wasi` crate is generated by the `witx-bindgen` tool, which lives at
`crates/witx-bindgen` and is part of the cargo workspace.
```
$ cargo install wasm-tools
$ wasm-tools component new target/wasm32-wasi/debug/foo.wasm \
--adapt ./wasi_snapshot_preview1.command.wasm \
-o component.wasm
```

The `src/lib_generated.rs` file can be re-generated with the following
command:
And finally the component can be run by a runtime that has Component Model
support, such as [Wasmtime]:

```
cargo run -p witx-bindgen -- crates/witx-bindgen/WASI/phases/snapshot/witx/wasi_snapshot_preview1.witx > src/lib_generated.rs
$ wasmtime run component.wasm
Hello, world!
```

Note that this uses the WASI standard repository as a submodule. If you do not
have this submodule present in your source tree, run:
[Wasmtime]: https://github.com/bytecodealliance/wasmtime

# Development

The bulk of the `wasi` crate is generated by the [`wit-bindgen`] tool. The
`src/bindings.rs` file can be regenerated with:

```
git submodule update --init
$ ./ci/regenerate.sh
```

WASI definitions are located in the `wit` directory of this repository.
Currently they're copied from upstream repositories but are hoped to be better
managed in the future.

# License

This project is licensed under the Apache 2.0 license with the LLVM exception.
Expand Down
15 changes: 15 additions & 0 deletions ci/regenerate.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
#!/bin/sh

set -ex

wit-bindgen rust wit --out-dir src --std-feature

# rustfmt chokes on the raw output of wit-bindgen right now due to trailling
# whitespace (unsure as to why), so format it with some options first to get it
# into a better state before applying the final format with default options
# which gets this to succeed.
#
# NB: this should be considered a bug in wit-bindgen that this is required to do
# twice. Passing `--rustfmt` to `wit-bindgen` should work.
rustfmt src/bindings.rs --edition 2021 --config-path ./ci/rustfmt-bindings.toml
rustfmt src/bindings.rs --edition 2021
2 changes: 2 additions & 0 deletions ci/rustfmt-bindings.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
max_width = 100
tab_spaces = 2
21 changes: 0 additions & 21 deletions crates/wasi-ephemeral/Cargo.toml

This file was deleted.

18 changes: 0 additions & 18 deletions crates/wasi-ephemeral/README.md

This file was deleted.

34 changes: 0 additions & 34 deletions crates/wasi-ephemeral/build.rs

This file was deleted.

31 changes: 0 additions & 31 deletions crates/wasi-ephemeral/src/lib.rs

This file was deleted.

17 changes: 0 additions & 17 deletions crates/witx-bindgen/Cargo.toml

This file was deleted.

9 changes: 0 additions & 9 deletions crates/witx-bindgen/README.md

This file was deleted.

1 change: 0 additions & 1 deletion crates/witx-bindgen/WASI
Submodule WASI deleted from 0ba0c5
Loading

0 comments on commit d2ba9f4

Please sign in to comment.