Bazel First-Time Setup¶
This document describes how to configure Bazel to connect to an EngFlow Remote Execution cluster.
You also need a credential
This page covers only the project configuration your whole repository shares.
You also need a credential of your own. Get one from your cluster's Getting
Started page at https://<CLUSTER_ENDPOINT>/gettingstarted, then add the
matching flags when you set up .bazelrc.
1. Prepare a Docker container image for remote actions¶
Refer to Create a container image for remote actions, which describes the requirements for a container image, how to build a new image, and where to store your image for best performance.
If you already have a container image you use for local execution in CI, make sure it meets the requirements, then use that. Ideally, your local and remote environments are similar so actions may run either locally or remotely.
To proceed, you'll need to know your container image's URL, including its SHA-256 sum. A complete URL looks like docker://gcr.io/bazel-public/ubuntu2004-java11@sha256:69a78f121230c6d5cbfe2f4af8ce65481aa3f2acaaaf8e899df335f1ac1b35b5. If your container image is stored on a private registry, you'll also need to ensure EngFlow workers are authorized to pull from it. Ask EngFlow support if you're unsure.
2. Create a remote platform configuration¶
In Bazel, a platform expresses an environment where an action can run. When performing remote execution, Bazel is instructed to build for a special EngFlow platform. This platform carries the Docker image and other environmental configuration to the remote execution service.
Skip this step if your project already defines a platform target for the
remote environment. Add the constraints or exec_properties you need to that
target instead of defining a second one.
Match your workers' operating system and CPU
The constraint_values must match the operating system and CPU architecture
of your remote workers. The example below is Linux on x86_64. If your workers
run Windows, start from //platform/windows_x64 instead, and read
Windows remote execution for the differences that affect containers,
toolchains, and paths.
| BUILD | |
|---|---|
If your remote actions require internet access, add "dockerNetwork": "standard" to exec_properties.
For an example, see //platform/linux_x64 or //platform/windows_x64 in our example repository.
3. Create a C++ toolchain configuration.¶
To construct C/C++ commands that can run remotely, Bazel needs a C++ toolchain configuration. If you have installed a C++ toolchain in your container image, refer to Create a Bazel C++ toolchain configuration for remote actions.
A C++ toolchain configuration embeds compiler, header, and library paths that are specific to your container image, so you generate it rather than copy it from elsewhere. The fastest starting point is //platform/linux_x64 or //platform/windows_x64 in our example repository, which each pair a generated toolchain with the matching platform target.
You will likely need a C++ toolchain, even if you don't develop C++ code directly. Many Bazel rulesets use C++ for tools and wrappers.
4. Set up .bazelrc.¶
Info
User-specific configuration can be included in .bazelrc using the try-import directive, typically at the end of the file. For example:
| .bazelrc | |
|---|---|
Configure Bazel to use the EngFlow platform in .bazelrc.
-
Add common flags:
- Compress uploads and downloads between Bazel and the cluster for faster data transfer. This is recommended for Bazel 5 onwards.
- Log executed spawns into the specified file. Used to display invocation-level insights in the UI. Stable and supported from Bazel 7.4.0 onwards.
- Upload build events surfaced as invocation-level insights in the UI.
-
Add platform flags. Replace
<YOUR_PLATFORM_PACKAGE>with the package where you defined theplatformtarget in step 2:.bazelrc The package is the directory holding that
BUILDfile, relative to your workspace root, and the part after the colon is the target name. Our example repository definesplatform(name = "linux_x64")inplatform/linux_x64/BUILDand registers it like this:.bazelrc //platform/linux_x64is shorthand for//platform/linux_x64:linux_x64, since the target and its directory share a name. Naming the config after the platform —remote_linux_x64,remote_macos_arm64,remote_windows_x64— lets you choose the remote environment on the command line with--config.The last flag registers the C++ toolchain from step 3 through toolchain resolution, which is how current Bazel selects a C++ toolchain. It replaces the
--crosstool_top,--cpu, and--compilerflags in the next substep, which are no-ops on Bazel 8 and later. -
On Bazel 7 and earlier, add flags for the container's C++ toolchain instead of
--extra_toolchains. Make sure to set--crosstool_topto acc_toolchain_suitetarget, and--cpuand--compilerto match an entry in itstoolchainsattribute. Also set the--host_*versions of these flags unless you're cross-compiling with a different toolchain. Replace<YOUR_CC_TOOLCHAIN_PACKAGE>with the package holding the toolchain you created in step 3. -
If Java is required, optionally use the hermetic JDK shipped with Bazel:
.bazelrc -
Add the remote executor flags. For the
<CLUSTER_ENDPOINT>, use the host name or IP address of the Load Balancer. You may also have to specify the port, if using a non-standard one. The default ports are 443 for grpc/s, and 80 for http/s.Before you go on, go back to your cluster's Getting Started page at
https://<CLUSTER_ENDPOINT>/gettingstartedand get your credential — an mTLS certificate or a JWT token, depending on how your cluster authenticates. You add the matching flags in the next step, and remote builds fail without them.If you use TLS, connect over
grpcs:You usually don't need
--tls_certificateLeave
--tls_certificateout if your cluster's server certificate comes from a public CA, which is the common case. Bazel already trusts public CAs.Add it only when your cluster uses a private or internal CA that Bazel does not trust, and point it at that CA's certificate.
-
Add your authentication flags. Which flags you need depends on how your cluster authenticates gRPC clients. Your cluster's Getting Started page at
https://<CLUSTER_ENDPOINT>/gettingstartedshows the mechanism it uses, lets you create a credential, and emits the exact flags to copy.Mechanism Bazel flags Where to read more mTLS client certificate --tls_client_certificate,--tls_client_keyBuild the example project; mTLS Credential helper ( ef)--credential_helper=<CLUSTER_HOSTNAME>=efUse efas a credential helper; Credential helperCluster-issued JWT --remote_headerand--bes_header, each set tox-engflow-auth-method=jwt-v0and tox-engflow-auth-token=<token>JWT OIDC federation --remote_header=x-engflow-auth-method=oidcand--remote_header=Authorization=Bearer <token>OIDC federation GitHub token (deprecated) --remote_header=Authorization=Bearer <token>GitHub Tokens For
--credential_helper,<CLUSTER_HOSTNAME>is a bare host name: the scope takes no port, unlike<CLUSTER_ENDPOINT>above.--remote_headerapplies to the remote cache and executor only, so for any header-based mechanism, pass the same headers with--bes_headeras well. Otherwise build event uploads fail to authenticate. TLS client credentials apply to every channel, so mTLS needs no header flags.Credentials are per user, so put these flags in
.bazelrc.userrather than the checked-in.bazelrc.--tls_certificateis not a client credentialBazel's
--tls_certificateflag configures the CA that Bazel trusts to sign your cluster's server certificate, for the case where that CA is not one Bazel already trusts. Do not point it at a client certificate; use--tls_client_certificateand--tls_client_keyfor that.
Usage¶
We recommend using the latest available Bazel version.
| Bash | |
|---|---|