Is it possible to link a C++ project compiled to wasm32-wasi into a Rust crate that uses wasm-bindgen and compiles to wasm32-unknown-unknown?
In rust due to historic accident wasm32-unknown-unknown is ABI incompatible with the wasm C ABI that rustc uses for wasm32-wasi and clang uses for all wasm targets. So if you want to directly call C++ functions from the rust crate, that isn't going to work. If you only work through the wasi interface it could work, but you did have to write a wasi implementation in rust and link the C++ code as static library. You can't link an already linked wasm module with other code.
Oh interesting, that's unfortunate. Thanks for the reply. What I Was trying to do is to link a C++ project (URL parser) into a Rust crate but that C++ project requires some libc functionality.
Tho it's not really relying on any syscalls, so I am wondering if I could somehow mock the syscalls and compile it to wasm32-unknown-unknown :thinking:
Would that be possible @bjorn3?
If you only pass primitive types like integers (32 and 64bit only), floats and pointers and don't pass any structs without a pointer indirection the abi incompatibility shouldn't hit you.
By the way maybe you could compile your C++ code using emscripten exporting a javascript interface and then call the exported javascript interface using wasm-bindgen from the rust code? https://emscripten.org/docs/porting/connecting_cpp_and_javascript/Interacting-with-code.html provides some documentation on how to export a javascript interface from emscripten. This is probably going to be slower than directly linking the C++ and rust code though.
By the way for a URL parser is there a reason you aren't using the javascript URL parser or the url crate? There are two versions of the URL specification (the RFC1738 one and the WHATWG one) which are different in ways that can cause security issues. Browsers and the url crate use the WHATWG version. I don't know which variant your C++ URL parser uses.
Hm, I think what I'd like to pass is strings (as pointers maybe)
The problem I am running into is, even if I compile the lib to wasi, it somehow complains then about
rust-lld: error: unable to find library -lstdc++
Cause my lib type is crate-type = ["cdylib"]
But browser also don't closely follow WHATWG unfortunately, at least Chrome and FF
I wanna link https://www.ada-url.com/ because Node.js uses that parser and the browser's URL doesn't seem to be fully compliant with ada
Cause Chrome and FF are not fully spec compliant
If you are doing URL parsing for security related purposes you did want to use the browser's URL parser rather than whatever the specification says precisely because the divergence can cause the browser to interpret URL's in ways you didn't expect.
Dominic Elm said:
Cause Chrome and FF are not fully spec compliant
This statement surprised me because the whole reason the WHATWG URL specification exists at all afaik is to codify the divergence between actual browsers and RFC1738, but it seems there are indeed some divergences between WHATWG and some actual browsers.
Dominic Elm said:
The problem I am running into is, even if I compile the lib to wasi, it somehow complains then about
rust-lld: error: unable to find library -lstdc++
Are you telling rustc where to find the library dir of the wasi-sdk using -L
?
Do I have to pass the -L
in the build.rs
?
This is what my current build.rs looks like
fn main() {
cc::Build::new()
.cpp(true)
.compiler("/opt/wasi-sdk/build/wasi-sdk-20.10g7c0558ba4159/bin/clang++")
.flag("--sysroot=/opt/wasi-sdk/build/wasi-sdk-20.10g7c0558ba4159/share/wasi-sysroot")
.include("./ada/include")
.include("./ada/include/ada")
.target("wasm32-wasi")
.file("./ada/src/ada.cpp")
.compile("ada");
}
But that results in the error that I posted earlier
Try adding println!("cargo:rustc-link-search=/opt/wasi-sdk/build/wasi-sdk-20.10g7c0558ba4159/share/wasi-sysroot/lib");
(I think /opt/wasi-sdk/build/wasi-sdk-20.10g7c0558ba4159/share/wasi-sysroot/lib
would be the directory containing libstdc++
, but if not change it to the directory that does contain it)
Hm yea, doesn't seem to work
Tho that folder contains the following
image.png
So there is libc++.a
Oh wait
It's libc++
Not libstdc++
So maybe I can change it to use c++ as the standard lib
Uhhh that worked maybe :eyes:
Okay... I am a little closer
Now I am seeing a few imports, prolly from the stdlib
Any idea how I can get those or what I can do?
Ok passing -fno-exceptions
will get rid of some
Down to these
image.png
Not sure what to do about those
Abort and memchr are coming from libc normally with memchr being provided for you from the rust side. You could implement abort as a panic in rust. __cxa_atexit
allows registering a function to run when exiting the current process. Probably fine to implement it as no-op. For the rest I'm not sure what they do. You could try implementing them as panic. If that doesn't work could you run their names through a C++ name demangler like c++filt? That may make their name more readable.
Run what through a demangler?
I am now linking libc++
Is there a way I can also include libc so that it may find memchr?
aha
image.png
Operators
Seems like libc++ is missing those?
Hm
@Dominic Elm You can try using wasm-bridge, which is a create I built from loading and running wasm modules in Rust on the web. I have never tried it with C++, but that should not matter, as long as it's compiled to WASM correctly. The wasi support is still in progress though.
Last updated: Dec 23 2024 at 12:05 UTC