github.com/tetratelabs/wazero@v1.7.3-0.20240513003603-48f702e154b5/imports/wasi_snapshot_preview1/example/cat.go (about) 1 package main 2 3 import ( 4 "context" 5 "embed" 6 "fmt" 7 "io/fs" 8 "log" 9 "os" 10 11 "github.com/tetratelabs/wazero" 12 "github.com/tetratelabs/wazero/imports/wasi_snapshot_preview1" 13 "github.com/tetratelabs/wazero/sys" 14 ) 15 16 // catFS is an embedded filesystem limited to test.txt 17 // 18 //go:embed testdata/test.txt 19 var catFS embed.FS 20 21 // catWasmCargoWasi was compiled from testdata/cargo-wasi/cat.rs 22 // 23 //go:embed testdata/cargo-wasi/cat.wasm 24 var catWasmCargoWasi []byte 25 26 // catWasmTinyGo was compiled from testdata/tinygo/cat.go 27 // 28 //go:embed testdata/tinygo/cat.wasm 29 var catWasmTinyGo []byte 30 31 // catWasmZig was compiled from testdata/zig/cat.zig 32 // 33 //go:embed testdata/zig/cat.wasm 34 var catWasmZig []byte 35 36 // catWasmZigCc was compiled from testdata/zig-cc/cat.c 37 // 38 //go:embed testdata/zig-cc/cat.wasm 39 var catWasmZigCc []byte 40 41 // main writes an input file to stdout, just like `cat`. 42 // 43 // This is a basic introduction to the WebAssembly System Interface (WASI). 44 // See https://github.com/WebAssembly/WASI 45 func main() { 46 // Choose the context to use for function calls. 47 ctx := context.Background() 48 49 // Create a new WebAssembly Runtime. 50 r := wazero.NewRuntime(ctx) 51 defer r.Close(ctx) // This closes everything this Runtime created. 52 53 // Since wazero uses fs.FS, we can use standard libraries to do things like trim the leading path. 54 rooted, err := fs.Sub(catFS, "testdata") 55 if err != nil { 56 log.Panicln(err) 57 } 58 59 // Combine the above into our baseline config, overriding defaults. 60 config := wazero.NewModuleConfig(). 61 // By default, I/O streams are discarded and there's no file system. 62 WithStdout(os.Stdout).WithStderr(os.Stderr).WithFS(rooted) 63 64 // Instantiate WASI, which implements system I/O such as console output. 65 wasi_snapshot_preview1.MustInstantiate(ctx, r) 66 67 // Choose the binary we want to test. Most compilers that implement WASI 68 // are portable enough to use binaries interchangeably. 69 var catWasm []byte 70 toolchain := os.Getenv("TOOLCHAIN") 71 switch toolchain { 72 case "": 73 fallthrough // default to TinyGo 74 case "cargo-wasi": 75 catWasm = catWasmCargoWasi 76 case "tinygo": 77 catWasm = catWasmTinyGo 78 case "zig": 79 catWasm = catWasmZig 80 case "zig-cc": 81 catWasm = catWasmZigCc 82 default: 83 log.Panicln("unknown toolchain", toolchain) 84 } 85 86 // InstantiateModule runs the "_start" function, WASI's "main". 87 // * Set the program name (arg[0]) to "wasi"; arg[1] should be "/test.txt". 88 if _, err = r.InstantiateWithConfig(ctx, catWasm, config.WithArgs("wasi", os.Args[1])); err != nil { 89 // Note: Most compilers do not exit the module after running "_start", 90 // unless there was an error. This allows you to call exported functions. 91 if exitErr, ok := err.(*sys.ExitError); ok && exitErr.ExitCode() != 0 { 92 fmt.Fprintf(os.Stderr, "exit_code: %d\n", exitErr.ExitCode()) 93 } else if !ok { 94 log.Panicln(err) 95 } 96 } 97 }