8bitworkshop icon indicating copy to clipboard operation
8bitworkshop copied to clipboard

Move to WASI for tool binaries

Open sehugg opened this issue 4 years ago • 0 comments

We've been using Emscripten, but WASI is better-suited to headless command-line tools.

https://github.com/WebAssembly/wasi-sdk

Will have to rebuild everything, like this:

 make CC="$WASISDK/bin/clang --sysroot=$WASISDK/share/wasi-sysroot -g" AR="$WASISDK/bin/ar" EXE_SUFFIX=.wasm cc65

Exceptions might not work yet, though. So have to stay w/ Emscripten for some tools for now.

Runtime: https://github.com/wasmerio/wasmer-js

Example

import { WASI } from "@wasmer/wasi"
import { WasmFs } from "@wasmer/wasmfs"

const wasmBindings = require("@wasmer/wasi/lib/bindings/node").default

var fs = require('fs')
var binary = fs.readFileSync('./cc65.wasm')
var mod = new WebAssembly.Module(binary);

function go() {
    var wasmFs = new WasmFs();
    wasmFs.fs.mkdirSync('/work');
    wasmFs.fs.writeFileSync('/work/test.c', 'void main(void) { return; }')

    var bindings = Object.create(wasmBindings);
    bindings.exit = (code?: number) => { console.log('exit',code); return 0; }
    bindings.fs = wasmFs.fs

    let myWASIInstance = new WASI({
        // OPTIONAL: The pre-opened dirctories
        preopenDirectories: {'/work':'/work'},
    
        // OPTIONAL: The environment vars
        env: {},
    
        // OPTIONAL: The arguments provided
        args: ['cc65', '/work/test.c', '--verbose'],
    
        // OPTIONAL: The environment bindings (fs, path),
        // useful for using WASI in diferent environments
        // such as Node.js, Browsers, ...
        bindings: bindings,
            //exit: (code?: number) => { console.log('exit',code); return 0; },
        // kill: (pid: number, signal?: string | number) -> void
        // randomFillSync: (buffer: Buffer, offset?: number, size?: number) -> Buffer
        // isTTY: () -> bool
        // fs: Filesystem (with similar API interface as Node 'fs' module)
        // path: Path  (with similar API Interface as Node 'path' module)
    });

    var inst = new WebAssembly.Instance(mod, myWASIInstance.getImports(mod));
    var _exports = inst.exports;
    console.log(inst);
    try {
        myWASIInstance.start(inst);
    } catch (e) {
        console.log('error',e); // maybe exit() was called?
    }
    console.log(wasmFs.fs.readFileSync('/work/test.s'));
}

go();

sehugg avatar Jul 20 '21 23:07 sehugg