Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rust bindings #858

Closed
ncthbrt opened this issue Jul 9, 2024 · 24 comments
Closed

Rust bindings #858

ncthbrt opened this issue Jul 9, 2024 · 24 comments

Comments

@ncthbrt
Copy link

ncthbrt commented Jul 9, 2024

There is interest in using manifold for the Bevy game engine. To do so would require that Rust bindings are made available. This should be possible for native platforms and also the latest nightly of Rust for web assembly (in theory). We're currently trying to produce a proof of concept that demonstrates the bindings in action.

@pca006132
Copy link
Collaborator

Thanks for your interest. FYI folks working on godot engine is also looking into using manifold for their csg operations (#91).

For rust binding, I am not sure if we want to add it here. I think maintaining a rust binding outside this repo should be fine as we already have a relatively stable C FFI.

@ncthbrt
Copy link
Author

ncthbrt commented Jul 9, 2024

The only wrinkle with that might be wasm suppport. As rust largely has largely settled on targeting wasm32 unknown rather than wasm32 emscripten

@pca006132
Copy link
Collaborator

I think clang can compile to wasm32 unknown? Never tried that though. Our wasm port is in fact just a js binding using emscripten, I don't think we have anything specific about using emscripten.

Maybe you want to compile the sequential version for now, tbb may not work that well in wasm iirc.

@elalish
Copy link
Owner

elalish commented Jul 9, 2024

Great to hear, please let us know how it goes and if there's anything to change here to make it easier to bind. Honestly, I kind of wish I'd started this library in Rust (didn't know about it at the time). Someday when Github Copilot gets good enough to translate code bases, maybe I'll try to port it.

@pca006132
Copy link
Collaborator

// You will probably have a terrible time trying to beat rust's borrow checker to compile those parallel for_each loops.

I think the major problem is that different projects want different dependencies: C++ projects said it would be hard for them to adapt something written in rust, and conversely for rust. For C++ projects though it is kind of understandable as they probably don't want another compiler toolchain to build things.

I did thought about porting to rust, I don't think it will be too hard. However, at the end I feel that a rust port will not be very useful as C++ libraries will not be switching to the rust version, and maintaining two implementations and optimizing them will be really time consuming.

@elalish
Copy link
Owner

elalish commented Jul 9, 2024

Yeah, maybe this is more of a distant future thing if Rust really does become a lot more popular than C++. Anyway, for now I'm certainly happy with C++, since everyone seems to be able to bind to it, including Rust.

@ncthbrt
Copy link
Author

ncthbrt commented Jul 10, 2024

Regarding the web assembly concern, it may be necessary to replace some of the usages of the stdlib with alternatives to get compilation working on wasm32-unknown-unknown.

@elalish
Copy link
Owner

elalish commented Jul 10, 2024

Can you give an example? PRs welcome.

@ncthbrt
Copy link
Author

ncthbrt commented Jul 10, 2024

Examples include use of the c++ stl modules: algorithm, array, limits, etc.
It would be quite onerous to replace these all, (or more likely to #ifdef them) but if I am correct may be the only way to get manifold compilation working for bevy on web.

@pca006132
Copy link
Collaborator

Why? These are header-only libraries. I thought issues related to wasm32-unknown-unknown are ABI issues, which should have nothing to do with header-only libraries.

@ncthbrt
Copy link
Author

ncthbrt commented Jul 10, 2024

I'll test that then. Hopefully you are correct.

@ncthbrt
Copy link
Author

ncthbrt commented Jul 13, 2024

The ABI issues are fixed by a flag in Rust nightly.

Unfortunately there is a few dependencies on libm/libc.
Which means that to get stuff working you'd need to vendor in a minimal subset of those libs.

Which is quite a tall order.

I'm going to investigate alternative approaches. Perhaps an rpc like interface would make it possible to interop between bevy and manifold.

@pca006132
Copy link
Collaborator

I think rust can target wasi and they have https://github.com/WebAssembly/wasi-libc?

@ncthbrt
Copy link
Author

ncthbrt commented Jul 13, 2024

That is true however the broader Rust ecosystem has eschewed wasi in favour of wasm32-unknown-unknown and wasm-bindgen. It may change in time as wasi gains traction but currently manifold would be a desert island in terms of compatibility.

@pca006132
Copy link
Collaborator

Do you have a set of undefined symbols that we use from libc and libm? I think it the set should be small amd maybe you can implement them in rust. I don't think it is possible to avoid libc and libm when the compiler is expecting them to present... And without libm we can't even do things like trigonometry.

@ncthbrt
Copy link
Author

ncthbrt commented Jul 13, 2024

Yes. I agree that it's not practical to get rid of those as dependencies.

Hmmm. I don't have a full list but dequeue and cmath were the two imports that were failing.

I'm wondering if a simpler stop gap for now would be to declare the ecmascript package as a ffi and call into that for wasm. Sure it'll be slower but it would be a significantly smaller maintenance ask.

@pca006132
Copy link
Collaborator

By imports that are failing, do you mean no such header file or linker error? I think dequeue is header only, or it will be in libcxx/libstdc++ and not libc.

@ncthbrt
Copy link
Author

ncthbrt commented Jul 13, 2024

Header file.

@pca006132
Copy link
Collaborator

I think it should be fine to use the host system headers? Maybe you can give me the script you used to compile it and I can have a look at the issue when I have time.

@ncthbrt
Copy link
Author

ncthbrt commented Jul 13, 2024

I've updated the test repository here:
https://github.com/ncthbrt/manifold-rust/

Note you'll need to install the nightly version of rust to get this to partially compile. And also set the flags
export CXX=/usr/bin/clang++ and export CC=/usr/bin/clang. The entry point is ./build_with_wasm_pack.sh

@pca006132
Copy link
Collaborator

pca006132 commented Jul 13, 2024

OK, I took a look at it. I think the issue is that the cmake/cc crate is basically treating wasm32-unknown-unknown as wasm32 + nostdlib for C/C++. This means that users should provide their own toolchain files for those headers. dequeue and cmath are failing because there is no such toolchain file. In fact, every single include to the standard library will fail, you only see dequeue and cmath failing because they are the first to fail, and the latter failures are not checked. It may be possible to write a toolchain file that include from llvm libc and libcxx headers (plus some specific files that are platform dependent), but it requires some knowledge about libc and libcxx of llvm. Folks working on emscripten should know better about this.

I guess for now you need alternative approaches. I don't think there is an easy way to get around this.

@ncthbrt
Copy link
Author

ncthbrt commented Jul 13, 2024

Thanks for taking a look! Going to investigate work arounds

@pca006132
Copy link
Collaborator

Is there anything we can do regarding this? Or maybe we should just close this issue/move this to discussion.

@ncthbrt
Copy link
Author

ncthbrt commented Sep 7, 2024

For now probably not. Thank you for following up though!

@pca006132 pca006132 closed this as not planned Won't fix, can't repro, duplicate, stale Sep 7, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants