NOTE: Crubit currently expects deep integration with the build system, and is difficult to deploy to environments dissimilar to Google's monorepo. We do not have our tooling set up to accept external contributions at this time.
Crubit is a bidirectional bindings generator for C++ and Rust, with the goal of integrating the C++ and Rust ecosystems.
See the [status](http:///overview/status) page for an overview of the current supported features.
Consider the following C++ function:
bool IsGreater(int lhs, int rhs);
This function, if present in a header file which is processed by Crubit, becomes callable from Rust as if it were defined as:
pub fn IsGreater(lhs: ffi::c_int, rhs: ffi::c_int) -> bool {...}
Note: There are some temporary restrictions on the API shape. For example, functions that accept a type like std::string
can't be called from Rust directly via Crubit. These restrictions will be relaxed over time.
Consider the following Rust function:
pub fn is_greater(lhs: i32, rhs: i32) -> bool { ... }
This function becomes callable from C++ as if it were defined as:
bool is_greater(int32_t lhs, int32_t rhs);
Note: There are some temporary restrictions on the API shape. For example, functions that accept two mutable references can't be called from C++ directly via Crubit. These restrictions will be relaxed over time.
We have detailed walkthroughs on how to use C++ from Rust, or Rust from C++, using Crubit, as well as copy-pastable example code. The example code also includes spanshots of what the generated bindings look like.
examples/cpp/
examples/rust/
Prerequisites:
Linux-specific setup:
# Choice of compiler is optional. export CC=/path/to/clang export CXX=/path/to/clang++ # We must use `lld` linker via clang. It must be in the PATH. export PATH="$PATH:/dir/containing/lld" export RUSTFLAGS="$RUSTFLAGS -Clinker=/path/to/clang" export RUSTFLAGS="$RUSTFLAGS -Clink-arg=-fuse-ld=lld" # If you want to use a sysroot. # SYSROOT_FLAG=--sysroot=$SYSROOT # export CXXFLAGS="$CXXFLAGS $SYSROOT_FLAG" # export RUSTFLAGS="$RUSTFLAGS -Clink-arg=$SYSROOT_FLAG"
MacOS-specific setup:
export CC=clang export CXX=clang++ export RUSTFLAGS="$RUSTFLAGS -Clinker=clang" export RUSTFLAGS="$RUSTFLAGS -Clink-arg=-fuse-ld=lld" # Point to the Xcode sysroot. export CXXFLAGS="$CXXFLAGS -isysroot $(xcrun --show-sdk-path)" export RUSTFLAGS="$RUSTFLAGS -Clink-arg=-isysroot -Clink-arg=$(xcrun --show-sdk-path)"
Windows-specific setup:
# We use clang compiler (clang-cl); MSVC may work too but is unsupported. export CC=clang-cl export CXX=clang-cl # We must use lld to link, which is spelt lld-link. So user-specified linker # flags must be in MSVC format. export RUSTFLAGS="$RUSTFLAGS -Clinker=/path/to/lld-link" # LLVM was built with Zlib support. Point Crubit to the same library. export CXXFLAGS="$CXXFLAGS /I/path/to/zlib" export RUSTFLAGS="$RUSTFLAGS -Clink-arg=/LIBPATH:/path/to/zlib" # Avoid deprecation warnings. export CXXFLAGS="$CXXFLAGS /D_CRT_SECURE_NO_DEPRECATE" # If LLVM (-DCMAKE_MSVC_RUNTIME_LIBRARY) and Abseil (-DABSL_MSVC_STATIC_RUNTIME) # are built against static CRT, then Rust needs to match, or vice-versa. # export RUSTFLAGS="$RUSTFLAGS -Ctarget-feature=+crt-static"
Run the build step via cargo:
# Paths for Crubit's cargo to use. ## This path contains clang/ and llvm/ dirs with their respective headers. export CLANG_INCLUDE_PATH=/path/to/llvm/and/clang/headers ## This path contains libLLVM*.a and libclang*.a. export CLANG_LIB_STATIC_PATH=/path/to/llvm/and/clang/libs ## This path contains absl/ dir with all the includes. export ABSL_INCLUDE_PATH=/path/to/absl/include/dir ## This path contains libabsl_* export ABSL_LIB_STATIC_PATH=/path/to/absl/libs cargo build --bin rs_bindings_from_cc
apt install clang lld bazel git clone git@github.com:google/crubit.git cd crubit bazel build --linkopt=-fuse-ld=/usr/bin/ld.lld //rs_bindings_from_cc:rs_bindings_from_cc_impl
git clone https://github.com/llvm/llvm-project cd llvm-project CC=clang CXX=clang++ cmake -S llvm -B build -DLLVM_ENABLE_PROJECTS='clang' -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=install cmake --build build -j # wait... cmake --install build cd ../crubit LLVM_INSTALL_PATH=../llvm-project/install bazel build //rs_bindings_from_cc:rs_bindings_from_cc_impl