Bazel: platforms

Summary Table

ConceptWhat it isAnalogy
Constraint SettingA property category“Vehicle Type”
Constraint ValueA specific option“Car”, “Truck”, “Motorcycle”
PlatformA group of settings“Vehicle configured for highway use” (Car + 4 Tires)

The Core Concepts

To understand how they relate, think of them in terms of a property-based system:

  • constraint_setting: Defines a category or type of property that distinguishes machines (e.g., “CPU architecture”, “Operating System”).
  • constraint_value: Defines a specific choice within a category (e.g., within the “CPU architecture” setting, choices could be “x86”, “ARM”, “RISC-V”).
  • platform: A collection of constraint_values that defines a complete environment (e.g., a “Linux-x86” platform is a collection of OS:Linux and CPU:x86).

Example: Defining Custom Constraints

Suppose you are building an embedded system and you need to distinguish between different GPU types and glibc versions. You would define these in your own BUILD file.

1. Define the “Categories” (Settings)

Create a BUILD file (e.g., //tools/platforms:BUILD) to hold your custom logic.

# //tools/platforms/BUILD

# A new dimension for GPU hardware
constraint_setting(name = "gpu_type")

# A new dimension for C library versions
constraint_setting(name = "glibc_version")

2. Define the “Choices” (Values)

Now, define the specific values that belong to those categories.

# //tools/platforms/BUILD

# Values for gpu_type
constraint_value(name = "nvidia_rtx", constraint_setting = ":gpu_type")
constraint_value(name = "amd_radeon", constraint_setting = ":gpu_type")

# Values for glibc_version
constraint_value(name = "glibc_2_25", constraint_setting = ":glibc_version")
constraint_value(name = "glibc_2_28", constraint_setting = ":glibc_version")

3. Bundle them into a Platform

Now that you have defined these custom constraints, you can use them alongside standard ones to define your custom platform.

# //tools/platforms/BUILD

platform(
    name = "custom_embedded_gpu_linux",
    constraint_values = [
        "@platforms//os:linux",          # Standard constraint
        "@platforms//cpu:aarch64",       # Standard constraint
        ":nvidia_rtx",                   # YOUR custom constraint
        ":glibc_2_28",                   # YOUR custom constraint
    ],
)

How to use these in your build

Once you’ve defined these, you can use select() in your rules to change behavior based on these custom constraints.

# //myapp/BUILD

cc_library(
    name = "gpu_driver",
    srcs = select({
        "//tools/platforms:nvidia_rtx": ["driver_nvidia.cc"],
        "//tools/platforms:amd_radeon": ["driver_amd.cc"],
        "//conditions:default": ["driver_stub.cc"],
    }),
)

Why this approach is powerful:

  1. Strict Typing: Bazel ensures that nvidia_rtx is only used for the gpu_type setting. You can’t accidentally assign it to an OS setting.
  2. Organization: You keep your project-specific needs (like “is this a high-security build?”) inside your own repository, while using @platforms for universal things like cpu and os.
  3. Cross-Project Compatibility: If another team in your company wants to build for the same custom_embedded_gpu_linux platform, they can import the label //tools/platforms:custom_embedded_gpu_linux and get all the same settings.

Leave a Reply

Your email address will not be published. Required fields are marked *