bytecodealliance / bytecodealliance/wasmtime
wasmtime-wasi: `p1` cannot be used without `wasmtime/async`, requiring a C toolchain for sync-only embedders
- Dominant language
- Rust
- Stars
- 18.6k
- Forks
- 1.8k
- Avg merge
- 1d 18h
- Merged PRs (30d)
- 126
Description
### Summary
`wasmtime-wasi`'s `p1` feature cannot be enabled without also enabling `wasmtime/async`, which pulls in `wasmtime-internal-fiber` and therefore requires a working C toolchain. Embedders that use only the synchronous WASIp1 API pay that cost for a capability they never touch.
### The chain
In `wasmtime-wasi` 48.0.1:
```toml
[features]
default = ["p1", "p2"]
p0 = ["p1"]
p1 = ["dep:wiggle", "p2"]
p2 = ["wasmtime/component-model", "wasmtime/async"]
```
`p1` requires `p2`, and `p2` enables `wasmtime/async`. In `wasmtime` 48.0.1:
```toml
async = [
"dep:wasmtime-fiber",
"wasmtime-component-macro?/async",
"runtime",
]
```
And `wasmtime-internal-fiber` 48.0.1 ships `src/windows.c`, compiled through `cc` in its build script. So enabling `p1` transitively makes a pure-Rust build into one that needs a C compiler.
There is no feature combination that avoids this: `default-features = false, features = ["p1"]` still reaches `wasmtime/async` through `p2`.
### Why this is surprising
`p1`'s own module documentation describes the relationship as incidental rather than semantic:
> Support for WASIp1 is built on top of support for WASIp2 available at [the crate root](crate), but that's just an internal implementation detail.
And `p1` offers `add_to_linker_sync` alongside `add_to_linker_async`, so a fully synchronous embedder is a first-class supported use case. Our embedding uses `p1::add_to_linker_sync` and contains no `call_async` or `async_support` anywhere, yet still requires fibers.
### Concrete impact
We distribute a compiler toolchain that embeds Wasmtime to run WASIp1 guest modules. On Windows the fiber dependency turns "download our release and run it" into "download our release and also install Visual Studio Build Tools or MinGW-w64", solely to build a feature we never call. For a language toolchain trying to offer a self-contained install, that is a significant prerequisite to inherit from an unused code path.
This is not Windows-specific in principle — it is a C toolchain requirement for every sync-only embedder on every host — but Windows is where it is most visible, because a C compiler is not present by default.
### Request
Could `p1` be usable without `wasmtime/async`? Two shapes that would work, without preference between them:
- Split `p2` so `wasmtime/component-model` and `wasmtime/async` can be enabled independently, letting `p1` depend only on the former.
- Give `wasmtime-wasi` an `async` feature, default-on for compatibility, that `default-features = false` can switch off, with `add_to_linker_async` gated behind it.
If the `p1` → `p2` → `async` path is load-bearing rather than incidental, that would be useful to know too — we would then document the C toolchain as a permanent prerequisite rather than waiting on it.
### Happy to help
We have a native Windows x64 environment set up and can test a patch on both the sync path and the removal of the C-compiler requirement.
### Versions
Observed on `wasmtime-wasi` 48.0.1 and `wasmtime` 48.0.1; the same relationship holds in 46.0.3 and 47.0.4. In 36.x the coupling was even tighter — `async` was hardcoded in `[dependencies.wasmtime]` rather than feature-gated — so this has already improved, and the remaining step is the `p1` → `p2` edge.
Contributor guide
Research direction
Start by inspecting the wasmtime-wasi and wasmtime Cargo feature definitions for the p1 → p2 → async chain, then trace how add_to_linker_sync and add_to_linker_async are gated. Verify feature resolution for a sync-only embedder without a C toolchain. Done means p1 remains usable synchronously without enabling async while existing default and async behavior remains compatible.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- rust, wasm
- Domain
- build-system, developer-experience
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 55/100