Browse Source

wasi-adapter: Implement provider crate that embeds the adapter binaries (#8792)

* wasi-adapter: Implement provider crate that embeds the adapter binaries

* Upgrade wasi adapters to the latest version

* Update adapter docs

* Recompile asi adapters with 1.78

* Recompile wasi adapters with 1.79

* Add some debugging to adapter build script

* Fix script debugging

* Compute wasi adapter version based on latest adapter commit hash

* Try to bless wasi adapters again

* Try to work around CI auto-merges

* Revert to just using workspace version

* Add the wasi adapter provider to the crate publication list

* Use wasi adapter provider in artifacts test + explicit MSRV in CI

* Explicit adapter crate version

* Small fix

* Remove version info from adapter metadata

* Check but don't install rust toolchain in build script

* Bless after rebase

---------

Co-authored-by: Alex Crichton <alex@alexcrichton.com>
pull/8836/head
Juniper Tyree 5 months ago
committed by GitHub
parent
commit
2dbf8f15b3
No known key found for this signature in database GPG Key ID: B5690EEEBB952194
  1. 14
      .github/workflows/main.yml
  2. 5
      Cargo.lock
  3. 2
      Cargo.toml
  4. 60
      ci/build-wasi-preview1-component-adapter.sh
  5. 1
      crates/test-programs/artifacts/Cargo.toml
  6. 58
      crates/test-programs/artifacts/build.rs
  7. 1
      crates/wasi-preview1-component-adapter/Cargo.toml
  8. 19
      crates/wasi-preview1-component-adapter/provider/Cargo.toml
  9. BIN
      crates/wasi-preview1-component-adapter/provider/artefacts/wasi_snapshot_preview1.command.wasm
  10. BIN
      crates/wasi-preview1-component-adapter/provider/artefacts/wasi_snapshot_preview1.proxy.wasm
  11. BIN
      crates/wasi-preview1-component-adapter/provider/artefacts/wasi_snapshot_preview1.reactor.wasm
  12. 51
      crates/wasi-preview1-component-adapter/provider/src/lib.rs
  13. 4
      scripts/publish.rs

14
.github/workflows/main.yml

@ -793,8 +793,16 @@ jobs:
- uses: actions/checkout@v4
with:
submodules: true
- uses: ./.github/actions/install-rust
- run: rustup target add wasm32-wasi wasm32-unknown-unknown
- name: Install Rust version
run: |
RUST_VERSION=$( \
grep '^rust-version\s*=' crates/wasi-preview1-component-adapter/Cargo.toml | \
sed 's/rust-version.*=.*\"\(.*\)\"/\1/' \
)
rustup toolchain install $RUST_VERSION --profile minimal
rustup target add wasm32-wasi wasm32-unknown-unknown --toolchain $RUST_VERSION
echo RUSTUP_TOOLCHAIN=$RUST_VERSION >> "$GITHUB_ENV"
- name: Install wasm-tools
run: |
@ -802,8 +810,6 @@ jobs:
echo `pwd`/wasm-tools-1.0.27-x86_64-linux >> $GITHUB_PATH
- run: ./ci/build-wasi-preview1-component-adapter.sh
env:
VERSION: ${{ github.sha }}
- uses: actions/upload-artifact@v4
with:

5
Cargo.lock

@ -2762,6 +2762,7 @@ version = "0.0.0"
dependencies = [
"cargo_metadata",
"heck 0.4.0",
"wasi-preview1-component-adapter-provider",
"wasmtime",
"wit-component",
]
@ -3190,6 +3191,10 @@ dependencies = [
"wit-bindgen-rust-macro",
]
[[package]]
name = "wasi-preview1-component-adapter-provider"
version = "23.0.0"
[[package]]
name = "wasm-bindgen"
version = "0.2.87"

2
Cargo.toml

@ -138,6 +138,7 @@ members = [
"crates/environ/fuzz",
"crates/test-programs",
"crates/wasi-preview1-component-adapter",
"crates/wasi-preview1-component-adapter/provider",
"crates/wasi-preview1-component-adapter/verify",
"examples/fib-debug/wasm",
"examples/wasi/wasm",
@ -204,6 +205,7 @@ wiggle = { path = "crates/wiggle", version = "=23.0.0", default-features = false
wiggle-macro = { path = "crates/wiggle/macro", version = "=23.0.0" }
wiggle-generate = { path = "crates/wiggle/generate", version = "=23.0.0" }
wasi-common = { path = "crates/wasi-common", version = "=23.0.0", default-features = false }
wasi-preview1-component-adapter-provider = { path = "crates/wasi-preview1-component-adapter/provider", version = "23.0.0", default-features = false }
wasmtime-fuzzing = { path = "crates/fuzzing" }
wasmtime-jit-icache-coherence = { path = "crates/jit-icache-coherence", version = "=23.0.0" }
wasmtime-wit-bindgen = { path = "crates/wit-bindgen", version = "=23.0.0" }

60
ci/build-wasi-preview1-component-adapter.sh

@ -7,6 +7,25 @@ verify="cargo run -p verify-component-adapter --"
debug="target/wasm32-unknown-unknown/debug/wasi_snapshot_preview1.wasm"
release="target/wasm32-unknown-unknown/release/wasi_snapshot_preview1.wasm"
# The rust version that the adapter is built with is the crate's MSRV
RUST_VERSION=$( \
grep '^rust-version\s*=' crates/wasi-preview1-component-adapter/Cargo.toml | \
sed 's/rust-version.*=.*\"\(.*\)\"/\1/' \
)
if [[ $(rustc --version | grep $RUST_VERSION | wc -c) -eq 0 ]]; then
set +x
echo "The adapter is being built with a different Rust version than its"
echo "MSRV"
echo ""
echo " current rust version: $(rustc --version)"
echo " MSRV: $RUST_VERSION"
echo ""
echo "Please rerun this script with Rust version $RUST_VERSION, or update"
echo "the adapter's MSRV in its Cargo.toml file"
exit 1
fi
# Debug build, default features (reactor)
$build_adapter
$verify $debug
@ -15,20 +34,43 @@ $verify $debug
$build_adapter --no-default-features --features command
$verify $debug
compare() {
input=$1
flavor=$2
$verify $input
name=wasi_snapshot_preview1.$flavor.wasm
dst=$(dirname $input)/$name
reference=crates/wasi-preview1-component-adapter/provider/artefacts/$name
wasm-tools metadata add --name "wasi_preview1_component_adapter.$flavor.adapter" $input \
-o $dst
set +x
if [ "$BLESS" = "1" ]; then
cp $dst $reference
elif ! cmp -s $dst $reference; then
echo "Reference copy of adapter is not the same as the generated copy of"
echo "the adapter"
echo ""
echo " reference copy: $reference"
echo " built copy: $dst"
echo ""
echo "To automatically update the reference copy set \`BLESS=1\` in the"
echo "environment"
diff -u <(wasm-tools print $reference) <(wasm-tools print $dst)
exit 1
else
echo "Reference copy of adapter matches local copy"
fi
set -x
}
# Release build, command
$build_adapter --release --no-default-features --features command
$verify $release
wasm-tools metadata add --name "wasi_preview1_component_adapter.command.adapter:${VERSION}" $release \
-o target/wasm32-unknown-unknown/release/wasi_snapshot_preview1.command.wasm
compare $release command
# Release build, default features (reactor)
$build_adapter --release
$verify $release
wasm-tools metadata add --name "wasi_preview1_component_adapter.reactor.adapter:${VERSION}" $release \
-o target/wasm32-unknown-unknown/release/wasi_snapshot_preview1.reactor.wasm
compare $release reactor
# Release build, proxy
$build_adapter --release --no-default-features --features proxy
$verify $release
wasm-tools metadata add --name "wasi_preview1_component_adapter.proxy.adapter:${VERSION}" $release \
-o target/wasm32-unknown-unknown/release/wasi_snapshot_preview1.proxy.wasm
compare $release proxy

1
crates/test-programs/artifacts/Cargo.toml

@ -14,5 +14,6 @@ wasmtime = { workspace = true, features = ['incremental-cache', 'cranelift', 'co
[build-dependencies]
heck = { workspace = true }
wasi-preview1-component-adapter-provider = { workspace = true }
wit-component = { workspace = true }
cargo_metadata = "0.18.1"

58
crates/test-programs/artifacts/build.rs

@ -13,18 +13,6 @@ fn main() {
fn build_and_generate_tests() {
let out_dir = PathBuf::from(env::var_os("OUT_DIR").unwrap());
let reactor_adapter = build_adapter(&out_dir, "reactor", &[]);
let command_adapter = build_adapter(
&out_dir,
"command",
&["--no-default-features", "--features=command"],
);
let proxy_adapter = build_adapter(
&out_dir,
"proxy",
&["--no-default-features", "--features=proxy"],
);
println!("cargo:rerun-if-changed=../src");
// Build the test programs:
@ -94,9 +82,13 @@ fn build_and_generate_tests() {
continue;
}
let adapter = match target.as_str() {
"reactor" => &reactor_adapter,
s if s.starts_with("api_proxy") => &proxy_adapter,
_ => &command_adapter,
"reactor" => {
wasi_preview1_component_adapter_provider::WASI_SNAPSHOT_PREVIEW1_REACTOR_ADAPTER
}
s if s.starts_with("api_proxy") => {
wasi_preview1_component_adapter_provider::WASI_SNAPSHOT_PREVIEW1_PROXY_ADAPTER
}
_ => wasi_preview1_component_adapter_provider::WASI_SNAPSHOT_PREVIEW1_COMMAND_ADAPTER,
};
let path = compile_component(&wasm, adapter);
generated_code += &format!("pub const {camel}_COMPONENT: &'static str = {path:?};\n");
@ -116,37 +108,6 @@ fn build_and_generate_tests() {
std::fs::write(out_dir.join("gen.rs"), generated_code).unwrap();
}
// Build the WASI Preview 1 adapter, and get the binary:
fn build_adapter(out_dir: &PathBuf, name: &str, features: &[&str]) -> Vec<u8> {
println!("cargo:rerun-if-changed=../../wasi-preview1-component-adapter");
let mut cmd = cargo();
cmd.arg("build")
.arg("--release")
.arg("--package=wasi-preview1-component-adapter")
.arg("--target=wasm32-unknown-unknown")
.env("CARGO_TARGET_DIR", out_dir)
.env("RUSTFLAGS", rustflags())
.env_remove("CARGO_ENCODED_RUSTFLAGS");
for f in features {
cmd.arg(f);
}
eprintln!("running: {cmd:?}");
let status = cmd.status().unwrap();
assert!(status.success());
let adapter = out_dir.join(format!("wasi_snapshot_preview1.{name}.wasm"));
std::fs::copy(
out_dir
.join("wasm32-unknown-unknown")
.join("release")
.join("wasi_snapshot_preview1.wasm"),
&adapter,
)
.unwrap();
println!("wasi {name} adapter: {:?}", &adapter);
fs::read(&adapter).unwrap()
}
fn rustflags() -> &'static str {
match option_env!("RUSTFLAGS") {
// If we're in CI which is denying warnings then deny warnings to code
@ -164,7 +125,10 @@ fn compile_component(wasm: &Path, adapter: &[u8]) -> PathBuf {
.module(module.as_slice())
.unwrap()
.validate(true)
.adapter("wasi_snapshot_preview1", adapter)
.adapter(
wasi_preview1_component_adapter_provider::WASI_SNAPSHOT_PREVIEW1_ADAPTER_NAME,
adapter,
)
.unwrap()
.encode()
.expect("module can be translated to a component");

1
crates/wasi-preview1-component-adapter/Cargo.toml

@ -1,6 +1,7 @@
[package]
name = "wasi-preview1-component-adapter"
version.workspace = true
rust-version = "1.77.0"
authors.workspace = true
edition.workspace = true
publish = false

19
crates/wasi-preview1-component-adapter/provider/Cargo.toml

@ -0,0 +1,19 @@
[package]
name = "wasi-preview1-component-adapter-provider"
version.workspace = true
authors.workspace = true
description = "Embedded wasi-preview1-component-adapter binaries"
license = "Apache-2.0 WITH LLVM-exception"
repository = "https://github.com/bytecodealliance/wasmtime"
documentation = "https://docs.rs/wasi-preview1-component-adapter-provider/"
categories = ["wasm"]
keywords = ["webassembly", "wasm"]
edition.workspace = true
[lints]
workspace = true
[package.metadata.docs.rs]
all-features = true
[dependencies]

BIN
crates/wasi-preview1-component-adapter/provider/artefacts/wasi_snapshot_preview1.command.wasm

Binary file not shown.

BIN
crates/wasi-preview1-component-adapter/provider/artefacts/wasi_snapshot_preview1.proxy.wasm

Binary file not shown.

BIN
crates/wasi-preview1-component-adapter/provider/artefacts/wasi_snapshot_preview1.reactor.wasm

Binary file not shown.

51
crates/wasi-preview1-component-adapter/provider/src/lib.rs

@ -0,0 +1,51 @@
//! This crate contains the binaries of three WebAssembly modules:
//!
//! - [`WASI_SNAPSHOT_PREVIEW1_REACTOR_ADAPTER`]
//! - [`WASI_SNAPSHOT_PREVIEW1_COMMAND_ADAPTER`]
//! - [`WASI_SNAPSHOT_PREVIEW1_PROXY_ADAPTER`]
//!
//! These three modules bridge the wasip1 ABI to the wasip2 ABI of the component
//! model.
//!
//! They can be given to the [`wit_component::ComponentEncoder::adapter`]
//! method, using the [`WASI_SNAPSHOT_PREVIEW1_ADAPTER_NAME`], to translate a
//! module from the historical WASM ABI to the canonical ABI.
//!
//! [`wit_component::ComponentEncoder::adapter`]: https://docs.rs/wit-component/latest/wit_component/struct.ComponentEncoder.html#method.adapter
/// The name of the adapters in this crate, which may be provided to
/// [`wit_component::ComponentEncoder::adapter`].
///
/// [`wit_component::ComponentEncoder::adapter`]: https://docs.rs/wit-component/latest/wit_component/struct.ComponentEncoder.html#method.adapter
pub const WASI_SNAPSHOT_PREVIEW1_ADAPTER_NAME: &str = "wasi_snapshot_preview1";
/// The "reactor" adapter provides the default adaptation from preview1 to
/// preview2.
///
/// This adapter implements the [`wasi:cli/imports`] world.
///
/// [`wasi:cli/imports`]: https://github.com/WebAssembly/WASI/blob/01bb90d8b66cbc1d50349aaaab9ac5b143c9c98c/preview2/cli/imports.wit
pub const WASI_SNAPSHOT_PREVIEW1_REACTOR_ADAPTER: &[u8] =
include_bytes!("../artefacts/wasi_snapshot_preview1.reactor.wasm");
/// The "command" adapter extends the ["reactor" adapter] and additionally
/// exports a `run` function entrypoint.
///
/// This adapter implements the [`wasi:cli/command`] world.
///
/// ["reactor" adapter]: WASI_SNAPSHOT_PREVIEW1_REACTOR_ADAPTER
/// [`wasi:cli/command`]: https://github.com/WebAssembly/WASI/blob/01bb90d8b66cbc1d50349aaaab9ac5b143c9c98c/preview2/cli/command.wit
pub const WASI_SNAPSHOT_PREVIEW1_COMMAND_ADAPTER: &[u8] =
include_bytes!("../artefacts/wasi_snapshot_preview1.command.wasm");
/// The "proxy" adapter provides implements a HTTP proxy which is more
/// restricted than the ["reactor" adapter] adapter, as it lacks filesystem,
/// socket, environment, exit, and terminal support, but includes HTTP handlers
/// for incoming and outgoing requests.
///
/// This adapter implements the [`wasi:http/proxy`] world.
///
/// ["reactor" adapter]: WASI_SNAPSHOT_PREVIEW1_REACTOR_ADAPTER
/// [`wasi:http/proxy`]: https://github.com/WebAssembly/WASI/blob/01bb90d8b66cbc1d50349aaaab9ac5b143c9c98c/preview2/http/proxy.wit
pub const WASI_SNAPSHOT_PREVIEW1_PROXY_ADAPTER: &[u8] =
include_bytes!("../artefacts/wasi_snapshot_preview1.proxy.wasm");

4
scripts/publish.rs

@ -73,6 +73,8 @@ const CRATES_TO_PUBLISH: &[&str] = &[
"wasmtime-cli-flags",
"wasmtime-explorer",
"wasmtime-cli",
// wasi component adapter
"wasi-preview1-component-adapter-provider",
];
// Anything **not** mentioned in this array is required to have an `=a.b.c`
@ -109,6 +111,8 @@ const PUBLIC_CRATES: &[&str] = &[
// This is a dependency of cranelift crates and as a result can't break in
// patch releases as well
"wasmtime-types",
// wasi component adapter
"wasi-preview1-component-adapter-provider",
];
const C_HEADER_PATH: &str = "./crates/c-api/include/wasmtime.h";

Loading…
Cancel
Save