Skip to content

BUILD Files in Bazel

This guide explains how to write and organize BUILD files effectively.

What are BUILD Files?

BUILD files are the core of Bazel's build system. They define:

  • Targets that can be built
  • Dependencies between targets
  • Build rules and their attributes
  • Package visibility and constraints

Basic Structure

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

package(default_visibility = ["//visibility:private"])

cc_library(
    name = "hello_lib",
    srcs = ["hello.cc"],
    hdrs = ["hello.h"],
    visibility = ["//visibility:public"],
)

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

Target Naming

Target names should be:

  • Descriptive and meaningful
  • Lowercase with underscores
  • Unique within the package
  • Related to their function

Example:

python
cc_library(
    name = "string_utils",  # Good: descriptive
    srcs = ["string_utils.cc"],
)

Common Rules

Built-in rules for various languages:

python
# C/C++
cc_binary(name = "app")
cc_library(name = "lib")
cc_test(name = "test")

# Java
java_binary(name = "app")
java_library(name = "lib")
java_test(name = "test")

# Python
py_binary(name = "app")
py_library(name = "lib")
py_test(name = "test")

# Protocol Buffers
proto_library(name = "proto")

Visibility

Control who can depend on your targets:

python
package(default_visibility = ["//visibility:private"])

cc_library(
    name = "internal_lib",
    # Uses package default visibility
)

cc_library(
    name = "public_lib",
    visibility = ["//visibility:public"],
)

cc_library(
    name = "limited_lib",
    visibility = [
        "//my/package:__subpackages__",
        "//other/package:__pkg__",
    ],
)

Dependencies

Different types of dependencies:

python
cc_binary(
    name = "app",
    deps = [
        ":local_lib",  # Within same package
        "//other/package:lib",  # Different package
        "@external_repo//:lib",  # External repository
    ],
    data = ["//path/to:data_file"],  # Runtime dependencies
)

Best Practices

  1. Package Organization

    • Keep BUILD files close to source
    • One BUILD file per directory
    • Group related targets together
  2. Target Design

    • Make targets as small as practical
    • Avoid circular dependencies
    • Use appropriate visibility
  3. Dependencies

    • Minimize dependency chains
    • Use precise dependencies
    • Document non-obvious deps
  4. Maintainability

    • Use buildifier for formatting
    • Document complex build rules
    • Use macros for repetitive patterns

Common Patterns

Test Targets

python
cc_test(
    name = "lib_test",
    srcs = ["lib_test.cc"],
    deps = [
        ":lib",
        "@com_google_googletest//:gtest_main",
    ],
)

Data Dependencies

python
py_binary(
    name = "tool",
    srcs = ["tool.py"],
    data = [
        "//path/to:config.json",
        "//path/to:resources",
    ],
)

Released under the MIT License.