Integrating Automatically Generated FFI Bindings
There are a number of tools to automatically generate bindings between Rust and different foreign languages.
bindgen
bindgen is a tool to automatically generate Rust bindings from C headers. As such, integrating bindgen via a build-script works well and their doesn't seem to be a need to create CMake rules for generating the bindings.
cbindgen integration
⚠️⚠️⚠️ EXPERIMENTAL ⚠️⚠️⚠️
cbindgen is a tool that generates C/C++ headers from Rust code. When compiling C/C++
code that #include
s such generated headers the buildsystem must be aware of the dependencies.
Generating the headers via a build-script is possible, but Corrosion offers no guidance here.
Instead, Corrosion offers an experimental function to add CMake rules using cbindgen to generate the headers. This is not available on a stable released version yet, and the details are subject to change.
corrosion_cbindgen(
TARGET <imported_target_name>
HEADER_NAME <output_header_name>
[CARGO_PACKAGE <cargo_package_name>]
[MANIFEST_DIRECTORY <package_manifest_directory>]
[CBINDGEN_VERSION <version>]
[FLAGS <flag1> ... <flagN>]
)
A helper function which uses cbindgen to generate C/C++ bindings for a Rust crate.
If cbindgen
is not in PATH
the helper function will automatically try to download
cbindgen
and place the built binary into CMAKE_BINARY_DIR
. The binary is shared
between multiple invocations of this function.
-
TARGET: The name of an imported Rust library target, for which bindings should be generated. If the target was not previously imported by Corrosion, because the crate only produces an
rlib
, you must additionally specifyMANIFEST_DIRECTORY
. -
MANIFEST_DIRECTORY: Directory of the package defining the library crate bindings should be generated for. If you want to avoid specifying
MANIFEST_DIRECTORY
you could add astaticlib
target to your package manifest as a workaround to make corrosion import the crate. -
HEADER_NAME: The name of the generated header file. This will be the name which you include in your C/C++ code (e.g.
#include "myproject/myheader.h" if you specify
HEADER_NAME "myproject/myheader.h"`. -
CBINDGEN_VERSION: Version requirement for cbindgen. Exact semantics to be specified. Currently not implemented.
-
FLAGS: Arbitrary other flags for
cbindgen
. Runcbindgen --help
to see the possible flags.
Current limitations
- Cbindgens (optional) macro expansion feature internally actually builds the crate / runs the build script. For this to work as expected in all cases, we probably need to set all the same environment variables as when corrosion builds the crate. However the crate is a library, so we would need to figure out which target builds it - and if there are multiple, potentially generate bindings per-target? Alternatively we could add support of setting some environment variables on rlibs, and pulling that information in when building the actual corrosion targets Alternatively we could restrict corrosions support of this feature to actual imported staticlib/cdylib targets.
Current limitations
- The current version regenerates the bindings more often then necessary to be on the safe side, but an upstream PR is open to solve this in a future cbindgen version.
cxx integration
⚠️⚠️⚠️ EXPERIMENTAL ⚠️⚠️⚠️
cxx is a tool which generates bindings for C++/Rust interop.
corrosion_add_cxxbridge(cxx_target
CRATE <imported_target_name>
REGEN_TARGET <regen_target_name>
[FILES <file1.rs> <file2.rs>]
)
Adds build-rules to create C++ bindings using the cxx crate.
Arguments:
cxxtarget
: Name of the C++ library target for the bindings, which corrosion will create.- FILES: Input Rust source file containing #[cxx::bridge].
- CRATE: Name of an imported Rust target. Note: Parameter may be renamed before release
- REGEN_TARGET: Name of a custom target that will regenerate the cxx bindings without recompiling. Note: Parameter may be renamed before release
Currently missing arguments
The following arguments to cxxbridge currently have no way to be passed by the user:
--cfg
--cxx-impl-annotations
--include
The created rules approximately do the following:
- Check which version of
cxx
the Rust crate specified by theCRATE
argument depends on. - Check if the exact same version of
cxxbridge-cmd
is installed (available inPATH
) - If not, create a rule to build the exact same version of
cxxbridge-cmd
. - Create rules to run
cxxbridge
and generate- The
rust/cxx.h
header - A header and source file for each of the files specified in
FILES
- The
- The generated sources (and header include directories) are added to the
cxxtarget
CMake library target.
Limitations
We currently require the CRATE
argument to be a target imported by Corrosion, however,
Corrosion does not import rlib
only libraries. As a workaround users can add
staticlib
to their list of crate kinds. In the future this may be solved more properly,
by either adding an option to also import Rlib targets (without build rules) or by
adding a MANIFEST_PATH
argument to this function, specifying where the crate is.
Contributing
Specifically some more realistic test / demo projects and feedback about limitations would be welcome.