| <!-- Part of the Crubit project, under the Apache License v2.0 with LLVM --> | |
| <!-- Exceptions. See /LICENSE for license information. --> | |
| <!-- SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception --> | |
| # Building | |
| This page is about calling **C++ from Rust** with `rust_api_from_cpp`. If you | |
| want to call Rust from C++, see [C++ bindings for Rust | |
| libraries](../rust/building.md) instead. | |
| ## Using `rust_api_from_cpp` in your build | |
| `rust_api_from_cpp` is available in **Bazel**, through the `rules_crubit` | |
| module. See [Bazel](../overview/bazel.md#rust_api_from_cpp) for setup | |
| instructions. Bazel builds the `rs_bindings_from_cc` tool for you, including | |
| the LLVM libraries it depends on, so there is nothing else to install. | |
| <!-- TODO(b/574505910): Link to a rust_api_from_cpp example and CI job once | |
| examples/build_systems/bazel covers it. --> | |
| CMake and Cargo integrations for `rust_api_from_cpp` are planned | |
| <!-- TODO(b/539627008) --> but not available yet. See | |
| [Build System Integrations](../overview/build_systems.md) for the current | |
| status of every build system. | |
| ## Building `rs_bindings_from_cc` yourself | |
| If you're integrating Crubit into another build system, you can build the | |
| `rs_bindings_from_cc` binary yourself and run it the way the | |
| [Bazel rules](https://github.com/google/crubit/tree/main/rs_bindings_from_cc/bazel_support) | |
| do. | |
| `rs_bindings_from_cc` is a Rust program that links against Clang's C++ | |
| libraries, plus Abseil and Protobuf. It is built against a specific | |
| `llvm-project` commit, pinned in `MODULE.bazel` and updated regularly by CI. | |
| Open-source CI covers Linux x86_64. | |
| There are two ways to build it: with Bazel (which builds LLVM from source for | |
| you) or with Cargo against your own LLVM, Abseil, and Protobuf installation. | |
| ### Bazel | |
| This is how Crubit's CI builds the tool. Bazel downloads the Rust and Clang | |
| toolchains, and it builds LLVM from source at the commit pinned in | |
| [`MODULE.bazel`](https://github.com/google/crubit/blob/main/MODULE.bazel). | |
| Because it builds LLVM, the first build takes a long time. | |
| Prerequisites: `bazelisk`, `python3`, and the development headers for zlib, | |
| libxml2, and zstd in `/usr/include`. On Debian or Ubuntu, install them with | |
| `apt install zlib1g-dev libxml2-dev libzstd-dev`. | |
| ```sh | |
| git clone https://github.com/google/crubit.git | |
| cd crubit | |
| bazelisk build //rs_bindings_from_cc:rs_bindings_from_cc_main | |
| ``` | |
| To build against a different `llvm-project` commit, set the | |
| `CRUBIT_LLVM_COMMIT` environment variable to the full commit SHA. | |
| ### Cargo, with your own LLVM, Abseil, and Protobuf | |
| This option is for packagers and for projects that already build LLVM, such as | |
| Chromium. CI doesn't test it. | |
| #### Prerequisites | |
| * LLVM and Clang libraries, built and installed from the `llvm-project` | |
| commit pinned in `MODULE.bazel` (or one close to it). | |
| * They must be built with compression support (zlib), which is the | |
| default build config. | |
| * Abseil libraries, built and installed. | |
| * Protobuf libraries and the `protoc` compiler (v27.1 or later), installed. | |
| Crubit's CI uses Protobuf 36.1. | |
| * zlib (for example, `libz.so`) in the system include and lib paths. | |
| * A recent Rust toolchain. In a Crubit checkout, `rustup` automatically | |
| selects the nightly toolchain from `rust-toolchain.toml`. | |
| Linux-specific setup: | |
| ```sh | |
| # 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 (untested): | |
| ```sh | |
| 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. | |
| ```sh | |
| # 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: | |
| ```sh | |
| # Pre-generate the C++ headers for Crubit's own .proto files. This avoids | |
| # races during the parallel Cargo build. | |
| python3 cargo/build/generate_proto_headers.py \ | |
| --protoc=/path/to/protoc --out_dir=/path/to/generated_headers | |
| export PROTOC=/path/to/protoc | |
| # Paths for Crubit's cargo to use. Most accept a comma-separated list. | |
| ## 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. On Windows it may also hold the | |
| ## import libraries of LLVM's DLLs (LLVM-C.lib and friends); those are recognised by | |
| ## their contents and skipped, so the whole `lib` dir can be given as-is. | |
| 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 | |
| ## These paths contain google/protobuf/ dir with all the includes, and the | |
| ## headers generated above. | |
| export PROTOBUF_INCLUDE_PATH=/path/to/protobuf/include/dir,/path/to/generated_headers | |
| ## This path contains libprotobuf.a and libutf8_validity.a. Other archives that a | |
| ## protobuf install tree holds (libutf8_range.a, libprotobuf-lite.a, libprotoc.a, | |
| ## libupb.a) are ignored; the first two would collide with the ones above. | |
| export PROTOBUF_LIB_STATIC_PATH=/path/to/protobuf/libs | |
| # Tell Crubit which LLVM it is compiled against, as the commit date (YYYYMMDD) of | |
| # your llvm-project checkout. | |
| LLVM_DATE=$(python3 cargo/build/get_llvm_commit_date.py <llvm_commit_sha>) | |
| export CXXFLAGS="$CXXFLAGS -DCRUBIT_LLVM_DEV_DATE=${LLVM_DATE}" | |
| cargo build --locked --release -p rs_bindings_from_cc | |
| ``` | |
| [Cargo build of Crubit](../overview/cargo_build.md#custom-build-systems-chromium-android-or-other-projects) | |
| explains each of these variables in more detail. | |
| If you need to build LLVM and Clang yourself, here is an example: | |
| ```sh | |
| 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 | |
| ``` |