Skip to content

Bazel Cheatsheet

Overview

Bazel is a fast, scalable, multi-language build tool developed by Google. It supports large codebases, provides fast incremental builds, and offers reproducible builds across different platforms.

Installation

Package Managers

bash
# macOS
brew install bazel

# Ubuntu/Debian
curl -fsSL https://bazel.build/bazel-release.pub.gpg | gpg --dearmor > bazel.gpg
sudo mv bazel.gpg /etc/apt/trusted.gpg.d/
echo "deb [arch=amd64] https://storage.googleapis.com/bazel-apt stable jdk1.8" | sudo tee /etc/apt/sources.list.d/bazel.list
sudo apt update && sudo apt install bazel

# CentOS/RHEL
sudo dnf copr enable vbatts/bazel
sudo dnf install bazel

# Windows (Chocolatey)
choco install bazel

# Manual installation
wget https://github.com/bazelbuild/bazel/releases/download/6.0.0/bazel-6.0.0-installer-linux-x86_64.sh
chmod +x bazel-6.0.0-installer-linux-x86_64.sh
./bazel-6.0.0-installer-linux-x86_64.sh --user

Verification

bash
bazel version

Basic Concepts

Key Terms

Workspace    # Root directory containing WORKSPACE file
Package      # Directory containing BUILD file
Target       # Buildable unit (binary, library, test)
Label        # Unique identifier for targets
Rule         # Function that defines how to build targets

Project Structure

workspace/
├── WORKSPACE
├── .bazelrc
├── BUILD
├── src/
│   ├── main/
│   │   ├── java/
│   │   └── BUILD
│   └── test/
│       ├── java/
│       └── BUILD
└── third_party/
    └── BUILD

WORKSPACE File

Basic WORKSPACE

python
workspace(name = "my_project")

# Load rules
load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")

# Java rules
http_archive(
    name = "rules_java",
    urls = ["https://github.com/bazelbuild/rules_java/releases/download/6.0.0/rules_java-6.0.0.tar.gz"],
    sha256 = "469b7f3b580b4fcf8112f4d6d0d5a4ce8e1ad5e21fee67d8e8335d5f018f7a4a",
)

# Python rules
http_archive(
    name = "rules_python",
    sha256 = "8c8fe44ef0a9afc256d1e75ad5f448bb59b81aba149b8958f02f7b3a98f5d9b4",
    strip_prefix = "rules_python-0.13.0",
    url = "https://github.com/bazelbuild/rules_python/archive/refs/tags/0.13.0.tar.gz",
)

# Go rules
http_archive(
    name = "io_bazel_rules_go",
    sha256 = "099a9fb96a376ccbbb7d291ed4ecbdfd42f6bc822ab77ae6f1b5cb9e914e94fa",
    urls = [
        "https://mirror.bazel.build/github.com/bazelbuild/rules_go/releases/download/v0.35.0/rules_go-v0.35.0.zip",
        "https://github.com/bazelbuild/rules_go/releases/download/v0.35.0/rules_go-v0.35.0.zip",
    ],
)

load("@io_bazel_rules_go//go:deps.bzl", "go_register_toolchains", "go_rules_dependencies")
go_rules_dependencies()
go_register_toolchains(version = "1.19.3")

External Dependencies

python
# Maven dependencies
load("@rules_jvm_external//:defs.bzl", "maven_install")

maven_install(
    artifacts = [
        "junit:junit:4.13.2",
        "com.google.guava:guava:31.1-jre",
        "org.apache.commons:commons-lang3:3.12.0",
    ],
    repositories = [
        "https://repo1.maven.org/maven2",
    ],
)

# Git repository
load("@bazel_tools//tools/build_defs/repo:git.bzl", "git_repository")

git_repository(
    name = "com_google_protobuf",
    remote = "https://github.com/protocolbuffers/protobuf",
    tag = "v3.21.7",
)

# Local repository
local_repository(
    name = "my_local_repo",
    path = "/path/to/local/repo",
)

BUILD Files

Java Example

python
# Load rules
load("@rules_java//java:defs.bzl", "java_binary", "java_library", "java_test")

# Java library
java_library(
    name = "hello-lib",
    srcs = ["src/main/java/com/example/Hello.java"],
    deps = [
        "@maven//:com_google_guava_guava",
        "@maven//:org_apache_commons_commons_lang3",
    ],
    visibility = ["//visibility:public"],
)

# Java binary
java_binary(
    name = "hello-world",
    srcs = ["src/main/java/com/example/Main.java"],
    main_class = "com.example.Main",
    deps = [":hello-lib"],
)

# Java test
java_test(
    name = "hello-test",
    srcs = ["src/test/java/com/example/HelloTest.java"],
    test_class = "com.example.HelloTest",
    deps = [
        ":hello-lib",
        "@maven//:junit_junit",
    ],
)

Python Example

python
load("@rules_python//python:defs.bzl", "py_binary", "py_library", "py_test")

# Python library
py_library(
    name = "hello_lib",
    srcs = ["hello_lib.py"],
    deps = [
        "@pip//requests",
        "@pip//numpy",
    ],
    visibility = ["//visibility:public"],
)

# Python binary
py_binary(
    name = "hello_world",
    srcs = ["main.py"],
    deps = [":hello_lib"],
    python_version = "PY3",
)

# Python test
py_test(
    name = "hello_test",
    srcs = ["hello_test.py"],
    deps = [
        ":hello_lib",
        "@pip//pytest",
    ],
)

Go Example

python
load("@io_bazel_rules_go//go:def.bzl", "go_binary", "go_library", "go_test")

# Go library
go_library(
    name = "hello_lib",
    srcs = ["hello.go"],
    importpath = "github.com/example/hello",
    visibility = ["//visibility:public"],
    deps = [
        "@com_github_gorilla_mux//:mux",
    ],
)

# Go binary
go_binary(
    name = "hello_world",
    embed = [":hello_lib"],
)

# Go test
go_test(
    name = "hello_test",
    srcs = ["hello_test.go"],
    embed = [":hello_lib"],
)

C++ Example

python
load("@rules_cc//cc:defs.bzl", "cc_binary", "cc_library", "cc_test")

# C++ library
cc_library(
    name = "hello_lib",
    srcs = ["hello.cc"],
    hdrs = ["hello.h"],
    deps = [
        "@com_google_absl//absl/strings",
    ],
    visibility = ["//visibility:public"],
)

# C++ binary
cc_binary(
    name = "hello_world",
    srcs = ["main.cc"],
    deps = [":hello_lib"],
)

# C++ test
cc_test(
    name = "hello_test",
    srcs = ["hello_test.cc"],
    deps = [
        ":hello_lib",
        "@com_google_googletest//:gtest_main",
    ],
)

Command Line Usage

Basic Commands

bash
# Build target
bazel build //src:hello-world
bazel build //...  # Build all targets

# Run binary
bazel run //src:hello-world

# Test
bazel test //src:hello-test
bazel test //...  # Test all targets

# Clean
bazel clean
bazel clean --expunge  # Deep clean

# Query
bazel query //...
bazel query "deps(//src:hello-world)"

# Info
bazel info
bazel version

Advanced Options

bash
# Parallel builds
bazel build //... --jobs=8

# Verbose output
bazel build //... --verbose_failures

# Compilation mode
bazel build //... --compilation_mode=opt  # optimized
bazel build //... --compilation_mode=dbg  # debug

# Platform-specific builds
bazel build //... --platforms=@io_bazel_rules_go//go/toolchain:linux_amd64

# Remote execution
bazel build //... --remote_executor=grpc://remote-executor:8980

# Build with specific flags
bazel build //... --copt=-O2 --linkopt=-static

# Test with specific options
bazel test //... --test_output=all --test_verbose_timeout_warnings

Configuration

bash
# Use .bazelrc file
bazel build //...  # Uses settings from .bazelrc

# Override config
bazel build //... --config=release

# Set flags
bazel build //... --define=version=1.0.0

Configuration (.bazelrc)

Basic Configuration

bash
# Build settings
build --compilation_mode=opt
build --copt=-O2
build --copt=-DNDEBUG

# Test settings
test --test_output=errors
test --test_verbose_timeout_warnings

# Common flags
common --enable_platform_specific_config

# Platform-specific settings
build:linux --copt=-fPIC
build:macos --copt=-Wno-deprecated-declarations
build:windows --copt=/W3

# Configuration aliases
build:release --compilation_mode=opt --strip=always
build:debug --compilation_mode=dbg --strip=never

# Remote execution
build:remote --remote_executor=grpc://remote-executor:8980
build:remote --remote_cache=grpc://remote-cache:8981

Advanced Configuration

bash
# Memory settings
build --local_ram_resources=8192
build --local_cpu_resources=8

# Disk cache
build --disk_cache=/tmp/bazel-cache

# Remote cache
build --remote_cache=https://storage.googleapis.com/my-bazel-cache

# Build event service
build --bes_backend=grpc://build-event-service:8982
build --bes_results_url=https://my-build-results.com/

# Execution strategies
build --spawn_strategy=sandboxed
build --strategy=Javac=worker
build --strategy=CppCompile=sandboxed

# Sandboxing
build --sandbox_debug
build --sandbox_writable_path=/tmp

Rules and Macros

Custom Rules

python
# rules.bzl
def _my_rule_impl(ctx):
    output = ctx.actions.declare_file(ctx.label.name + ".out")
    ctx.actions.run_shell(
        inputs = ctx.files.srcs,
        outputs = [output],
        command = "cat {} > {}".format(" ".join([f.path for f in ctx.files.srcs]), output.path),
    )
    return [DefaultInfo(files = depset([output]))]

my_rule = rule(
    implementation = _my_rule_impl,
    attrs = {
        "srcs": attr.label_list(allow_files = True),
    },
)

Macros

python
# macros.bzl
def java_service(name, srcs, deps = [], **kwargs):
    """Macro to create a Java service with common dependencies."""
    java_library(
        name = name + "_lib",
        srcs = srcs,
        deps = deps + [
            "@maven//:com_google_guava_guava",
            "@maven//:org_slf4j_slf4j_api",
        ],
        **kwargs
    )
    
    java_binary(
        name = name,
        main_class = "com.example.Main",
        runtime_deps = [name + "_lib"],
        **kwargs
    )

# Usage in BUILD file
load("//tools:macros.bzl", "java_service")

java_service(
    name = "my_service",
    srcs = ["Main.java", "Service.java"],
    deps = ["//common:utils"],
)

Aspects

python
# aspects.bzl
def _print_aspect_impl(target, ctx):
    print("Target: %s" % target.label)
    return []

print_aspect = aspect(
    implementation = _print_aspect_impl,
    attr_aspects = ["deps"],
)

# Usage
bazel build //src:hello-world --aspects=//tools:aspects.bzl%print_aspect

Testing

Test Configuration

python
# BUILD file
java_test(
    name = "integration_test",
    srcs = ["IntegrationTest.java"],
    deps = [
        ":hello_lib",
        "@maven//:junit_junit",
    ],
    size = "large",
    timeout = "long",
    tags = ["integration"],
    data = ["//testdata:sample_files"],
    jvm_flags = ["-Xmx2g"],
)

# Test suite
test_suite(
    name = "all_tests",
    tests = [
        ":unit_tests",
        ":integration_tests",
    ],
)

Test Execution

bash
# Run specific test
bazel test //src:hello_test

# Run tests by tag
bazel test //... --test_tag_filters=unit
bazel test //... --test_tag_filters=-integration

# Run tests by size
bazel test //... --test_size_filters=small,medium

# Parallel test execution
bazel test //... --local_test_jobs=4

# Test with coverage
bazel coverage //src:hello_test

Multi-Language Projects

Workspace Setup

python
# WORKSPACE
workspace(name = "multi_lang_project")

# Java
load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
http_archive(name = "rules_java", ...)

# Python
http_archive(name = "rules_python", ...)
load("@rules_python//python:pip.bzl", "pip_install")
pip_install(
    name = "pip",
    requirements = "//python:requirements.txt",
)

# Go
http_archive(name = "io_bazel_rules_go", ...)
load("@io_bazel_rules_go//go:deps.bzl", "go_register_toolchains", "go_rules_dependencies")
go_rules_dependencies()
go_register_toolchains(version = "1.19.3")

# Protocol Buffers
http_archive(name = "com_google_protobuf", ...)
load("@com_google_protobuf//:protobuf_deps.bzl", "protobuf_deps")
protobuf_deps()

Cross-Language Dependencies

python
# proto/BUILD
load("@rules_proto//proto:defs.bzl", "proto_library")
load("@rules_java//java:defs.bzl", "java_proto_library")
load("@io_bazel_rules_go//proto:def.bzl", "go_proto_library")

proto_library(
    name = "api_proto",
    srcs = ["api.proto"],
    visibility = ["//visibility:public"],
)

java_proto_library(
    name = "api_java_proto",
    deps = [":api_proto"],
)

go_proto_library(
    name = "api_go_proto",
    importpath = "github.com/example/api",
    proto = ":api_proto",
)

# java/BUILD
java_library(
    name = "java_service",
    srcs = ["Service.java"],
    deps = ["//proto:api_java_proto"],
)

# go/BUILD
go_library(
    name = "go_service",
    srcs = ["service.go"],
    deps = ["//proto:api_go_proto"],
)

Performance Optimization

Build Performance

bash
# .bazelrc optimizations
build --local_ram_resources=HOST_RAM*.8
build --local_cpu_resources=HOST_CPUS
build --jobs=auto

# Disk cache
build --disk_cache=/tmp/bazel-cache

# Remote cache
build --remote_cache=grpc://cache-server:8080

# Build without the bytes
build --remote_download_minimal

# Incremental builds
build --experimental_reuse_sandbox_directories

Memory Management

bash
# Limit memory usage
build --local_ram_resources=8192  # 8GB
startup --host_jvm_args=-Xmx4g

# Garbage collection
startup --host_jvm_args=-XX:+UseG1GC
startup --host_jvm_args=-XX:MaxGCPauseMillis=200

Debugging

Build Debugging

bash
# Verbose output
bazel build //... --verbose_failures
bazel build //... --subcommands

# Explain build
bazel build //... --explain=explain.log
bazel build //... --verbose_explanations

# Profile build
bazel build //... --profile=profile.json

# Sandbox debugging
bazel build //... --sandbox_debug
bazel build //... --spawn_strategy=standalone

Query and Analysis

bash
# Dependency analysis
bazel query "deps(//src:hello-world)"
bazel query "rdeps(//..., //common:utils)"

# Build graph
bazel query --output=graph //... | dot -Tpng > graph.png

# Action graph
bazel aquery //src:hello-world

# Configuration
bazel cquery //src:hello-world --output=starlark --starlark:expr="target.label"

Best Practices

Project Structure

workspace/
├── WORKSPACE
├── .bazelrc
├── BUILD.bazel
├── tools/
│   ├── BUILD.bazel
│   └── rules.bzl
├── third_party/
│   └── BUILD.bazel
├── src/
│   ├── main/
│   │   └── BUILD.bazel
│   └── test/
│       └── BUILD.bazel
└── docs/
    └── BUILD.bazel

Target Naming

python
# Use descriptive names
java_library(
    name = "user_service_lib",  # Not just "lib"
    srcs = ["UserService.java"],
)

# Group related targets
java_library(name = "auth_lib", ...)
java_test(name = "auth_test", ...)
java_binary(name = "auth_server", ...)

# Use consistent patterns
cc_library(name = "foo_lib", ...)
cc_test(name = "foo_test", ...)

Visibility Management

python
# Package-level visibility
package(default_visibility = ["//visibility:private"])

# Specific visibility
java_library(
    name = "internal_lib",
    visibility = ["//src/main:__subpackages__"],
)

# Public libraries
java_library(
    name = "public_api",
    visibility = ["//visibility:public"],
)

Troubleshooting

Common Issues

bash
# Clear cache
bazel clean --expunge

# Check workspace
bazel info workspace

# Verify dependencies
bazel query "deps(//src:target)"

# Check build configuration
bazel config

# Analyze failures
bazel build //... --verbose_failures --keep_going

Performance Issues

bash
# Profile build
bazel build //... --profile=profile.json
bazel analyze-profile profile.json

# Memory analysis
bazel dump --rules
bazel dump --skylark_memory

# Cache analysis
bazel info repository_cache
bazel info output_base

Resources