This tool generates Go bindings for a chosen WIT world.
If changes need to be made to the go.bytecodealliance.org/pkg files referenced by the generated bindings, here are the steps that need to be taken:
- Make the required changes to the bytecodealliance/go-pkg Go files and tag a release.
- Update the
crates/go/src/pkggit submodule to reflect the most-recent release ofgo-pkg. - Update the
REMOTE_PKG_VERSIONconstant in lib.rs to reflect the most-recent release ofgo-pkg. - Make the required changes to
wit-bindgen-go.
The easiest way to use wit-bindgen-go is through the componentize-go tool. See below for using wit-bindgen-go directly.
To generate bindings with this crate, issue the go subcommand to wit-bindgen:
$ wit-bindgen go [OPTIONS] <WIT>See the output of wit-bindgen help go for available options.
This command will generate a variable number of files, depending on the WIT world provided:
go.mod: defines a minimal Go module with the namewit_component- You can replace this with your own version (e.g. referencing third party dependencies) if desired
wit_bindings.go: defines themainpackage for the module, including low-level,//go:export-annotated entrypoint functions corresponding to exported functions- These entrypoint functions in turn call high-level functions which must be provided by the application developer
<name>/wit_bindings.go: defines any types generated for the interface named<name>(orwit_worldfor WIT types defined at the world level), plus any imported functions- Note that the types placed in these files include all types for both imported and exported interfaces, except for exported resource types and any types which depend on exported resource types
export_<name>/wit_bindings.go: defines intrinsics for use with any exported resource types generated for the interface named<name>(orwit_worldfor WIT types defined at the world level), plus any types which depend on those exported resource types, plus any exported functions- The exported resource type definitions must be provided by the application developer
- The
export_<name>package is also the place to define any exported functions
The generated files will reference the following files in the bytecodealliance/go-pkg repository:
go.bytecodealliance.org/pkg/wit/runtime: defines low-level functions for supporting the component model ABIgo.bytecodealliance.org/pkg/wit/types(if needed):- defines
Tuple<N>types as required by the WIT world - defines an
Optiontype as required by the WIT world - defines a
Resulttype as required by the WIT world - defines a
Unittype as required by the WIT world - defines a
StreamReaderandStreamWritertypes as required by the WIT world - defines a
FutureReaderandFutureWritertypes as required by the WIT world
- defines
go.bytecodealliance.org/pkg/wit/async(if needed): defines low-level functions for integrating the Go scheduler with the component model async ABI
Note that async support currently requires a patched version of Go. Code generated for worlds that don't use any async features can be compiled using a stock release of Go.
wit-bindgenwasm-toolswasmtimecurlbashor similar
Given the following WIT file, we can generate bindings for it, write code to target the two worlds, and finally compose, build, and run the components.
cat >world.wit <<EOF
package test:test;
interface foo {
record thing {
a: s32,
b: string,
}
echo: func(x: thing) -> tuple<s32, string>;
}
world test {
export foo;
}
world runner {
import foo;
export run: func() -> tuple<s32, string>;
}
EOF
curl -OL https://github.com/bytecodealliance/wasmtime/releases/download/v39.0.1/wasi_snapshot_preview1.reactor.wasm
mkdir test runner
pushd test
wit-bindgen go -w test ../world.wit
mkdir export_test_test_foo
cat >export_test_test_foo/test.go <<EOF
package export_test_test_foo
import . "wit_component/test_test_foo"
func Echo(x Thing) (int32, string) {
return x.A, x.B
}
EOF
go mod tidy
GOARCH="wasm" GOOS="wasip1" go build -o core.wasm -buildmode=c-shared -ldflags=-checklinkname=0
wasm-tools component embed -w test ../world.wit core.wasm -o core-with-wit.wasm
wasm-tools component new --adapt ../wasi_snapshot_preview1.reactor.wasm core-with-wit.wasm -o component.wasm
popd
pushd runner
wit-bindgen go -w runner ../world.wit
mkdir export_wit_world
cat >export_wit_world/runner.go <<EOF
package export_wit_world
import . "wit_component/test_test_foo"
func Run() (int32, string) {
return Echo(Thing{42, "hello, world!"})
}
EOF
go mod tidy
GOARCH="wasm" GOOS="wasip1" go build -o core.wasm -buildmode=c-shared -ldflags=-checklinkname=0
wasm-tools component embed -w runner ../world.wit core.wasm -o core-with-wit.wasm
wasm-tools component new --adapt ../wasi_snapshot_preview1.reactor.wasm core-with-wit.wasm -o component.wasm
popd
wasm-tools compose -d test/component.wasm runner/component.wasm -o component.wasm
wasmtime run --invoke 'run()' component.wasmIf all goes well, you should see (42, "hello, world!").