|
|
|
# Wasm3 Cookbook
|
|
|
|
|
|
|
|
## WASM module examples
|
|
|
|
|
|
|
|
### Rust WASI app
|
|
|
|
|
|
|
|
Create a new project:
|
|
|
|
```sh
|
|
|
|
$ cargo new --bin hello
|
|
|
|
$ cd hello
|
|
|
|
$ rustup target add wasm32-wasi
|
|
|
|
```
|
|
|
|
|
|
|
|
Build and run:
|
|
|
|
```sh
|
|
|
|
$ cargo build --release --target wasm32-wasi
|
|
|
|
|
|
|
|
$ wasm3 ./target/wasm32-wasi/release/hello.wasm
|
|
|
|
Hello, world!
|
|
|
|
```
|
|
|
|
|
|
|
|
### AssemblyScript WASI app
|
|
|
|
|
|
|
|
Create `hello.ts`:
|
|
|
|
```ts
|
|
|
|
import "wasi"
|
|
|
|
|
|
|
|
import {Console} from "as-wasi"
|
|
|
|
Console.log('Hello World!');
|
|
|
|
```
|
|
|
|
|
|
|
|
Create `package.json`:
|
|
|
|
```json
|
|
|
|
{
|
|
|
|
"name": "hello",
|
|
|
|
"version": "1.0.0",
|
|
|
|
"description": "Hello world with AssemblyScript and as-wasi",
|
|
|
|
"main": "hello.ts",
|
|
|
|
"scripts": {
|
|
|
|
"build": "asc hello.ts -b hello.wasm"
|
|
|
|
},
|
|
|
|
"devDependencies": {
|
|
|
|
"assemblyscript": "^0.18.30",
|
|
|
|
"as-wasi": "^0.4.4"
|
|
|
|
}
|
|
|
|
}
|
|
|
|
```
|
|
|
|
|
|
|
|
Build and run:
|
|
|
|
```sh
|
|
|
|
$ npm install
|
|
|
|
$ npm run build
|
|
|
|
|
|
|
|
$ wasm3 hello.wasm
|
|
|
|
Hello World!
|
|
|
|
```
|
|
|
|
|
|
|
|
### TinyGo WASI app
|
|
|
|
|
|
|
|
Create `hello.go`:
|
|
|
|
```go
|
|
|
|
package main
|
|
|
|
|
|
|
|
import "fmt"
|
|
|
|
|
|
|
|
func main() {
|
|
|
|
fmt.Printf("Hello, %s!\n", "world")
|
|
|
|
}
|
|
|
|
```
|
|
|
|
|
|
|
|
Build and run:
|
|
|
|
```sh
|
|
|
|
$ tinygo build -o hello.wasm -target wasi ./hello.go
|
|
|
|
|
|
|
|
$ wasm3 hello.wasm
|
|
|
|
Hello, world!
|
|
|
|
```
|
|
|
|
|
|
|
|
### Zig WASI app
|
|
|
|
|
|
|
|
Create `hello.zig`:
|
|
|
|
```zig
|
|
|
|
const std = @import("std");
|
|
|
|
|
|
|
|
pub fn main() !void {
|
|
|
|
const stdout = std.io.getStdOut().writer();
|
|
|
|
try stdout.print("Hello, {s}!\n", .{"world"});
|
|
|
|
}
|
|
|
|
```
|
|
|
|
|
|
|
|
Build and run:
|
|
|
|
```sh
|
|
|
|
$ zig build-exe -O ReleaseSmall -target wasm32-wasi hello.zig
|
|
|
|
|
|
|
|
$ wasm3 hello.wasm
|
|
|
|
Hello, world!
|
|
|
|
```
|
|
|
|
|
|
|
|
## Zig library
|
|
|
|
|
|
|
|
Create `add.zig`:
|
|
|
|
```zig
|
|
|
|
export fn add(a: i32, b: i32) i64 {
|
|
|
|
return a + b;
|
|
|
|
}
|
|
|
|
```
|
|
|
|
|
|
|
|
Build and run:
|
|
|
|
```sh
|
|
|
|
$ zig build-lib add.zig -O ReleaseSmall -target wasm32-freestanding
|
|
|
|
|
|
|
|
$ wasm3 --repl add.wasm
|
|
|
|
wasm3> add 1 2
|
|
|
|
Result: 3
|
|
|
|
```
|
|
|
|
|
|
|
|
### C/C++ WASI app
|
|
|
|
|
|
|
|
The easiest way to start is to use [Wasienv](https://github.com/wasienv/wasienv).
|
|
|
|
|
|
|
|
Create `hello.cpp`:
|
|
|
|
```cpp
|
|
|
|
#include <iostream>
|
|
|
|
int main() {
|
|
|
|
std::cout << "Hello, world!" << std::endl;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
```
|
|
|
|
|
|
|
|
Or `hello.c`:
|
|
|
|
```c
|
|
|
|
#include <stdio.h>
|
|
|
|
int main() {
|
|
|
|
printf("Hello, %s!\n", "world");
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
```
|
|
|
|
|
|
|
|
Build and run:
|
|
|
|
```sh
|
|
|
|
$ wasic++ -O3 hello.cpp -o hello.wasm
|
|
|
|
$ wasicc -O3 hello.c -o hello.wasm
|
|
|
|
|
|
|
|
$ wasm3 hello.wasm
|
|
|
|
Hello World!
|
|
|
|
```
|
|
|
|
|
|
|
|
Limitations:
|
|
|
|
- `setjmp/longjmp` and `C++ exceptions` are not available
|
|
|
|
- no support for `threads` and `atomics`
|
|
|
|
- no support for `dynamic libraries`
|
|
|
|
|
|
|
|
### WAT WASI app
|
|
|
|
|
|
|
|
Create `hello.wat`:
|
|
|
|
```wat
|
|
|
|
(module
|
|
|
|
;; wasi_unstable!fd_write(file_descriptor, *iovs, iovs_len, nwritten) -> status_code
|
|
|
|
(import "wasi_unstable" "fd_write" (func $fd_write (param i32 i32 i32 i32) (result i32)))
|
|
|
|
|
|
|
|
(memory 1)
|
|
|
|
(export "memory" (memory 0))
|
|
|
|
|
|
|
|
;; Put a message to linear memory at offset 32
|
|
|
|
(data (i32.const 32) "Hello, world\n")
|
|
|
|
|
|
|
|
(func $main (export "_start")
|
|
|
|
;; Create a new io vector
|
|
|
|
(i32.store (i32.const 0) (i32.const 32)) ;; iov.iov_base - pointer to the start of the message
|
|
|
|
(i32.store (i32.const 4) (i32.const 13)) ;; iov.iov_len - length of the message
|
|
|
|
|
|
|
|
(call $fd_write
|
|
|
|
(i32.const 1) ;; file_descriptor - 1 for stdout
|
|
|
|
(i32.const 0) ;; *iovs - pointer to the io vector
|
|
|
|
(i32.const 1) ;; iovs_len - count of items in io vector
|
|
|
|
(i32.const 20) ;; nwritten - where to store the number of bytes written
|
|
|
|
)
|
|
|
|
drop ;; discard the WASI status code
|
|
|
|
)
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
Build and run:
|
|
|
|
```sh
|
|
|
|
$ wat2wasm hello.wat -o hello.wasm
|
|
|
|
|
|
|
|
$ wasm3 hello.wasm
|
|
|
|
Hello, world!
|
|
|
|
```
|
|
|
|
|
|
|
|
### WAT library
|
|
|
|
|
|
|
|
Create `swap.wat`:
|
|
|
|
```wat
|
|
|
|
(module
|
|
|
|
(func (export "swap") (param i32 i32) (result i32 i32)
|
|
|
|
(get_local 1)
|
|
|
|
(get_local 0)
|
|
|
|
)
|
|
|
|
)
|
|
|
|
```
|
|
|
|
|
|
|
|
Build and run:
|
|
|
|
```sh
|
|
|
|
$ wat2wasm swap.wat -o swap.wasm
|
|
|
|
|
|
|
|
$ wasm3 --repl swap.wasm
|
|
|
|
wasm3> :invoke swap 123 456
|
|
|
|
Result: 456:i32, 123:i32
|
|
|
|
```
|