Skip to content

Bazel First-Time Setup

This document describes how to configure Bazel to connect to an EngFlow Remote Execution cluster.

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.

BUILD
platform(
    name = "platform",
    constraint_values = [
        "@platforms//os:linux",
        "@platforms//cpu:x86_64",
    ],
    exec_properties = {
        "container-image": "docker://gcr.io/bazel-public/ubuntu2004-java11@sha256:69a78f121230c6d5cbfe2f4af8ce65481aa3f2acaaaf8e899df335f1ac1b35b5",
    },
)

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.

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.

Configure Bazel to use the EngFlow platform in .bazelrc.

  1. Add common flags:

    .bazelrc
    build:engflow --define=EXECUTOR=remote
    build:engflow --disk_cache=
    build:engflow --experimental_inmemory_dotd_files
    build:engflow --experimental_inmemory_jdeps_files
    build:engflow --incompatible_strict_action_env=true
    build:engflow --remote_timeout=600
    build:engflow --nolegacy_important_outputs
    build:engflow --grpc_keepalive_time=30s
    # Compress uploads and downloads between Bazel and the cluster for faster data transfer.
    #
    # This is recommended for Bazel 5 and later.
    build:engflow --experimental_remote_cache_compression=true
    

  2. Add platform flags:

    .bazelrc
    1
    2
    3
    build:engflow --host_platform=//engflow_config/config:platform
    build:engflow --platforms=//engflow_config/config:platform
    build:engflow --extra_execution_platforms=//engflow_config/config:platform
    

  3. If not using a custom C++ toolchain already, add flags for the container's C++ toolchain. Make sure to set --crosstool_top to a cc_toolchain_suite target, and --cpu and --compiler to match an entry in its toolchains attribute. Also set the --host_* versions of these flags unless you're cross-compiling with a different toolchain.

    .bazelrc
    1
    2
    3
    4
    5
    6
    7
    build:engflow --action_env=BAZEL_DO_NOT_DETECT_CPP_TOOLCHAIN=1
    build:engflow --crosstool_top=//engflow_config/cc:toolchain
    build:engflow --host_crosstool_top=//engflow_config/cc:toolchain
    build:engflow --cpu=k8
    build:engflow --host_cpu=k8
    build:engflow --compiler=clang
    build:engflow --host_compiler=clang
    
  4. If Java is required, optionally use the hermetic JDK shipped with Bazel:

    .bazelrc
    build:engflow --java_runtime_version=remotejdk_11
    
  5. 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.

    If you use TLS with our certificate (engflow-ca.crt):

    .bazelrc
    1
    2
    3
    4
    5
    build:engflow --remote_cache=grpcs://<CLUSTER_ENDPOINT>
    build:engflow --remote_executor=grpcs://<CLUSTER_ENDPOINT>
    build:engflow --bes_backend=grpcs://<CLUSTER_ENDPOINT>
    build:engflow --bes_results_url=https://<CLUSTER_ENDPOINT>/invocation/
    build:engflow --tls_certificate=<PATH>/engflow-remote-execution/engflow-ca.crt
    

    If you don't use TLS at all:

    .bazelrc
    1
    2
    3
    4
    build:engflow --remote_cache=grpc://<CLUSTER_ENDPOINT>
    build:engflow --remote_executor=grpc://<CLUSTER_ENDPOINT>
    build:engflow --bes_backend=grpc://<CLUSTER_ENDPOINT>
    build:engflow --bes_results_url=http://<CLUSTER_ENDPOINT>/invocation/
    

Usage

We recommend using the latest available Bazel version.

Bash
bazel build --config=engflow //foo:bar