Getting started¶
Work in progress
This page is a draft. It describes Burroughs as of its latest release and may change. Where it disagrees with the engine's own documentation or CHANGELOG, those win.
Written against v0.12.0. The transcripts below are generated by this site's CI, which builds the burroughs CLI
at the latest release tag and runs each session in examples/cli/. Blocks labelled as fragments are not run by it.
Requirements¶
- Go 1.26 or newer. The module's
go.modsaysgo 1.26, which is the language floor. It also carriestoolchain go1.26.9. That line only applies when you build inside the Burroughs repository, where its Makefile pins it exactly. As a dependency of your module, your own toolchain is used. - No cgo, no C toolchain. The engine imports only the Go standard library.
- 64-bit Linux or macOS. These are what CI tests. Windows runs the tests in a separate CI workflow that is measured, not a gate, so treat it as unsupported.
Add it to a module¶
$ go mod init example.com/fetch
$ go get github.com/scttfrdmn/burroughs@v0.12.0
go: downloading github.com/scttfrdmn/burroughs v0.12.0
go: added github.com/scttfrdmn/burroughs v0.12.0
The package is burroughs, imported as github.com/scttfrdmn/burroughs. Everything public is in that one package.
Everything under internal/ is engine and not API.
Get the CLI¶
Build a binary, or run it without installing:
$ go install github.com/scttfrdmn/burroughs/cmd/burroughs@v0.12.0
$ go run github.com/scttfrdmn/burroughs/cmd/burroughs@v0.12.0 version
Either way, burroughs version prints:
$ burroughs version
burroughs v0.0.1 — the machine Burroughs never built
Known issue: the banner says v0.0.1 (#1130)
The version banner is a fixed string in cmd/burroughs/main.go, not the module version, so it has said
v0.0.1 at every release so far, including v0.12.0. To find out which version you have, look at your
go.mod or run go version -m $(which burroughs).
Your first module¶
Save this as calc.wat:
(module
(global $calls (export "calls") (mut i32) (i32.const 0))
(func $bump (global.set $calls (i32.add (global.get $calls) (i32.const 1))))
(func (export "add") (param i32 i32) (result i32)
(call $bump)
(i32.add (local.get 0) (local.get 1)))
(func (export "mul64") (param i64 i64) (result i64)
(call $bump)
(i64.mul (local.get 0) (local.get 1)))
(func (export "hypot") (param f64 f64) (result f64)
(f64.sqrt (f64.add (f64.mul (local.get 0) (local.get 0)) (f64.mul (local.get 1) (local.get 1)))))
(func (export "divmod") (param i32 i32) (result i32 i32)
(i32.div_s (local.get 0) (local.get 1))
(i32.rem_s (local.get 0) (local.get 1)))
(func (export "boom") unreachable))
Burroughs reads binary modules (.wasm) only. The engine contains a WAT parser, but it is internal and neither
the CLI nor the API exposes it. Assemble with any WAT assembler. These docs used wasm-tools 1.258.0:
$ wasm-tools parse calc.wat -o calc.wasm
(This site's examples/embed-core/calc.wasm is that output, committed. The engine repository also ships examples/add/add.wasm, already assembled, if you want to skip this step.)
List the exports, then call some. In these transcripts, [exit N] is the CLI's exit status when it is not 0:
$ burroughs run calc.wasm
add
mul64
hypot
divmod
boom
$ burroughs run calc.wasm add i32:2 i32:40
i32:42
$ burroughs run calc.wasm divmod i32:17 i32:5
i32:3 i32:2
$ burroughs run calc.wasm hypot f64:3 f64:4
f64:5
$ burroughs run calc.wasm divmod i32:1 i32:0
burroughs: trap: integer divide by zero
[exit 4]
$ burroughs run calc.wasm add 1 2
burroughs: "1" has no type prefix — values are spelled `i32:42`, `f64:nan`, `extern:3`, `null:func`
[exit 1]
Arguments are typed: i32:42, not 42. The last command shows an untyped value being refused.
A result is printed in the same spelling an argument takes, so you can feed one back in as the other.
The same thing from Go¶
wasm, err := os.ReadFile("calc.wasm")
if err != nil {
log.Fatal(err)
}
in, err := burroughs.Instantiate(wasm)
if err != nil {
log.Fatal(err)
}
res, err := in.Call("add", burroughs.I32(2), burroughs.I32(40))
if err != nil {
log.Fatal(err)
}
fmt.Println(res[0].Int32()) // 42
Tutorial 1 builds this out into a complete program. The embedding guide covers the whole API.
What burroughs run does with a file¶
run looks at the file and picks one of three paths. You do not choose the path:
- A component runs its
wasi:cli/runexport, with its arguments after--. A flag that cannot apply to a component is refused by name (see the CLI reference). - A WASI preview 1 command (it imports
wasi_snapshot_preview1and exports_start) runs as a program. Its arguments go after--, and its exit code becomes the CLI's. If it imports"burroughs" "spawn", it can start its own threads. - Anything else is a core module. It is instantiated, and then either its exports are listed or the function you name is called.
The CLI reference has every flag and exit code.