cpp_api_from_rust

Availability

Experimental support in Chromium

cpp_api_from_rust support is currently considered experimental and unstable.

TODO(https://crbug.com/470466915): Edit this section once we officially declare and announce support for using cpp_api_from_rust for some Rust libraries. (“some” because of toolchain availability caveats in the other section below.)

Toolchain availability outside of Chromium

Chromium's //third_party/rust-toolchain includes cpp_api_from_rust, but other projects may not. This means that Chromium code that is built in such other projects should not depend on cpp_api_from_rust. Examples of code that should not depend on cpp_api_from_rust:

  • //base, //net and other Cronet dependencies. (This restriction should go away when/if Android support for cpp_api_from_rust hopefully comes later in 2026.)
  • 2nd-party projects like
    • ANGLE (TODO: more details - something about being used by Apple?)
    • Skia (no cpp_api_from_rust support in Bazel)
    • V8 (TODO: more details - probably need Crubit support for official releases of Rust toolchain)

Other docs

  • Generic, Chromium-agnostic documentation of Crubit can be found at https://crubit.rs.
    • Note that some examples are Bazel-specific, but most of the documentation should still apply to Chromium.
    • Note that the documentation covers both cpp_api_from_rust (with some Chromium support - see “availability” above) and rust_api_from_cpp (with no Chromium support at this point).
  • Google-internal Crubit documentation can be found at go/crubit
    • This is mostly the same content as above, but is mentioned here because it includes a few extra things like document freshness and owner metadata, link to a Google-internal chatroom, etc.)
  • TODO: Cover Crubit in Chromium/FFI chapter of Comprehensive Rust course

Using cpp_api_from_rust in Chromium

Enabling cpp_api_from_rust for a rust_static_library crate

Example:

// build/rust/tests/test_cpp_api_from_rust/lib.rs:
pub fn mul_two_ints_via_rust(x: i32, y: i32) -> i32 {
    x * y
}
# build/rust/tests/test_cpp_api_from_rust/BUILD.gn

import("//build/rust/rust_static_library.gni")

rust_static_library("rust_lib") {
  crate_root = "lib.rs"
  sources = [ crate_root ]
  cpp_api_from_rust = {
    target_name = "rust_lib_bindings"
  }
}

source_set("unittests") {
  sources = [ "unittests.cc" ]
  deps = [
    ":rust_lib_bindings",
  ]
}
// build/rust/tests/test_cpp_api_from_rust/unittests.cc:

#include "build/rust/tests/test_cpp_api_from_rust/rust_lib.h"

void foo() {
  auto product = rust_lib::mul_two_ints_via_rust(3, 4);
}

Enabling cpp_api_from_rust for a third_party/rust crate

TODO: This is not implemented yet.

Inspecting the generated bindings

Let's assume that cpp_api_from_rust bindings are generated for //some/dir:some_target - e.g.:

# some/dir/BUILD.gn

import("//build/rust/rust_static_library.gni")

rust_static_library("some_target") {
  crate_root = "lib.rs"
  sources = [ crate_root ]
  cpp_api_from_rust = {
    target_name = "some_target_bindings"
  }
}

The generated bindings can then be found and inspected in <out_dir>/gen/some/dir/some_target.h. For example:

$ cat out/rel/gen/build/rust/tests/test_cpp_api_from_rust/rust_lib.h | head -3
// Automatically @generated C++ bindings for the following Rust crate:
// rust_lib_1dc874e1
// Features: <none>

Troubleshooting

APIs missing from the generated bindings

If cpp_api_from_rust is unable to generate bindings for a given Rust API, then the generated .h file will contain a comment explaining why. The sections below describe a few errors that are somewhat related to how Chromium integrates Crubit into its build system.

No --crate-header was specified for this crate

If you see an error like:

$ cat out/rel/gen/build/rust/tests/test_cpp_api_from_rust/rust_lib.h
...
// Error generating bindings for `create_multiplier` defined at
// ../../build/rust/tests/test_cpp_api_from_rust/lib.rs;l=22: Error formatting
// function return type `other_lib::Multiplier`: Type `other_lib::Multiplier`
// comes from the `other_lib_1dc874e1` crate, but no `--crate-header` was
// specified for this crate
...

Then: TODO: Support for transitive deps is not implemented yet.