bazel_ci_rules)This folder contains the unified, GCS-free, and Remote Build Execution (RBE) toolchain generator rule (rbe_config).
It automates the generation of RBE toolchain configurations dynamically on-the-fly, eliminating the maintenance overhead of pre-generating and uploading configurations to Google Cloud Storage (GCS) buckets when new Bazel versions are released.
docker vs host): Supports both standard Docker-out-of-Docker generation (default when RBE_CONFIG_CONTAINER is unset) and direct host environment generation (automatically enabled when RBE_CONFIG_CONTAINER is set).RBE_CONFIG_CONTAINER is exported, rbe_configs_gen compiles natively on the host using go build and runs with --exec_mode=host, executing C++ and Java auto-detection (@@rules_cc..., java -version) against the host filesystem without Docker. The target container image is authoritative from the RBE_CONFIG_CONTAINER environment variable.rules/rbe_presets.json) on the master branch of this repository. At runtime, the repository rule dynamically downloads this file. If the CI maintainers update a container image tag or environment parameter on master, all projects immediately receive the update without modifying their pinned ruleset commit hashes!MODULE.bazel)To configure RBE toolchains using Bzlmod (Bazel 8.0.0+), load and use the rbe_config_extension module extension:
Simply pass the name of a standard preset (e.g. "ubuntu"):
bazel_dep(name = "bazel_ci_rules", version = "2.0.0") # Load and instantiate the RBE config module extension rbe = use_extension("@bazel_ci_rules//:rbe_config.bzl", "rbe_config_extension") rbe.config( name = "rbe_ubuntu", # Standard target repository name preset = "ubuntu", # Request the generic latest Ubuntu preset ) use_repo(rbe, "rbe_ubuntu")
If you are using a custom compiler container or customized settings, specify the target image and C++ compiler environment directly inside the tag:
bazel_dep(name = "bazel_ci_rules", version = "2.0.0") rbe = use_extension("@bazel_ci_rules//:rbe_config.bzl", "rbe_config_extension") rbe.config( name = "rbe_ubuntu", container = "gcr.io/my-custom/image:latest", cpp_env = { "CC": "gcc", "ABI_LIBC_VERSION": "glibc_2.39", "ABI_VERSION": "gcc", "BAZEL_COMPILER": "gcc", "BAZEL_HOST_SYSTEM": "i686-unknown-linux-gnu", "BAZEL_TARGET_CPU": "k8", "BAZEL_TARGET_LIBC": "glibc_2.39", "BAZEL_TARGET_SYSTEM": "x86_64-unknown-linux-gnu", "CC_TOOLCHAIN_NAME": "linux_gnu_x86" } ) use_repo(rbe, "rbe_ubuntu")
If your repository has not migrated to Bzlmod yet, load and call the rbe_config macro inside your WORKSPACE file:
load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive") http_archive( name = "bazel_ci_rules", strip_prefix = "bazel_ci_rules-2.0.0", # Pre-packaged release prefix url = "https://github.com/bazelbuild/continuous-integration/releases/download/rules-2.0.0/bazel_ci_rules-2.0.0.tar.gz", # Official 2.0.0 tarball release ) load("@bazel_ci_rules//:rbe_config.bzl", "rbe_config") rbe_config( name = "rbe_ubuntu", preset = "ubuntu", # Request the standard 'ubuntu' preset dynamically )
load("@bazel_ci_rules//:rbe_config.bzl", "rbe_config") rbe_config( name = "rbe_ubuntu", spec = { "container": "gcr.io/my-custom/image:latest", "cpp_env": { "CC": "gcc", "CC_TOOLCHAIN_NAME": "linux_gnu_x86", # ... } } )
Once your workspace is configured with the rbe_ubuntu repository, you can compile and test your targets remotely on GCP by passing the standard Remote Execution flags:
bazel build \ --extra_toolchains=@rbe_ubuntu//config:cc-toolchain \ --extra_execution_platforms=@rbe_ubuntu//config:platform \ --host_platform=@rbe_ubuntu//config:platform \ --platforms=@rbe_ubuntu//config:platform \ --javabase=@rbe_ubuntu//java:jdk \ --host_javabase=@rbe_ubuntu//java:jdk \ --remote_executor=remotebuildexecution.googleapis.com \ --remote_instance_name=projects/YOUR_GCP_PROJECT/instances/YOUR_RBE_INSTANCE \ --google_default_credentials \ //path/to:your_target
--extra_toolchains=@rbe_ubuntu//config:cc-toolchain: Registers the dynamically auto-detected C++ compiler toolchain.--extra_execution_platforms / --platforms: Configures Bazel to execute actions and target outputs inside the container's platform environment.--javabase / --host_javabase=@rbe_ubuntu//java:jdk: Resolves Java compilations and host execution using the JDK detected inside the container.--remote_executor: The gRPC endpoint of the Google Remote Build Execution service.--remote_instance_name: The RBE instance mapped specifically to your Google Cloud Platform (GCP) project.--google_default_credentials: Authenticates your remote requests natively using your Google Application Default Credentials (ADC) or system gcloud login.docker vs host)rbe_config supports two execution modes for toolchain auto-detection, automatically selected based on your environment:
--exec_mode=docker, Default)When RBE_CONFIG_CONTAINER is unset (e.g., on developer workstations running macOS or Linux):
rbe_configs_gen is compiled inside a sibling golang:1.21 Docker container using Docker-out-of-Docker (/var/run/docker.sock). No local Go compiler is required.rbe_configs_gen pulls and runs the target toolchain container image (from preset or spec["container"]), mounts host Bazel, and runs C++ and Java auto-detection inside the sandboxed container.--exec_mode=host, Automatic in Container CI)When the RBE_CONFIG_CONTAINER environment variable is exported (e.g., in containerized CI workers or Buildkite pipelines):
rbe_config automatically switches to host mode.rbe_configs_gen is compiled natively on the host using go build (requires Go installed in PATH; no Docker required).rbe_configs_gen runs with --exec_mode=host, discovering C++ compilers (gcc/clang) and JDK runtimes directly from the host filesystem without invoking Docker.host mode, because detection happens against the host filesystem, the RBE execution platform image in @rbe_ubuntu//config:platform is authoritatively determined by RBE_CONFIG_CONTAINER (overriding any requested preset container image to prevent ABI or toolchain discrepancies).To generate toolchain configurations, rbe_config must determine which Bazel version to target and potentially mount a host Bazel binary inside the compiler container. It resolves this using the following four-tier precedence lookup strategy:
RBE_CONFIG_BAZEL_PATH Environment Variable: (Highest Precedence) Explicitly forces the generator to use this host Bazel binary (passes --host_bazel_path to the generator).BAZEL_REAL Environment Variable: Forces the generator to use this real host Bazel binary (usually set by wrappers like Bazelisk) and passes it as --host_bazel_path.native.bazel_version Detection: Automatically detects the version string of the running Bazel (e.g., "9.1.0" or "8.4.2"). If found, it passes --bazel_version to rbe_configs_gen, which allows the generator to fetch the matching Bazel release inside the container cleanly without copying host binaries.PATH scan: (Fallback) If no explicit path is set and version detection fails (e.g., on untagged development builds), it scans the host PATH for bazel and copies it into the container.Note: When invoking a custom or locally built Bazel binary directly (e.g.,
/tmp/bazel build ...),BAZEL_REALandnative.bazel_versionare unset, sorbe_configfalls back tobazelinPATH. If thatPATHentry is missing or is a wrapper script (such as/usr/bin/bazelfrom the apt package), toolchain generation fails and reports which Bazel binary and resolution source were selected. SetRBE_CONFIG_BAZEL_PATH=/path/to/bazelto point to a standalone Bazel binary.
If you run custom development layouts or want to force a specific Bazel binary override, choose one of the following methods:
Export the path to your executable in your active terminal session before running the build:
export RBE_CONFIG_BAZEL_PATH=/path/to/your/custom_bazel bazel build //...
tools/bazel Wrapper (Recommended)Creating a wrapper script at tools/bazel at the root of your workspace is the cleanest, zero-configuration way. Bazel and Bazelisk automatically execute this wrapper, which can capture the real running binary path (BAZEL_REAL). Our rule will automatically pick up BAZEL_REAL and prioritize it over native.bazel_version:
#!/bin/bash # tools/bazel # This wrapper script is executed automatically by Bazelisk # BAZEL_REAL will be automatically detected and prioritized by rbe_config exec "${BAZEL_REAL}" "$@"