Ecosyste.ms: Awesome

An open API service indexing awesome lists of open source software.

Awesome Lists | Featured Topics | Projects

https://github.com/wasmerio/wasmer-go

πŸΉπŸ•ΈοΈ WebAssembly runtime for Go
https://github.com/wasmerio/wasmer-go

golang golang-library rust wasm webassembly

Last synced: 5 days ago
JSON representation

πŸΉπŸ•ΈοΈ WebAssembly runtime for Go

Awesome Lists containing this project

README

        



Wasmer logo


Wasmer Go





Build Status


License


Go Package


API Documentation


Website
β€’
Docs
β€’
Slack Channel


A complete and mature WebAssembly runtime for Go based on
[Wasmer](https://github.com/wasmerio/wasmer).

Features

* **Easy to use**: The `wasmer` API mimics the standard WebAssembly API,
* **Fast**: `wasmer` executes the WebAssembly modules as fast as
possible, close to **native speed**,
* **Safe**: All calls to WebAssembly will be fast, but more
importantly, completely safe and sandboxed.

**Documentation**: [browse the detailed API
documentation](https://pkg.go.dev/github.com/wasmerio/wasmer-go/wasmer)
full of examples.

**Examples** as tutorials: [browse the `examples/`
directory](https://github.com/wasmerio/wasmer-go/tree/master/examples),
it's the best place for a complete introduction!

# Install

To install the library, follow the classical:

```sh
$ go get github.com/wasmerio/wasmer-go/wasmer
```

And you're ready to get fun!

## Supported platforms

This library embeds the Wasmer runtime compiled as shared library
objects, and so uses [`cgo`](https://golang.org/cmd/cgo/) to consume
it. A set of precompiled shared library objects are provided. Thus
this library works (and is tested) on the following platforms:



Platform
Architecture
Triple
Status




Linux
amd64
x86_64-unknown-linux-gnu
βœ…


aarch64
aarch64-unknown-linux-gnu
βœ…


Darwin
amd64
x86_64-apple-darwin
βœ…


aarch64
aarch64-apple-darwin
⏳


Windows
amd64
x86_64-pc-windows-msvc
⏳

What to do if your platform is missing?

Up to now, there is no script to automate that process. [We are
working on it](https://github.com/wasmerio/wasmer-go/issues/191).

Here are the steps to do that manually:

```sh
$ # Build the new Wasmer C API shared object library.
$ cargo build --release
$
$ # Configure cgo.
$ export CGO_CFLAGS="-I$(pwd)/wasmer/packaged/include/"
$ export CGO_LDFLAGS="-Wl,-rpath,$(pwd)/target/release/ -L$(pwd)/target/release/ -lwasmer_go"
$
$ # Run the tests.
$ just test -tags custom_wasmer_runtime
```

# Examples

We highly recommend to read the
[`examples/`](https://github.com/wasmerio/wasmer-go/tree/master/examples)
directory, which contains a sequence of examples/tutorials. It's the
best place to learn by reading examples.

But for the most eager of you, there is a quick toy program in
`examples/appendices/simple.go`, written in Rust:

```rust
#[no_mangle]
pub extern "C" fn sum(x: i32, y: i32) -> i32 {
x + y
}
```

A compiled WebAssembly binary is included in
[`examples/appendices/simple.wasm`]((https://github.com/wasmerio/wasmer-go/blob/master/examples/appendices/simple.wasm)).

Then, we can execute it in Go:

```go
package main

import (
"fmt"
"os"
wasmer "github.com/wasmerio/wasmer-go/wasmer"
)

func main() {
wasmBytes, _ := os.ReadFile("simple.wasm")

engine := wasmer.NewEngine()
store := wasmer.NewStore(engine)

// Compiles the module
module, _ := wasmer.NewModule(store, wasmBytes)

// Instantiates the module
importObject := wasmer.NewImportObject()
instance, _ := wasmer.NewInstance(module, importObject)

// Gets the `sum` exported function from the WebAssembly instance.
sum, _ := instance.Exports.GetFunction("sum")

// Calls that exported function with Go standard values. The WebAssembly
// types are inferred and values are casted automatically.
result, _ := sum(5, 37)

fmt.Println(result) // 42!
}
```

And then, finally, enjoy by running:

```sh
$ cd examples/appendices/
$ go run simple.go
42
```

# Testing

Run the tests with the following command:

```sh
$ just test
```

# What is WebAssembly?

Quoting [the WebAssembly site](https://webassembly.org/):

> WebAssembly (abbreviated Wasm) is a binary instruction format for a
> stack-based virtual machine. Wasm is designed as a portable target
> for compilation of high-level languages like C/C++/Rust, enabling
> deployment on the web for client and server applications.

About speed:

> WebAssembly aims to execute at native speed by taking advantage of
> [common hardware
> capabilities](https://webassembly.org/docs/portability/#assumptions-for-efficient-execution)
> available on a wide range of platforms.

About safety:

> WebAssembly describes a memory-safe, sandboxed [execution
> environment](https://webassembly.org/docs/semantics/#linear-memory) […].

# License

The entire project is under the MIT License. Please read [the
`LICENSE` file][license].

[license]: https://github.com/wasmerio/wasmer/blob/master/LICENSE

# FAQ

## How to run Go programs compiled to WebAssembly modules with `wasmer-go`?

Let's start by emphasing that `wasmer-go` is a WebAssembly runtime. It
allows to _run_ WebAssembly inside Go. It's not a tool to _compile_ a
Go program into WebAssembly. Nonetheless, many people are reporting
issues when compiling Go programs to WebAssembly, and then trying to
run them with `wasmer-go` (or in another hosts, like
[Python](https://github.com/wasmerio/wasmer-python),
[C](https://github.com/wasmerio/wasmer/tree/master/lib/c-api),
[PHP](https://github.com/wasmerio/wasmer-php),
[Ruby](https://github.com/wasmerio/wasmer-ruby),
[Rust](https://github.com/wasmerio/wasmer)…).

The major problem is that, whilst the Go compiler supports
WebAssembly, [it does not support
WASI](https://github.com/golang/go/issues/31105) (WebAssembly System
Interface). It generates an ABI that is deeply tied to JavaScript, and
one needs to use the `wasm_exec.js` file provided by the Go toolchain,
which doesn't work outside a JavaScript host.

Fortunately, there are two solutions to this problem:

1. Use [TinyGo](https://tinygo.org) to compile your Go program to
WebAssembly with the `-target wasi` option, e.g.:

```sh
$ tinygo build -o module.wasm -target wasi .
```

The generated WebAssembly module will be portable across all
WebAssembly runtimes that support WASI.

2. Use the Go compiler with adapters. Let's see how to compile:

```sh
$ GOOS=js GOARCH=wasm go build -o module.wasm .
```

(the `GOOS=js` is the sign that JavaScript is targeted, not a surprise).

Then pick one adapter (they are written by the community):

* [`mattn/gowasmer`](https://github.com/mattn/gowasmer/),
* [`go-wasm-adapter/go-wasm`](https://github.com/go-wasm-adapter/go-wasm/),

and follow their documentation.

We highly recommend the first solution (with TinyGo) if it works for
you as the WebAssembly module will be portable across all WebAssembly
runtimes. It's not a hacky solution based on adapters; it's the right
way to… go.