I'm trying to write WAT (WebAssembly Text Format) to understand WebAssembly better. I'd like to perform some I/O operations and I was able to find that importing "wasi_snapshot_preview1" "fd_write" let's you write to stdout. I'd like to learn how to use wasi 0.2 as well, but I'm having trouble finding the namespace used for it. I know I am missing something, and it's probably somewhere in you documentation or source code.
Stdout is handled through the wasi:cli/stdout
interface, in conjunction with wasi:io
's output-stream
resource. For hand-written code you'd probably be most interested in the blocking-write-and-flush
method which avoids a lot of complexity around non-blocking operations.
Lann Martin said:
Stdout is handled through the
wasi:cli/stdout
interface, in conjunction withwasi:io
'soutput-stream
resource. For hand-written code you'd probably be most interested in theblocking-write-and-flush
method which avoids a lot of complexity around non-blocking operations.
Thank you for the reply. However, I could not figure it out. Maybe I am missing something obvious, but I can't figure out how to write the import statement for those functions. I tried a variety of version of something like:
(module $test
(import "wasi:cli/stdout" "get-stdout" (func ...))
)
And more for the "blocking-write-and-flush" function you mentioned. I'm sorry if I'm missing something obvious. I've tried to look at the wit documentation and wat documentation, but I don't think I understand it well enough.
one perhaps useful bit of context here is that unlike WASIp1 the WASIp2 proposals (e.g. wasi 0.2) are defined in terms of the component model, not core wasm. That means that unlike WASIp1 there isn't a single definition you can do in core wasm.
Tooling conventions are in place, however, to be able to convert a core wasm module from core wasm to a component. This involves some understanding of components and the translations being made here though. One thing you can try out is to use wasm-tools component embed --dummy ./wit
to explore what core wasm can do. That emits a core wasm module which uses the world definition within ./wit
. If you've got a copy of wasi:cli
then you can pass --world wasi:cli/command
(or something similar to that) to generate a core wasm module that has access to all of the various imports. You probably don't need everything so you can trim it down to what you want.
As to what all the parameters/results are, that's where the canonical ABI of the component model kicks in
So for example if you check out this repo and run wasm-tools component embed --dummy ./wit --world command -t
then you should see something like:
(module
;; ...
(import "cm32p2|wasi:cli/environment@0.2" "get-environment" (func (;0;) (type 0)))
(import "cm32p2|wasi:cli/environment@0.2" "get-arguments" (func (;1;) (type 0)))
;; ...
(import "cm32p2|wasi:io/streams@0.2" "[method]output-stream.blocking-write-and-flush" (func (;17;) (type 5)))
;; ...
(import "cm32p2|wasi:cli/stdin@0.2" "get-stdin" (func (;27;) (type 7)))
(import "cm32p2|wasi:cli/stdout@0.2" "get-stdout" (func (;28;) (type 7)))
(import "cm32p2|wasi:cli/stderr@0.2" "get-stderr" (func (;29;) (type 7)))
;; ...
(memory (;0;) 0)
(export "cm32p2|wasi:cli/run@0.2|run" (func 136))
(export "cm32p2_memory" (memory 0))
(func (;136;) (type 7) (result i32)
unreachable
)
;; ...
You can sort of edit and fill in the skeleton with raw *.wat
if you'd like
that can then turn into a component with wasm-tools component new
so for example this module:
(module
(import "cm32p2|wasi:io/streams@0.2" "[method]output-stream.blocking-write-and-flush" (func $blocking-write-and-flush (param i32 i32 i32 i32)))
(import "cm32p2|wasi:cli/stdout@0.2" "get-stdout" (func $get-stdout (result i32)))
(func (export "cm32p2|wasi:cli/run@0.2|run") (result i32)
(call $blocking-write-and-flush
(call $get-stdout)
(i32.const 100)
(i32.const 6)
(i32.const 200))
(i32.const 0)
)
(memory (export "cm32p2_memory") 1)
(data (i32.const 100) "hello\n")
)
runs like so:
$ wasm-tools component embed ./wit --world command foo.wat -o foo.core.wasm
$ wasm-tools component new foo.core.wasm -o foo.component.wasm
$ wasmtime run foo.wasm
hello
Alex Crichton said:
one perhaps useful bit of context here is that unlike WASIp1 the WASIp2 proposals (e.g. wasi 0.2) are defined in terms of the component model, not core wasm. That means that unlike WASIp1 there isn't a single definition you can do in core wasm.
Tooling conventions are in place, however, to be able to convert a core wasm module from core wasm to a component. This involves some understanding of components and the translations being made here though. One thing you can try out is to use
wasm-tools component embed --dummy ./wit
to explore what core wasm can do. That emits a core wasm module which uses the world definition within./wit
. If you've got a copy ofwasi:cli
then you can pass--world wasi:cli/command
(or something similar to that) to generate a core wasm module that has access to all of the various imports. You probably don't need everything so you can trim it down to what you want.As to what all the parameters/results are, that's where the canonical ABI of the component model kicks in
Some things you mentioned went over my head ;) But I got wasi 2 up and running now so thank you! I'm a little confused about one thing though. I'm mostly interested in WebAssembly for its cross compatibility, but I see now that our names for the same modules are slightly different. My "cmp32p2|wasi:io/streams@0.2" is called "wasi:io/stream@0.2.2". So, would my compiled "foo.component.wasm" work on your machine?
For more component-related docs if you're interested I'd recommend browsing these docs, but otherwise:
My "cmp32p2|wasi:io/streams@0.2" is called "wasi:io/stream@0.2.2". So, would my compiled "foo.component.wasm" work on your machine?
Yes, this has to do with how versions work in component runtimes and how core wasm is wrapped up into components, but the general idea is that it shoudl all work out ok
Alex Crichton said:
For more component-related docs if you're interested I'd recommend browsing these docs, but otherwise:
My "cmp32p2|wasi:io/streams@0.2" is called "wasi:io/stream@0.2.2". So, would my compiled "foo.component.wasm" work on your machine?
Yes, this has to do with how versions work in component runtimes and how core wasm is wrapped up into components, but the general idea is that it shoudl all work out ok
Nice! The .wasm file works on both of my computers. There is a lot to unpack in these final .wasm files. I would ask more questions, but it's probably best if I read the docs for component syntax first. Thank you for your help.
Last updated: Dec 23 2024 at 13:07 UTC