This repository contains the various WebAssembly Interface Types files used by the Rune project.
The underlying idea behind WIT is that an API author will use a *.wit
file to
define the interface for how a WebAssembly module will interact with the outside
world. Anyone wanting to comply with that interface can take a copy of the
*.wit
file and run it through a code generator like wit-bindgen
to generate
the appropriate language bindings.
If you have used Protocol Buffers before, *.wit
is roughly analogous to a
*.proto
file.
The wit-bindgen
CLI tool can be installed directly from GitHub.
$ cargo install --git https://github.com/bytecodealliance/wit-bindgen wit-bindgen-cli
Once wit-bindgen
is installed, you will need to add this repository as a git
submodule.
$ git submodule add [email protected]:hotg-ai/wit-files.git
If you are writing a Rust crate that will be compiled to WebAssembly, you can
have the bindings automatically generated by a procedural macro by adding the
wit-bindgen-rust
crate as a dependency.
$ cargo add --git https://github.com/bytecodealliance/wit-bindgen wit-bindgen-rust
Inside your crate, you can now use the wit_bindgen_rust::import!()
macro to
generate bindings to functions provided by the host.
The wit_bindgen_rust::export!()
macro will generate a trait that is used
to expose your crate's functionality to the outside world. You will need to
provide an implementation of this trait.
// lib.rs
wit_bindgen_rust::import!("../wit-files/rune/runtime-v1.wit");
wit_bindgen_rust::export!("../wit-files/rune/rune-v1.wit");
pub struct Exports;
impl rune_v1::RuneV1 for Exports { ... }
We've published a JavaScript package to NPM called @hotg-ai/rune-wit-files
which contains the generated bindings for loading a WebAssembly module. The
package's source code is available in the rune/js/
folder.
The package's yarn build
script will automatically generate any necessary glue
code and compile it to a single bundle that can be published to NPM.
Under the hood, this script will first run the wit-bindgen
CLI...
$ cd rune/js/
$ wit-bindgen js --export ../runtime-v1.wit --import ../rune-v1.wit --out-dir ./bindings
Generating "bindings/intrinsics.js"
Generating "bindings/rune-v1.d.ts"
Generating "bindings/rune-v1.js"
Generating "bindings/runtime-v1.d.ts"
Generating "bindings/runtime-v1.js"
Next, it uses Parcel to generate a single release bundle...
$ ./node_modules/.bin/parcel build
✨ Built in 818ms
dist/index.js 11.12 KB 20ms
dist/index.d.ts 114 B 8ms
Done in 1.02s.
$ tree dist
dist
├── index.d.ts
├── index.d.ts.map
├── index.js
└── index.js.map
0 directories, 4 files
Finally, because Parcel doesn't generate a single typings file when from the
multiple generated *.d.ts
files, we create the typings file ourselves by
concatenating each of the generated typings files.
$ cat bindings/*.d.ts > dist/index.d.ts
To make inspecting metadata a bit easier, we've created a React app that lets you upload a WebAssembly binary and extract its metadata.
You build this app similar to most React apps.
$ cd rune/inspect/
$ yarn
yarn install v1.22.17
[1/4] Resolving packages...
[2/4] Fetching packages...
[3/4] Linking dependencies...
[4/4] Building fresh packages...
Done in 1.66s.
$ yarn start
yarn run v1.22.17
$ parcel serve index.html
Server running at http://localhost:1234
✨ Built in 397ms
Note: if you see errors saying
@hotg-ai/rune-wit-files
couldn't be imported, you may need to build the JavaScript bindings first.$ cd rune/js/ && yarn && yarn build