Bazel

Crubit is a Bazel module named rules_crubit. It provides both directions of bindings:

  • cpp_api_from_rust generates a C++ library from a rust_library. Load it from @rules_crubit//bazel:cpp_api_from_rust.bzl.
  • rust_api_from_cpp generates a Rust library from a cc_library. Load it from @rules_crubit//bazel:rust_api_from_cpp.bzl.

The examples/build_systems/bazel project is the reference setup. You can see Crubit in action by running:

git clone https://github.com/google/crubit.git
cd crubit/examples/build_systems/bazel
bazelisk run //:main

Set up your module

Add rules_crubit to your MODULE.bazel, together with the Rust and LLVM toolchains. The example project's MODULE.bazel shows the exact versions that Crubit is tested with:

cs/file:examples/build_systems/bazel/MODULE.bazel

The example uses local_path_override because it lives inside the Crubit repository. In your own project, use git_override instead, and pin a commit (for example, the one the latest tag points to):

git_override(
    module_name = "rules_crubit",
    remote = "https://github.com/google/crubit.git",
    commit = "<commit SHA>",
)

crubit_toolchains.configure configures the Rust and LLVM toolchains for the build. See Toolchain requirements for the versions that work.

Also copy the example's .bazelrc. It sets the Rust channel and the C++20 and Clang flags that Crubit expects.

C++ bindings for a Rust library {#cpp_api_from_rust}

Add a cpp_api_from_rust target for your rust_library, and depend on that target from C++:

cs/file:examples/build_systems/bazel/BUILD.bazel

The header name is the Rust target's name with .h appended, and the namespace is the target name:

cs/file:examples/build_systems/bazel/main.cpp

See C++ bindings for Rust libraries for what the generated API looks like, and how to customize it.

Rust bindings for a C++ library {#rust_api_from_cpp}

Define a rust_api_from_cpp target next to the cc_library, and add its automatically generated <name>.hint to the cc_library's aspect_hints:

load("@rules_cc//cc:cc_library.bzl", "cc_library")
load("@rules_crubit//bazel:rust_api_from_cpp.bzl", "rust_api_from_cpp")
load("@rules_rust//rust:rust_binary.bzl", "rust_binary")

cc_library(
    name = "foo",
    hdrs = ["foo.h"],
    srcs = ["foo.cc"],
    aspect_hints = [":foo_rust.hint"],
)

rust_api_from_cpp(
    name = "foo_rust",
    cpp_target = ":foo",
)

rust_binary(
    name = "main",
    srcs = ["main.rs"],  # use foo_rust::...;
    deps = [":foo_rust"],
)

See Rust bindings for C++ libraries for what the generated API looks like, and how to customize it.