Stream: wasi

Topic: ✔ Runtime linking issues with wasip3 and nightly reactor


view this post on Zulip Joel Dice (Jun 05 2025 at 15:25):

mainrs said:

Compilation is done using cargo build --manifest-path wasm/Cargo.toml --target wasm32-wasip1 --release, followed by wasm-tools component new target/wasm32-wasip1/release/library.wasm --adapt wasi_snapshot_preview1.reactor.wasm --skip-validation -o component.wasm. As far as I understood, this should lift my component into p3.

As you discovered, it won't lift your component into p3. The wasi_snapshot_preview1.reactor.wasm adapter only adapts from p1 to p2 -- it has no p3 support yet, and there are no specific plans to add such support AFAIK. Additionally, wasi-libc (on which Rust's std is based when targeting wasm32-wasip{1,2}) does not yet have any support for p3, so any features you (or your crate dependencies) use from std will bottom out in p1 or p2 imports.

Regarding a hypothetical p1->p3 or p2->p3 adapter: such a thing would certainly be useful, but it's much less urgent than the existing p1->p2 adapter was. The p1->p2 transition involved switching from core wasm modules and the WITX ABI to the component model and its canonical ABI, which meant a host had no way to provide both p1 and p2 imports to a single binary, meaning an adapter was necessary to support any mix of the two. For p2->p3, the situation is much better: p3 (and the component model async ABI it relies on) is purely additive and can be considered a superset of p2. Therefore, a host can easily run a component that imports (and exports) a mix of p2 and p3 interfaces, so an adapter is not necessary.

Practically speaking, that means you have only one option for exporting the wasi:cli@0.3.0 world currently: either generate the bindings using wit-bindgen and use them directly in a lib crate (not a bin crate, which would require a main function and pull in wasi:cli@0.2.0) instead of using std to e.g. get environment variables.

Alternatively, you could modify your host embedding to add both the p2 and p3 imports from wasmtime-wasi to the Linker, which would allow the p2 imports pulled in by std to work, as well as any p3 imports your app uses. You'd still need to manually generate the wasi:cli/run@0.3.0 export in order to export a p3-compatible async run function, though.

Eventually, we'll add native p3 support to wasi-libc and Rust via a new wasm32-wasip3 target, at which point you'll be able to run the resulting components in a "pure" p3 host with no p2 support, but we're not there yet. Also, I'm not sure what async main would look like for such a target. @Alex Crichton might have thoughts.

view this post on Zulip Alex Crichton (Jun 05 2025 at 15:32):

Everything Joel said makes sense to me, and the only bits I'd add are that we're likely to do a p1->p3 adapter at some point (basically new builds of the current adapter) but as Joel mentions we don't have that allocated for someone to work on just yet (WASIp3 is currently a moving target). For async main man I haven't thought about that at all, but I think that might be something we could support in the wasi crate (e.g. #[wasi::main] async fn main() { ... } where eventually the wasi crate will switch to WASIp3 by default

view this post on Zulip mainrs (Jun 05 2025 at 15:45):

Thank you for the clarifications! That helped me out a lot in understanding what exactly these adapters are doing and why they have been created!
Regarding the async main question: wouldn't it be enough for #[wasi::main] to translate to a normal main function that spawns a blocking call to an async closure? I think I've seen such a function inside wit_bindgen::rt.

view this post on Zulip Joel Dice (Jun 05 2025 at 15:57):

mainrs said:

Regarding the async main question: wouldn't it be enough for #[wasi::main] to translate to a normal main function that spawns a blocking call to an async closure?

Technically, yes, that's possible, but it would prevent the host (or composed component) from making more than one concurrent call to that component instance. And maybe that's okay for a CLI-style app, but it would be more flexible to allow concurrent calls, which requires exporting an async function from the component.

view this post on Zulip Notification Bot (Jun 05 2025 at 16:00):

mainrs has marked this topic as resolved.

view this post on Zulip Alex Crichton (Jun 05 2025 at 16:00):

I'd definitely say that the current block_on calls in the wit-bindgen tests are more of a kludge and are not "the future"

view this post on Zulip Alex Crichton (Jun 05 2025 at 16:01):

native async support is definitely the way to go (eventually)


Last updated: Dec 06 2025 at 06:05 UTC