olanod opened issue #10075:
From the docs
Not all features for Wasmtime can be built for custom targets. For example WASI support does not work on custom targets.
This is basically what I need, so I'd like to know(and possibly contribute) what would it take to add WASI support to the no_std version of Wasmtime.
I'm creating a simple "virtual OS" for embedded risc-v and a custom risc-v based VM and would like to run WASI programs on it. An initial MVP would be running a simple WASI component withwstd
that reads form stdin and write to stdout and another one that creates a service listening on a socket. The OS abstracts the concept of the filesystem or networking.
olanod edited issue #10075:
From the docs
Not all features for Wasmtime can be built for custom targets. For example WASI support does not work on custom targets.
This is basically what I need, so I'd like to know(and possibly contribute) what would it take to add WASI support to the no_std version of Wasmtime.
I'm creating a simple "virtual OS" for embedded risc-v and a custom risc-v based VM and would like to run WASI programs on it, the fact that programs need to be pre-compiled ahead of time is actually a plus as it allows distributing the binaries in the VM's format instead of WASM.
An initial MVP would be running a simple WASI component withwstd
that reads form stdin and write to stdout and another one that creates a service listening on a socket. The OS abstracts the concept of the filesystem or networking.
alexcrichton commented on issue #10075:
The documentation here more-or-less outlines why the
wasmtime-wasi
crate (andwasmtime-wasi-http
) don't compile on no_std platforms. They both currently have a hard requirement on thetokio
runtime which AFAIK has no "custom platform" support along similar lines as to Wasmtime.Unfortunately though there's not necessarily a super-small C API we can offer and say "implement this and you get all of WASI". What I might recommend instead is to avoid using the
wasmtime-wasi
crate entirely and build-your-own. Thewasmtime-wasi
crate, for example, is built exclusively on the public API of thewasmtime
crate which does build for no_std with custom platform support. This would mean that when building your own WASI implementation to run on your own custom OS you'd be usingLinker
yourself to add all your own functions and such.I'll note that this is also not the greatest state of things as reimplementing the
wasmtime-wasi
crate is a relatively significant undertaking. If you only want a few functions it might not be so bad but WASI has a relatively large surface area. That being said this large surface area is also why it's not feasible to provide a small/turnkey solution to a custom platform because there would be so many insertion points.If it works for your use case I might recommend providing only a few WASI interfaces and grow that set over time. For example you probably want
wasi:io
primitives and maybe others likewasi:clocks
andwasi:random
, and those shouldn't be too too hard to port to a custom platform implementation.Finally I'll also note that @pchickey is doing work to get
wasi:io
working on no_std so you might be interested in that as well.
pchickey commented on issue #10075:
Agree with Alex - its very hard to come up with a pluggable implementation of WASI that meets the needs of different platforms while still having enough in common across platforms to be worthwhile.
The wasmtime-wasi-io crate, which just landed in main, is a no_std implementation of the WASI poll function, and a set of traits for input-stream, output-stream, and pollable. Its just barely enough common ground for implementations to be worth having at all.
Once you have that, you still have to build up a lot of other functionality to be able to embed apps that use stdin/out, sockets, etc, and how you do so is heavily dependent on your underlying platform. My suggestion is to invoke
wasmtime::component::bindgen!
yourself withwith: { "wasi:io": wasmtime_wasi_io::bindings::wasi::io }
and then just start writing your own impl Hosts. There's a small amount of common boilerplate in most impl Hosts for handling ResourceTable manipulation, but abstracting that away ends up requiring manually writing a trait that basically looks like a HostSomeResource minus one argument, which is more of a burden to maintain as common infra than I think its worth. (But maybe its something you could add an option to bindgen to write for you, if you're motivated?)
pchickey edited a comment on issue #10075:
Agree with Alex - its very hard to come up with a pluggable implementation of WASI that meets the needs of different platforms while still having enough in common across platforms to be worthwhile.
The wasmtime-wasi-io crate, which just landed in main, is a no_std implementation of the WASI poll function, and a set of traits for input-stream, output-stream, and pollable. Its just barely enough common ground for implementations to be worth having at all.
Once you have that, you still have to build up a lot of other functionality to be able to embed apps that use stdin/out, sockets, etc, and how you do so is heavily dependent on your underlying platform. My suggestion is to invoke
wasmtime::component::bindgen!
yourself withwith: { "wasi:io": wasmtime_wasi_io::bindings::wasi::io }
and then just start writing your own impl Hosts. There's a small amount of common boilerplate in most impl Hosts for handling ResourceTable manipulation, but abstracting that away ends up requiring manually writing a trait that basically looks like a HostSomeResource minus one argument, which is more of a burden to maintain as common infra than I think its worth. (But maybe its something you could add an option to bindgen to write for you, if you're motivated?)At some point in the future I will add an example app that uses wasmtime-wasi-io to make a sample embedding, but right now I'm burning down other things on my critical path so that remains tech debt for today.
Last updated: Jan 24 2025 at 00:11 UTC