Bazel disk cache

This document describes how to configure and use a local disk cache for Bazel artifacts in your Fuchsia development environment.

Overview

The Fuchsia build system uses Bazel for building certain parts of the system. By default, Bazel stores its cache inside the build directory (e.g., out/default/bazel-*). If you clean your build directory (for example, by running fx clean-build or rm -rf out), this cache is lost, and Bazel must rebuild everything from scratch.

You can configure a persistent, shared disk cache that survives build directory cleans and can be shared across multiple Fuchsia checkouts and/or build directories on the same machine.

Benefits of a shared disk cache

  • Faster Clean Builds: When you run a clean build, Bazel can retrieve previously built actions and artifacts from the disk cache instead of rebuilding them.

  • Shared Across Checkouts: If you work with multiple Fuchsia checkouts on the same machine, they can all share the same disk cache. Artifacts built in one checkout can be reused in another, saving time and disk space.

  • Shared Across Build Directories: If you switch between different build directories in the same checkout, actions that are identical between them (including input contents) will automatically benefit from the cache too.

  • Shared Accross Branches: If you frequently switch between branches, while using the same build directory, incremental builds will also benefit from the disk cache.

  • Complements Remote Caching (RBE): Bazel's disk cache is compatible with remote caching. Even when Remote Build Execution (RBE) is enabled, a local disk cache is often faster because it avoids network latency when retrieving cached artifacts. It also allows you to work offline for targets you have already built.

Enabling the Bazel disk cache

To enable the disk cache, set the FUCHSIA_BAZEL_DISK_CACHE environment variable to an absolute path of a directory where you want to store the cache.

For example, add the following line to your shell startup script (e.g., ~/.bashrc or ~/.zshrc):

export FUCHSIA_BAZEL_DISK_CACHE="$HOME/.fuchsia_bazel_cache"

The build system will automatically create the directory if it does not exist.

Managing cache size (Garbage Collection)

By default, the disk cache will grow indefinitely. To prevent it from consuming too much disk space, you can enable automatic garbage collection by setting the FUCHSIA_BAZEL_DISK_CACHE_SIZE environment variable.

This variable specifies the maximum size of the cache. Bazel will periodically clean up older cached items in the background when it is idle to stay under this limit.

Add the following line to your shell startup script, specifying the desired limit (e.g., 40G for 40 Gigabytes):

export FUCHSIA_BAZEL_DISK_CACHE_SIZE="40G"

The size can be specified in bytes, or optionally followed by K, M, G, or T.

If FUCHSIA_BAZEL_DISK_CACHE_SIZE is not set, you must manage the cache size manually (e.g., by deleting the directory contents when it grows too large).

Avoiding caching for large artifacts

Caching is not always beneficial; for example, for targets that generate large artifacts which change often, such as product assembly. Bazel provides several ways to avoid caching these artifacts.

For individual target definitions, the tags attribute, common to all rules, can be used. For example:

genrule(
    name = "create_large_archive",
    ...

    # No need to run this remotely, nor cache the archive.
    tags = ["no-cache", "no-remote"],
)

For custom rules, the implementation function should invoke ctx.actions.run() with an execution_requirements attribute set to a dictionary mapping tag strings to the string literal "1". Note that using True or the integer 1 will not work, which is not properly documented. For example:

def _my_rule_impl(ctx):
    ...
    ctx.actions.run(
        ...,
        execution_requirements = {
            "no-cache": "1",
            "no-remote": "1",
        },
    )
    ...

my_rule = rule(
    implementation = _my_rule_impl,
    ...
)

In this case, all my_rule() target artifacts will automatically not be cached (or remoted).