Recommended way of calling a Rust library from OCaml

Hi,

what is currently a recommended way to call a library written in Rust from OCaml?

Thanks

1 Like

I haven’t used it myself, but you can try this project: GitHub - zshipko/ocaml-rs: OCaml extensions in Rust

2 Likes

GitHub - gridbugs/llama: Library for declaratively building software-defined modular synthesizers in OCaml uses Rust libraries from OCaml written by @gridbugs

Ocaml-rs is nice, but building and distribution problem is not yet solved. If you try to link two such Rust binding libraries into one OCaml executable - you’ll get linker errors about duplicate symbols, because there will be two Rust static libraries in the linking phase, and both export Rust stdlib and other symbols which will conflict.

We have some hacky tool developed internally that parses special metadata field in opam package definitions. That field states that certain opam package has an associated Rust crate which defines C stubs. Actual dune libraries do not explicitly depend on Rust stub library, and when used directly - produce linker errors about missing symbols. Our internal tool collects all opam dependencies of current project, and builds a list of corresponding Rust crates with C stubs. Then it generates dummy Rust crate, which depends on a those Rust crates with exact version constraints, i.e. Rust crate with C stubs is at the exact version as Opam package with OCaml part if the bindings to ensure compatibility between C stubs in Rust and their OCaml counterpart. That dummy Rust crate builds into static library and re-exports all those C stub crates via “pub use” in its lib.rs file.

This approach works and scales well to complex hierarchies of binding libraries, but it “taints” all binaries which depend directly or transitively on Rust bindings with, well, Rust toolchain. You have to have that Rust dummy staticlib generated in each project. And (empty) dune lib, pulling that static lib into linking needs to be added to all binaries so that lnker is satisfied.

It’s inspired by how Debian is packaging rust libs - they distribute Rust lib sources and build the sources into binaries when installing Rust binary packages.

Probably something along these lines could be implemented at dune level with less noise for the end user. We could instruct dune that certain library requires rust crate for C stubs, and during final project build, dune could assemble a list of crates, generate dummy static lib, build it with cargo, and pull it into the executables. Solving this at opam package level with extra metadata field requires hitting linker errors first and then running the special tool to generate dummy Rust staticlib with corresponding (empty) dune lib dragging the .a into linkage, and adding that dune lib in appropriate binaries by hand.