tree: a81c5cc862f5b388144240ee1ff712e118984ad4 [search]
  1. denylists/
  2. internal/
  3. test/
  4. BUILD
  5. crubit_feature_hint.bzl
  6. global_features.bzl
  7. README.md
features/README.md

Crubit Features

SUMMARY: To enable Crubit on a C++ target and make it usable from Rust, use cc_library(..., aspect_hints=["//features:supported"]). No additional work is necessary for Rust targets to make them usable from C++.

The other features are more rarely useful, and mostly form a testing or release staging area for making changes to :supported.

C++/Rust interop is configured per target using “features”: aspect hints which are applied onto a build target in order to configure its automatically generated bindings.

Features control which capabilities Crubit has. For example, the layout-compatible std::string type is gated behind the :layout_compat_string feature. If a target is configured to use :layout_compat_string, then std::string in its bindings will use the layout-compatible Rust type, otherwise it will use the bridged string_wrapper type.

Features are also used for gradual rollouts of new capabilities, and to allow for separate build modes for un-annotated code, code which opts into C++/Rust interop, and internal test code.

Using Features

To use a feature, add it to your target:

# Enables the `:supported` feature on a C++ library `:example`.
cc_library(
    name = "example",
    hdrs = ["example.h"],
    aspect_hints = ["//features:supported"],
)

This causes the generated bindings for that target to use all the Crubit capabilities in :supported.

Features

<default>

By default, Rust targets enable Crubit, and C++ targets do not.

Bindings are only generated for code without feature hints if this has minimal or generally-agreed upon impositions on library owners.

Rust targets are well behaved, and are expected to support C++ callers and integrate into the existing C++ codebase. For that reason, Crubit is automatically enabled on all Rust targets. See crubit.rs/rust.

However, by default, Crubit does not run at all on C++ targets. On a sufficiently “strange” target, Crubit can fail arbitrarily badly. As a real-world example, some libraries in third_party have headers that do not even parse, and which disable the header parsing check. See e.g. b/348557947. Crubit cannot run on these without manual intervention.

In addition, unexpected Rust callers could frustrate C++ library owners, as Rust (even via Crubit) constrains the C++ API changes users can make. (For example, changing a type from trivial to nontrivial is potentially mostly nonbreaking in C++, but a very major API break in Rust.) So, even if the technical ability were there, enabling Crubit by default would still require conversation and cooperation with the C++ ecosystem, and the resulting compromise might be short of what you get with :supported.

"//features:supported"

The supported feature enables generally-available C++/Rust interop capabilities, for libraries that specifically support FFI callers.

See crubit.rs/cpp for documentation on what this includes.

This is a no-op on Rust targets.

"//features:experimental"

WARNING: experimental is deprecated, visibility-restricted to Crubit itself, and slated for removal. Use :supported plus the individual feature hints described in Other features instead.

Other features

The other features float over time, as new features are taken from :experimental and moved into a separate, individual feature, and then released as part of :supported in a Bazel configuration change.

See crubit.rs/team/release for why features are released this way.

How-to: Testing Features

Crubit developers may want to temporarily enable features without respect to visibility restrictions or level of support. The build flag:

--//common/bazel_support:globally_enabled_features

accepts a comma-separated list of unstable internal feature names (like supported, experimental, or the special alias all) and overrides the baseline feature set for all targets for the duration of the build.