Do not collect attributed headers for targets that don't enable Crubit.

WTB: actual profiling tools for my starlark.

Since the number of targets that enable Crubit is very small, and will remain small for a long time, this was hypothesized to have an impact on build performance: instead of carrying around and communicating every single header from every single transitive dep (O(n)), we carry around only the ones that specifically enable Rust/Crubit support.

It does seem like a good idea on that grounds, and even if performance wins don't materialize here, it might be a part of the overall story later. That said, performance wins _don't_ materialize here, and the impact on bazel memory usage and CPU is indistinguishable from the null hypothesis.

Still, literally every CL in the chain to today, except for the immediately previous CL and this one, had a reason for existence other than the end goal of the bug, so there's only a little bit of wasted work. And it probably is marginally faster and better on memory, even if it's hard to measure.

Other effects: this does change the error messages: since we don't know what target a header is on, we can't say "enable Crubit on that target!", but instead say "enable Crubit on that header!". But the work necessary for this has all already been done: this is, as of this CL, _purely_ a change to the error comments, and not a particularly large one.

(The work necessary to unblock this was 1. to make it so that if a header is not known, it's treated the same as if it's known but Crubit was disabled on the target, and 2. to give error messages that mention the header file, in such an event.)

As of this CL, AFAIK, there is nothing left to do for the "shrink target_args" bug, and we can mark that as closed.

PiperOrigin-RevId: 825135672
Change-Id: I4cca69ac55410c28fdcc46bed5a08c283d62af48
2 files changed
tree: 028d51964e95f801f248d874ac4604b62e228e5f
  1. .bazelci/
  2. .github/
  3. bazel/
  4. buildenv/
  5. cargo/
  6. cc_bindings_from_rs/
  7. common/
  8. docs/
  9. examples/
  10. features/
  11. lifetime_analysis/
  12. lifetime_annotations/
  13. migrator/
  14. nullability/
  15. rs_bindings_from_cc/
  16. support/
  17. .bazelrc
  18. .bazelversion
  19. .gitignore
  20. book.toml
  21. BUILD
  22. Cargo.Bazel.lock
  23. Cargo.toml
  24. CODE_OF_CONDUCT
  25. CONTRIBUTING
  26. LICENSE
  27. MODULE.bazel
  28. README.md
  29. rust-toolchain.toml
  30. WORKSPACE.bzlmod
README.md

Crubit: C++/Rust Bidirectional Interop Tool

Build status

NOTE: Crubit currently expects deep integration with the build system, and is difficult to deploy to environments dissimilar to Google's monorepo. External contributions are accepted, but may in some cases be difficult to integrate for tooling reasons. See CONTRIBUTING. Both of these are being worked on, see https://github.com/google/crubit/blob/main/docs/overview/status.md#usage-outside-of-google

Crubit is a bidirectional bindings generator for C++ and Rust, with the goal of integrating the C++ and Rust ecosystems.

Status

See the [status](http:///overview/status) page for an overview of the current supported features.

Example

C++ {.new-tab}

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::vector can't be called from Rust directly via Crubit. These restrictions will be relaxed over time.

Rust {.new-tab}

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.

Getting Started

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.

Building Crubit

Cargo

Prerequisites:

  • Requires LLVM and Clang libraries to be built and installed.
    • They must be built with support for compression (zlib), which is the default build config.
  • Requires Abseil libraries to be built and installed.
  • Requires zlib (e.g. libz.so) to be available in the system include and lib paths.
  • An up-to-date stable Rust toolchain.

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:

  • Windows is currently unsupported, and the APIs generated by Crubit may not compile and will change over time.
  • All commands must be run from a development shell, where MSVC environment variables are set up.
# 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

Bazel

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

Using a prebuilt LLVM tree

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