Redirects users to tested example (#791)
Rather than clutter both the README and home page with details that can drift and have caused maintenance, this directs users to the tested basic example. This also adds a FAQ entry about TinyGo's main, thanks to @basvanbeek for the help. Signed-off-by: Adrian Cole <adrian@tetrate.io>
This commit is contained in:
2
Makefile
2
Makefile
@@ -54,7 +54,7 @@ build.examples.as:
|
||||
build.examples.zig:
|
||||
@cd examples/allocation/zig/testdata/ && zig build -Drelease-small=true && mv zig-out/lib/greet.wasm .
|
||||
|
||||
tinygo_sources := examples/allocation/tinygo/testdata/greet.go imports/wasi_snapshot_preview1/example/testdata/tinygo/cat.go
|
||||
tinygo_sources := examples/basic/testdata/add.go examples/allocation/tinygo/testdata/greet.go imports/wasi_snapshot_preview1/example/testdata/tinygo/cat.go
|
||||
.PHONY: build.examples.tinygo
|
||||
build.examples.tinygo: $(tinygo_sources)
|
||||
@for f in $^; do \
|
||||
|
||||
66
README.md
66
README.md
@@ -15,69 +15,9 @@ Import wazero and extend your Go application with code written in any language!
|
||||
|
||||
## Example
|
||||
|
||||
The best way to learn wazero is by trying one of our [examples](examples).
|
||||
|
||||
For the impatient, here's a peek of a general flow with wazero:
|
||||
|
||||
First, you need to compile your code into the WebAssembly Binary Format (Wasm).
|
||||
|
||||
Here's source in [TinyGo](https://wazero.io/languages/tinygo), which exports an
|
||||
"add" function:
|
||||
```go
|
||||
package main
|
||||
|
||||
//export add
|
||||
func add(x, y uint32) uint32 {
|
||||
return x + y
|
||||
}
|
||||
```
|
||||
|
||||
Here's the minimal command to build a `%.wasm` binary.
|
||||
```bash
|
||||
tinygo build -o add.wasm -target=wasi add.go
|
||||
```
|
||||
|
||||
Finally, you can run that inside your Go application.
|
||||
```go
|
||||
func main() {
|
||||
// Choose the context to use for function calls.
|
||||
ctx := context.Background()
|
||||
|
||||
// Read a WebAssembly binary containing an exported "add" function.
|
||||
wasm, err := os.ReadFile("./path/to/add.wasm")
|
||||
if err != nil {
|
||||
log.Panicln(err)
|
||||
}
|
||||
|
||||
// Create a new WebAssembly Runtime.
|
||||
r := wazero.NewRuntimeWithConfig(ctx, wazero.NewRuntimeConfig().
|
||||
// WebAssembly 2.0 allows use of any version of TinyGo, including 0.24+.
|
||||
WithWasmCore2())
|
||||
defer r.Close(ctx) // This closes everything this Runtime created.
|
||||
|
||||
// Instantiate WASI, which implements system I/O such as console output.
|
||||
if _, err = wasi_snapshot_preview1.Instantiate(ctx, r); err != nil {
|
||||
log.Panicln(err)
|
||||
}
|
||||
|
||||
// Instantiate the module and return its exported functions
|
||||
module, err := r.InstantiateModuleFromBinary(ctx, wasm)
|
||||
if err != nil {
|
||||
log.Panicln(err)
|
||||
}
|
||||
|
||||
// Discover 1+2=3
|
||||
fmt.Println(module.ExportedFunction("add").Call(ctx, 1, 2))
|
||||
}
|
||||
```
|
||||
|
||||
Notes:
|
||||
|
||||
* The embedding application is often called the "host" in WebAssembly.
|
||||
* The Wasm binary is often called the "guest" in WebAssembly. Sometimes they
|
||||
need [imports][imports] to implement features such as console output.
|
||||
* Many languages compile to (target) Wasm including AssemblyScript, C, C++,
|
||||
Rust, TinyGo and Zig!
|
||||
The best way to learn wazero is by trying one of our [examples](examples). The
|
||||
most [basic example](examples/basic) extends a Go application with an addition
|
||||
function defined in WebAssembly.
|
||||
|
||||
## Deeper dive
|
||||
|
||||
|
||||
@@ -1,48 +1,62 @@
|
||||
package wazero
|
||||
package wazero_test
|
||||
|
||||
import (
|
||||
"context"
|
||||
_ "embed"
|
||||
"fmt"
|
||||
"log"
|
||||
|
||||
"github.com/tetratelabs/wazero"
|
||||
"github.com/tetratelabs/wazero/imports/wasi_snapshot_preview1"
|
||||
)
|
||||
|
||||
// addWasm was generated by the following:
|
||||
//
|
||||
// cd examples/basic/testdata/testdata; wat2wasm --debug-names add.wat
|
||||
// cd examples/basic/testdata; tinygo build -o add.wasm -target=wasi add.go
|
||||
//
|
||||
//go:embed examples/basic/testdata/add.wasm
|
||||
var addWasm []byte
|
||||
|
||||
// This is an example of how to use WebAssembly via adding two numbers.
|
||||
// This is an example of how to extend a Go application with an addition
|
||||
// function defined in WebAssembly.
|
||||
//
|
||||
// See https://github.com/tetratelabs/wazero/tree/main/examples for more.
|
||||
// Since addWasm was compiled with TinyGo's `wasi` target, we need to configure
|
||||
// WASI host imports.
|
||||
//
|
||||
// A complete project that does the same as this is available here:
|
||||
// https://github.com/tetratelabs/wazero/tree/main/examples/basic
|
||||
func Example() {
|
||||
// Choose the context to use for function calls.
|
||||
ctx := context.Background()
|
||||
|
||||
// Create a new WebAssembly Runtime.
|
||||
r := NewRuntime(ctx)
|
||||
r := wazero.NewRuntimeWithConfig(ctx, wazero.NewRuntimeConfig().
|
||||
// WebAssembly 2.0 allows use of any version of TinyGo, including 0.24+.
|
||||
WithWasmCore2())
|
||||
defer r.Close(ctx) // This closes everything this Runtime created.
|
||||
|
||||
// Add a module to the runtime named "wasm/math" which exports one function
|
||||
// "add", implemented in WebAssembly.
|
||||
// Instantiate WASI, which implements host functions needed for TinyGo to
|
||||
// implement `panic`.
|
||||
if _, err := wasi_snapshot_preview1.Instantiate(ctx, r); err != nil {
|
||||
log.Panicln(err)
|
||||
}
|
||||
|
||||
// Instantiate the guest Wasm into the same runtime. It exports the `add`
|
||||
// function, implemented in WebAssembly.
|
||||
mod, err := r.InstantiateModuleFromBinary(ctx, addWasm)
|
||||
if err != nil {
|
||||
log.Panicln(err)
|
||||
}
|
||||
defer mod.Close(ctx)
|
||||
|
||||
// Get a function that can be reused until its module is closed:
|
||||
add := mod.ExportedFunction("add")
|
||||
|
||||
// Call the `add` function and print the results to the console.
|
||||
x, y := uint64(1), uint64(2)
|
||||
results, err := add.Call(ctx, x, y)
|
||||
results, err := mod.ExportedFunction("add").Call(ctx, x, y)
|
||||
if err != nil {
|
||||
log.Panicln(err)
|
||||
}
|
||||
|
||||
fmt.Printf("%s: %d + %d = %d\n", mod.Name(), x, y, results[0])
|
||||
fmt.Printf("%d + %d = %d\n", x, y, results[0])
|
||||
|
||||
// Output:
|
||||
// wasm/math: 1 + 2 = 3
|
||||
// 1 + 2 = 3
|
||||
}
|
||||
|
||||
@@ -1,3 +1,36 @@
|
||||
## Basic example
|
||||
|
||||
This example shows how to use both WebAssembly and Go-defined functions with wazero.
|
||||
This example shows how to extend a Go application with an addition function
|
||||
defined in WebAssembly.
|
||||
|
||||
Ex.
|
||||
```bash
|
||||
$ go run add.go 7 9
|
||||
7 + 9 = 16
|
||||
```
|
||||
|
||||
### Compilation
|
||||
|
||||
wazero is a WebAssembly runtime, embedded in your host application. To run
|
||||
WebAssembly functions, you need access to a WebAssembly Binary (Wasm),
|
||||
typically a `%.wasm` file.
|
||||
|
||||
[add.wasm](testdata/add.wasm) was compiled from [add.go](testdata/add.go) with
|
||||
[TinyGo][1], as it is the most common way to compile Go source to Wasm. Here's
|
||||
the minimal command to build a `%.wasm` binary.
|
||||
|
||||
```bash
|
||||
cd testdata; tinygo build -o add.wasm -target=wasi add.go
|
||||
```
|
||||
|
||||
### Notes
|
||||
|
||||
* Many other languages compile to (target) Wasm including AssemblyScript, C,
|
||||
C++, Rust, and Zig!
|
||||
* The embedding application is often called the "host" in WebAssembly.
|
||||
* The Wasm binary is often called the "guest" in WebAssembly. Sometimes they
|
||||
need [imports](../../imports) to implement features such as console output.
|
||||
TinyGo's `wasi` target, requires [WASI][2] imports.
|
||||
|
||||
[1]: https://wazero.io/languages/tinygo
|
||||
[2]: https://wazero.io/specs/#wasi
|
||||
|
||||
@@ -9,26 +9,40 @@ import (
|
||||
"strconv"
|
||||
|
||||
"github.com/tetratelabs/wazero"
|
||||
"github.com/tetratelabs/wazero/imports/wasi_snapshot_preview1"
|
||||
)
|
||||
|
||||
// addWasm was generated by the following:
|
||||
//
|
||||
// cd testdata; wat2wasm --debug-names add.wat
|
||||
// cd testdata; tinygo build -o add.wasm -target=wasi add.go
|
||||
//
|
||||
//go:embed testdata/add.wasm
|
||||
var addWasm []byte
|
||||
|
||||
// main implements a basic function in both Go and WebAssembly.
|
||||
// main is an example of how to extend a Go application with an addition
|
||||
// function defined in WebAssembly.
|
||||
//
|
||||
// Since addWasm was compiled with TinyGo's `wasi` target, we need to configure
|
||||
// WASI host imports.
|
||||
func main() {
|
||||
// Choose the context to use for function calls.
|
||||
ctx := context.Background()
|
||||
|
||||
// Create a new WebAssembly Runtime.
|
||||
r := wazero.NewRuntime(ctx)
|
||||
r := wazero.NewRuntimeWithConfig(ctx, wazero.NewRuntimeConfig().
|
||||
// WebAssembly 2.0 allows use of any version of TinyGo, including 0.24+.
|
||||
WithWasmCore2())
|
||||
defer r.Close(ctx) // This closes everything this Runtime created.
|
||||
|
||||
// Add a module to the runtime named "wasm/math" which exports one function "add", implemented in WebAssembly.
|
||||
wasm, err := r.InstantiateModuleFromBinary(ctx, addWasm)
|
||||
// Instantiate WASI, which implements host functions needed for TinyGo to
|
||||
// implement `panic`.
|
||||
if _, err := wasi_snapshot_preview1.Instantiate(ctx, r); err != nil {
|
||||
log.Panicln(err)
|
||||
}
|
||||
|
||||
// Instantiate the guest Wasm into the same runtime. It exports the `add`
|
||||
// function, implemented in WebAssembly.
|
||||
mod, err := r.InstantiateModuleFromBinary(ctx, addWasm)
|
||||
if err != nil {
|
||||
log.Panicln(err)
|
||||
}
|
||||
@@ -36,14 +50,14 @@ func main() {
|
||||
// Read two args to add.
|
||||
x, y := readTwoArgs()
|
||||
|
||||
// Call the `add` function in the module and print the results to the console.
|
||||
add := wasm.ExportedFunction("add")
|
||||
// Call the `add` function and print the results to the console.
|
||||
add := mod.ExportedFunction("add")
|
||||
results, err := add.Call(ctx, x, y)
|
||||
if err != nil {
|
||||
log.Panicln(err)
|
||||
}
|
||||
|
||||
fmt.Printf("%s: %d + %d = %d\n", wasm.Name(), x, y, results[0])
|
||||
fmt.Printf("%d + %d = %d\n", x, y, results[0])
|
||||
}
|
||||
|
||||
func readTwoArgs() (uint64, uint64) {
|
||||
|
||||
@@ -12,6 +12,6 @@ import (
|
||||
// go run add.go 7 9
|
||||
func Test_main(t *testing.T) {
|
||||
stdout, _ := maintester.TestMain(t, main, "add", "7", "9")
|
||||
require.Equal(t, `wasm/math: 7 + 9 = 16
|
||||
require.Equal(t, `7 + 9 = 16
|
||||
`, stdout)
|
||||
}
|
||||
|
||||
10
examples/basic/testdata/add.go
vendored
Normal file
10
examples/basic/testdata/add.go
vendored
Normal file
@@ -0,0 +1,10 @@
|
||||
package main
|
||||
|
||||
//export add
|
||||
func add(x, y uint32) uint32 {
|
||||
return x + y
|
||||
}
|
||||
|
||||
// main is required for the `wasi` target, even if it isn't used.
|
||||
// See https://wazero.io/languages/tinygo/#why-do-i-have-to-define-main
|
||||
func main() {}
|
||||
BIN
examples/basic/testdata/add.wasm
vendored
BIN
examples/basic/testdata/add.wasm
vendored
Binary file not shown.
15
examples/basic/testdata/add.wat
vendored
15
examples/basic/testdata/add.wat
vendored
@@ -1,15 +0,0 @@
|
||||
(module
|
||||
;; Define the optional module name. '$' prefixing is a part of the text format.
|
||||
$wasm/math
|
||||
|
||||
;; add returns $x+$y.
|
||||
;;
|
||||
;; Notes:
|
||||
;; * The stack begins empty and anything left must match the result type.
|
||||
;; * export allows api.Module to return this via ExportedFunction("add")
|
||||
(func (export "add") (param $x i32) (param $y i32) (result i32)
|
||||
local.get $x ;; stack: [$x]
|
||||
local.get $y ;; stack: [$x, $y]
|
||||
i32.add ;; stack: [$x+$y]
|
||||
)
|
||||
)
|
||||
8
go.mod
8
go.mod
@@ -4,6 +4,8 @@ module github.com/tetratelabs/wazero
|
||||
// https://go.dev/doc/devel/release (1 version behind latest)
|
||||
go 1.18
|
||||
|
||||
// Retract the first tag, which had the wrong naming convention. Also, retract
|
||||
// the first beta as it had a memory bug and quickly fixed in v1.0.0-beta.2.
|
||||
retract [v1.0.0-beta1, v1.0.0-beta.1]
|
||||
// Wrong naming convention
|
||||
retract v1.0.0-beta1
|
||||
|
||||
// Has memory bug and quickly fixed in v1.0.0-beta.2.
|
||||
retract v1.0.0-beta.1
|
||||
|
||||
@@ -11,68 +11,9 @@ wazero is the only zero dependency WebAssembly runtime written in Go.
|
||||
|
||||
## Example
|
||||
|
||||
The best way to learn wazero is by trying one of our [examples][1]
|
||||
|
||||
For the impatient, here's a peek of a general flow with wazero:
|
||||
|
||||
First, you need to compile your code into the WebAssembly Binary Format (Wasm).
|
||||
|
||||
Here's source in [TinyGo]({{< ref "/languages/tinygo" >}}), which exports an
|
||||
"add" function:
|
||||
```go
|
||||
package main
|
||||
|
||||
//export add
|
||||
func add(x, y uint32) uint32 {
|
||||
return x + y
|
||||
}
|
||||
```
|
||||
|
||||
Here's the minimal command to build a `%.wasm` binary.
|
||||
```bash
|
||||
tinygo build -o add.wasm -target=wasi add.go
|
||||
```
|
||||
|
||||
Finally, you can run that inside your Go application.
|
||||
```go
|
||||
func main() {
|
||||
// Choose the context to use for function calls.
|
||||
ctx := context.Background()
|
||||
|
||||
// Read a WebAssembly binary containing an exported "add" function.
|
||||
wasm, err := os.ReadFile("./path/to/add.wasm")
|
||||
if err != nil {
|
||||
log.Panicln(err)
|
||||
}
|
||||
|
||||
// Create a new WebAssembly Runtime.
|
||||
r := wazero.NewRuntimeWithConfig(ctx, wazero.NewRuntimeConfig().
|
||||
// WebAssembly 2.0 allows use of any version of TinyGo, including 0.24+.
|
||||
WithWasmCore2())
|
||||
defer r.Close(ctx) // This closes everything this Runtime created.
|
||||
|
||||
// Instantiate WASI, which implements system I/O such as console output.
|
||||
if _, err = wasi_snapshot_preview1.Instantiate(ctx, r); err != nil {
|
||||
log.Panicln(err)
|
||||
}
|
||||
|
||||
// Instantiate the module and return its exported functions
|
||||
module, err := r.InstantiateModuleFromBinary(ctx, wasm)
|
||||
if err != nil {
|
||||
log.Panicln(err)
|
||||
}
|
||||
|
||||
// Discover 1+2=3
|
||||
fmt.Println(module.ExportedFunction("add").Call(ctx, 1, 2))
|
||||
}
|
||||
```
|
||||
|
||||
Notes:
|
||||
|
||||
* The Wasm binary is often called the "guest" in WebAssembly.
|
||||
* The embedding application is often called the "host" in WebAssembly.
|
||||
* Many languages compile to (target) Wasm including AssemblyScript, C, C++,
|
||||
Rust, TinyGo and Zig!
|
||||
The best way to learn wazero is by trying one of our [examples][1]. The
|
||||
most [basic example][2] extends a Go application with an addition function
|
||||
defined in WebAssembly.
|
||||
|
||||
## Why zero?
|
||||
|
||||
@@ -93,8 +34,9 @@ go get github.com/tetratelabs/wazero@main
|
||||
|
||||
wazero will release its first beta at the end of August 2022, and finalize
|
||||
1.0 once Go 1.20 is released in Feb 2023. Meanwhile, please practice the
|
||||
current APIs to ensure they work for you, and give us a [star][2] if you are
|
||||
current APIs to ensure they work for you, and give us a [star][3] if you are
|
||||
enjoying it so far!
|
||||
|
||||
[1]: https://github.com/tetratelabs/wazero/blob/main/examples
|
||||
[2]: https://github.com/tetratelabs/wazero/stargazers
|
||||
[2]: https://github.com/tetratelabs/wazero/blob/main/examples/basic
|
||||
[3]: https://github.com/tetratelabs/wazero/stargazers
|
||||
|
||||
@@ -33,6 +33,9 @@ package main
|
||||
func add(x, y uint32) uint32 {
|
||||
return x + y
|
||||
}
|
||||
|
||||
// main is required for the `wasi` target, even if it isn't used.
|
||||
func main() {}
|
||||
```
|
||||
|
||||
The following is the minimal command to build a `%.wasm` binary.
|
||||
@@ -334,6 +337,17 @@ it.
|
||||
|
||||
## Frequently Asked Questions
|
||||
|
||||
### Why do I have to define main?
|
||||
|
||||
If you are using TinyGo's `wasi` target, you should define at least a no-op
|
||||
`func main() {}` in your source.
|
||||
|
||||
If you don't, instantiation of the WebAssembly will fail unless you've exported
|
||||
the following from the host:
|
||||
```webassembly
|
||||
(func (import "env" "main.main") (param i32) (result i32))
|
||||
```
|
||||
|
||||
### How do I use json?
|
||||
TinyGo doesn't yet implement [reflection APIs][16] needed by `encoding/json`.
|
||||
Meanwhile, most users resort to non-reflective parsers, such as [gjson][17].
|
||||
|
||||
Reference in New Issue
Block a user