cloudflare / workers-rs

Write Cloudflare Workers in 100% Rust via WebAssembly
Apache License 2.0
2.53k stars 269 forks source link

thirdparty .wasm usage from C #616

Open aviplayer opened 2 months ago

aviplayer commented 2 months ago

Is there an existing issue for this?

Description

Are there any ability to use C compiled code? I noticed nightly build provide an ability to compile/link C code example: https://github.com/rafaelbeckel/test-c-rust-wasm discussion: https://github.com/rustwasm/wasm-bindgen/pull/2209 I tried to reuse solutions, but got an exceptions:

Added lib like this: rbg_calculator = { path = "../test-c-rust-wasm/crates/5_rust_bindgen" }

But CloudFlare worker fails:  service core:user:memgraph: Uncaught TypeError: WebAssembly.Instance(): Import #6 "env": module is not an object or function

Final goal is to add this one: https://github.com/memgraph/mgclient It has an ability to be compiled in wasm:

Building WASM (Linux only)
Compiling mgclient for wasm requires the Emscripten sdk. This is automated in the following steps:
mkdir build && cd build
cmake .. -DWASM=ON

I also tried it, but the same error Any suggestion on this?

aviplayer commented 2 months ago

It fails directly there - var B = new WebAssembly.Instance(N, { "./index_bg.js": g }); What does it mean? What is index_bg? I tried to find any files but worker-build doesn't ptoduce any

spigaz commented 2 months ago

My understanding is that workers-rs just compiles to wasm32-unknown-unknown and that poses some limitations.

But under the hood, the plain wasm file is loaded by the engine and you can use that, to access some additional support that might be present: https://developers.cloudflare.com/workers/runtime-apis/webassembly/javascript/

And apparently there is a way to get emscripten to work (it seems required by your final goal in wasm) https://github.com/cloudflare/worker-emscripten-template

kflansburg commented 1 month ago

It fails directly there - var B = new WebAssembly.Instance(N, { "./index_bg.js": g }); What does it mean? What is index_bg? I tried to find any files but worker-build doesn't ptoduce any

These errors seem to be originating from the JavaScript shim that we auto-generate for you. Can you share a full reproduction repository?

aviplayer commented 1 month ago

Seems C static library was incorrect. Just bindings are not present. I asked on there repository, have no answer. One question: Can I use thirdparty .wasm from Rust on CF? Any suggestion to use from wasm? I see it is possible to use memgraph from js: https://github.com/memgraph/jsmgclient/tree/main But are there any standard/easy approach you can recommend? @kflansburg

Tried to load/embed using wasm_bingen, but got an error `Err value: JsValue(CompileError: WebAssembly.instantiate(): Wasm code generation disallowed by embedder ` https://github.com/cloudflare/cloudflare-docs/issues/13469

Then if there any way to run thirdparty wasm?

rafaelbeckel commented 1 month ago

@aviplayer, sorry for my late answer; I was on vacation and didn't see your message.

This issue arises because C symbols are not exported to a dylib unless you wrap them explicitly in Rust. This thread can give you some context: https://github.com/rust-lang/rfcs/issues/2771.

In the case of WASM, all missing symbols are expected to be provided from the env variable in the WASM imports table.

In my example, the memory.js file injects the missing symbols and provides a simple bump allocator from JS for malloc() and free() calls. Check out the build_with_wasm_pack.sh file in my example.

This was my first iteration for a POC and quite a hack-ish approach. In production, I'm using musl-libc (instead of the OpenBSD subset in the calculator) and have malloc() and free() implemented in Rust directly from the tinylibc crate, so we don't have to provide it from the imports table.

I will update the examples later on.