Description
I'm thinking about some sound approach to distribute bindings for ocaml-rs
as separate libraries.
I have a project, ocaml-lwt-interop, which provides some OCaml C stubs, that are wrapped by some OCaml library, and also it provides some library types and functions for Rust. Some other project might be willing to depend on ocaml-lwt-interop
and provide more OCaml and Rust primitives.
How it's best to distribute it?
One idea that I currently have is to separate Rust stubs part and Rust library part into separate crates. Crate with stubs will "embedded" into OCaml library, that wraps those stubs with higher level API (yet exposing raw Rust opaque types and getters for them so that they can be used in other binding libraries). And Rust library part should be a normal Rust crate.
Let's say someone wants to write bindings to hyper
, this might look like this (Rust libs in red, OCaml libs in yellow):
flowchart
olwti["ocaml-lwt-interop (rust crate)"]
style olwti fill:#e38d8d
olwti_stubs["ocaml-lwt-interop-stubs (rust private crate)"]
style olwti_stubs fill:#e38d8d,stroke:#e3dc8d,stroke-width:3px
rust_async["rust-async (dune library)"]
style rust_async fill:#e3dc8d
ocaml_hyper["ocaml-hyper (rust crate)"]
style ocaml_hyper fill:#e38d8d
ocaml_hyper_stubs["ocaml-hyper-stubs (rust private crate)"]
style ocaml_hyper_stubs fill:#e38d8d,stroke:#e3dc8d,stroke-width:3px
rust_hyper["rust-hyper (dune library)"]
style rust_hyper fill:#e3dc8d
olwti_stubs --> olwti
rust_async --> olwti_stubs
rust_hyper --> rust_async
ocaml_hyper --> olwti
ocaml_hyper_stubs --> ocaml_hyper
ocaml_hyper_stubs --> olwti
rust_hyper --> ocaml_hyper_stubs
But how to solve the version constraints? If final OCaml application installs OCaml library rust-hyper
, that vendors all its Rust dependencies, and rust-hyper
pulls rust-async
, which also vendors its Rust dependencies, won't we end up with conflicting versions of ocaml-lwt-interop
being used at the same time?
Probably such libraries with bindings should not vendor Rust deps, and should not be published to opam, but need to all be vendored in the final OCaml application, where Rust dependencies need to be vendored? 🤯