Appearance
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
- Official Documentation: bazel.build
- User Guide: bazel.build/docs
- Rules Repository: github.com/bazelbuild
- Best Practices: bazel.build/docs/best-practices