Skip to content

wasmtime-wasi: p1 cannot be used without wasmtime/async, requiring a C toolchain for sync-only embedders #14288

Description

@dannymeijer

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:

[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:

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, 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.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions