I compiled JavaScript to Web Assembly using Bytecode Alliance's Javy. I then compiled the `.wasm` to C using WABT's `wasm2c`. Now I am trying to compile the resulting C to a standalone executable.
``` ./javy emit-plugin -o plugin.wasm ./javy build -C dynamic -C plugin=plugin.wasm -o javy-permutations.wasm permutations.js ``` The code can be run using ``` wasmtime run --preload javy_quickjs_provider_v3=plugin.wasm javy-permutations.wasm ``` Compiling WASM to C ``` ./wabt/bin/wasm2c javy-permutations.wasm -n array_nth_permutation -o javy-permutations.c ``` ``` ./wabt/bin/wasm2c plugin.wasm -n w2c_javy__quickjs__provider__v3 -o plugin.c ``` which writes `plugin.c` and `plugin.h` to the filesystem. The Javy implementation of WebAssembly toolchain. I also, in my attempts to replicate a working JavaScript implementation of this using Node.js https://github.com/bytecodealliance/javy/blob/main/docs/docs-using-nodejs.md, compiled `wasi_snapshot_preview1.reactor.wasm` to C using `wasm2c`. I have not been able to reproduce what I do using JavaScript in C. I was able to achieve the result for the factorial example in `wasm2c` https://github.com/WebAssembly/wabt/blob/main/wasm2c/README.md#tutorial-wat---wasm---c. There's no examples in `wasm2c` for compiling WASI to a standalone executable. Here's one version of the working JavaScript version that I'm trying to reproduce in C ``` import { readFile } from "node:fs/promises"; import { WASI } from "node:wasi"; try { const [embeddedModule, pluginModule] = await Promise.all([ compileModule("./javy-permutations.wasm"), compileModule("./plugin.wasm"), ]); const result = await runJavy(pluginModule, embeddedModule); // console.log("Success!", JSON.stringify(result, null, 2)); } catch (e) { console.log(e); } async function compileModule(wasmPath) { const bytes = await readFile(new URL(wasmPath, import.meta.url)); return WebAssembly.compile(bytes); } async function runJavy(pluginModule, embeddedModule) { /* // Use stdin/stdout/stderr to communicate with Wasm instance // See https://k33g.hashnode.dev/wasi-communication-between-nodejs-and-wasm-modules-another-way-with-stdin-and-stdout */ try { const wasi = new WASI({ version: "preview1", args: [], env: {}, returnOnExit: true, }); const pluginInstance = await WebAssembly.instantiate( pluginModule, { "wasi_snapshot_preview1": wasi.wasiImport }, ); const instance = await WebAssembly.instantiate( embeddedModule, { "javy_quickjs_provider_v3": pluginInstance.exports }, ); console.log(pluginInstance.exports); // Javy plugin is a WASI reactor see https://github.com/WebAssembly/WASI/blob/main/legacy/application-abi.md?plain=1 wasi.initialize(pluginInstance); instance.exports._start(); return "Done"; } catch (e) { console.log(e); if (e instanceof WebAssembly.RuntimeError) { if (errorMessage) { throw new Error(errorMessage); } } throw e; } finally { // console.log("Finally"); } } ``` Here's `javy-permutations.h` ``` /* Automatically generated by wasm2c */ #ifndef JAVY_PERMUTATIONS_H_GENERATED_ #define JAVY_PERMUTATIONS_H_GENERATED_ #include "wasm-rt.h" #include <stdint.h> #ifndef WASM_RT_CORE_TYPES_DEFINED #define WASM_RT_CORE_TYPES_DEFINED typedef uint8_t u8; typedef int8_t s8; typedef uint16_t u16; typedef int16_t s16; typedef uint32_t u32; typedef int32_t s32; typedef uint64_t u64; typedef int64_t s64; typedef float f32; typedef double f64; #endif #ifdef __cplusplus extern "C" {// #endif struct w2c_javy__quickjs__provider__v3; extern wasm_rt_memory_t* w2c_javy__quickjs__provider__v3_memory(struct w2c_javy__quickjs__provider__v3*); typedef struct w2c_array__nth__permutation { struct w2c_javy__quickjs__provider__v3* w2c_javy__quickjs__provider__v3_instance; /* import: 'javy_quickjs_provider_v3' 'memory' */ wasm_rt_memory_t *w2c_javy__quickjs__provider__v3_memory; bool data_segment_dropped_w2c_array__nth__permutation_d0 : 1; } w2c_array__nth__permutation; void wasm2c_array__nth__permutation_instantiate(w2c_array__nth__permutation*, struct w2c_javy__quickjs__provider__v3*); void wasm2c_array__nth__permutation_free(w2c_array__nth__permutation*); wasm_rt_func_type_t wasm2c_array__nth__permutation_get_func_type(uint32_t param_count, uint32_t result_count, ...); /* import: 'javy_quickjs_provider_v3' 'canonical_abi_realloc' */ u32 w2c_javy__quickjs__provider__v3_canonical_abi_realloc(struct w2c_javy__quickjs__provider__v3*, u32, u32, u32, u32); /* import: 'javy_quickjs_provider_v3' 'invoke' */ void w2c_javy__quickjs__provider__v3_invoke(struct w2c_javy__quickjs__provider__v3*, u32, u32, u32, u32); extern const u64 wasm2c_array__nth__permutation_min_javy__quickjs__provider__v3_memory; extern const u64 wasm2c_array__nth__permutation_max_javy__quickjs__provider__v3_memory; extern const u8 wasm2c_array__nth__permutation_is64_javy__quickjs__provider__v3_memory; /* export: '_start' */ void w2c_array__nth__permutation_0x5Fstart(w2c_array__nth__permutation*); #ifdef __cplusplus } #endif #endif /* JAVY_PERMUTATIONS_H_GENERATED_ */ ``` Here's what I tried so far in `main.javy.c` ``` #include <stdio.h> #include <stdlib.h> #include "javy-permutations.h" #include "plugin.h" int main(int argc, char** argv) { /* Make sure there is at least one command-line argument. */ if (argc < 2) { printf("Invalid argument. Expected '%s NUMBER'\n", argv[0]); return 1; } /* Convert the argument from a string to an int. We'll implicitly cast the int to a `u32`, which is what `fac` expects. */ // u32 x = atoi(argv[1]); /* Initialize the Wasm runtime. */ wasm_rt_init(); /* Declare an instance of the `fac` module. */ w2c_array__nth__permutation array__nth__permutation; w2c_javy__quickjs__provider__v3 provider; /* Construct the module instance. */ wasm2c_array__nth__permutation_instantiate(&array__nth__permutation, &provider); /* Call `fac`, using the mangled name. */ // u32 result = w2c_fac_fac(&fac, x); /* Print the result. */ // printf("fac(%u) -> %u\n", x, result); w2c_array__nth__permutation_0x5Fstart(array__nth__permutation*) /* Free the fac module. */ w2c_w2c__javy__0x5Fquickjs__0x5Fprovider__0x5Fv3_canonical_abi_free(w2c_w2c__javy__0x5Fquickjs__0x5Fprovider__0x5Fv3*, u32, u32, u32); /* Free the Wasm runtime state. */ wasm_rt_free(); return 0; } ``` which throws errors when trying to compile ``` cc -o javy-permutations main.javy.c javy-permutations.c wasm2c/wasm-rt-impl.c wasm2c/wasm-rt-mem-impl.c -Iwasm2c -lm main.javy.c: In function ‘main’: main.javy.c:24:3: error: unknown type name ‘w2c_javy__quickjs__provider__v3’; use ‘struct’ keyword to refer to the type 24 | w2c_javy__quickjs__provider__v3 provider; | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | struct main.javy.c:27:72: warning: passing argument 2 of ‘wasm2c_array__nth__permutation_instantiate’ from incompatible pointer type [-Wincompatible-pointer-types] 27 | ray__nth__permutation_instantiate(&array__nth__permutation, &provider); | ^~~~~~~~~ | | | int * In file included from main.javy.c:4: javy-permutations.h:37:79: note: expected ‘struct w2c_javy__quickjs__provider__v3 *’ but argument is of type ‘int *’ 37 | _nth__permutation_instantiate(w2c_array__nth__permutation*, struct w2c_javy__quickjs__provider__v3*); | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ main.javy.c:34:65: error: expected expression before ‘)’ token 34 | w2c_array__nth__permutation_0x5Fstart(array__nth__permutation*) | ``` I suspect I need to initialize import `wasi_snapshot_preview` into the plugin in C, though I am not sure how to do that. -- You received this message because you are subscribed to the Google Groups "emscripten-discuss" group. To unsubscribe from this group and stop receiving emails from it, send an email to [email protected]. To view this discussion visit https://groups.google.com/d/msgid/emscripten-discuss/66e87783-4f35-482d-a6ae-c538477abf2an%40googlegroups.com.
