bazel
Use when writing Bazel BUILD files with cc_library or cc_binary rules, Bzlmod dependencies, toolchain registration, remote execution, sandbox debugging, or bazel query and cquery graphs.
Install
npx skills add https://github.com/OutlineDriven/outline-driven-development/tree/main/.devin/skills/bazel
claude plugin marketplace add https://llmmart.ai/marketplace.json && claude plugin install outlinedriven-outline-driven-development@llmmart
git clone https://github.com/OutlineDriven/outline-driven-development.git
The skills CLI installs just this skill, for any of its supported agents. Claude Code installs the whole outlinedriven/outline-driven-development collection as a plugin from our marketplace. Git is the plain clone.
Skill manifest
Bazel
Bazel for C/C++ projects: BUILD files, Bzlmod dependencies, toolchain registration, remote execution, dependency graph queries, and sandbox debugging. Grounded against Bazel 9.2.0, where Bzlmod is always enabled, all WORKSPACE logic is removed, and every C++ rule loads from @rules_cc.
Contract
| Field | Bound contract |
|---|---|
| Trigger | The task writes or debugs Bazel BUILD files, cc_library/cc_binary/cc_test rules, Bzlmod dependencies, toolchain registration, remote execution, sandbox failures, or bazel query/cquery/aquery dependency graphs. |
| Authority | Reversible local: writes only BUILD files, MODULE.bazel, .bzl files, and Bazel output directories (bazel-out, bazel-bin); rollback is version control plus bazel clean. No remote mutation. |
| Side effect | Local builds write to the Bazel output base; remote execution and remote cache flags contact a user-supplied endpoint. |
| Done | The requested targets build or test with bazel build/bazel test, or the blocker is reported with the failing command and output. |
Inputs
- Project layout (required): the source tree and where BUILD files should live.
- Bazel version (required if not inferrable): run
bazel version. Bazel 9 removed WORKSPACE and the native C++ rules; instructions below assume Bazel 9. - External dependencies (optional): library names; versions come from the Bazel Central Registry.
- Remote execution endpoint (optional): a user-supplied remote execution or cache service URL.
Procedure
- Lay out the workspace. Bazel 9 uses
MODULE.bazelas the only dependency file; there is no WORKSPACE. Put aBUILDfile in each package directory. Done when:MODULE.bazelexists at the root and each package has aBUILDfile.
my-project/
├── MODULE.bazel
├── BUILD
├── src/
│ ├── BUILD
│ └── main.cc
└── lib/
├── BUILD
├── mylib.cc
└── mylib.h
- Write BUILD rules. Load every C++ rule from
@rules_cc; the nativecc_library/cc_binary/cc_testrules were removed from Bazel 9. Done when: every target builds withbazel build.
# lib/BUILD
load("@rules_cc//cc:defs.bzl", "cc_library", "cc_test")
cc_library(
name = "mylib",
srcs = ["mylib.cc"],
hdrs = ["mylib.h"],
copts = ["-Wall", "-Wextra", "-std=c++23"],
visibility = ["//visibility:public"],
deps = [
"@abseil-cpp//absl/strings",
"//util:helpers",
],
)
cc_test(
name = "mylib_test",
srcs = ["mylib_test.cc"],
deps = [
":mylib",
"@googletest//:gtest_main",
],
)
# src/BUILD
load("@rules_cc//cc:defs.bzl", "cc_binary")
cc_binary(
name = "main",
srcs = ["main.cc"],
deps = ["//lib:mylib"],
linkopts = ["-lpthread"],
)
bazel build //src:main
bazel build //...
bazel test //lib:mylib_test
bazel run //src:main -- arg1 arg2
# Binary lands at bazel-bin/src/main
- Declare dependencies in
MODULE.bazelwithbazel_dep. Versions come from the Bazel Central Registry; the pins below are the versions Bazel 9.2.0 itself depends on. Done when:bazel mod graphresolves without errors.
# MODULE.bazel
module(name = "my_project", version = "1.0")
bazel_dep(name = "rules_cc", version = "0.2.17")
bazel_dep(name = "platforms", version = "1.0.0")
bazel_dep(name = "abseil-cpp", version = "20250814.1")
bazel_dep(name = "googletest", version = "1.17.0.bcr.2")
bazel mod graph # full resolved dependency graph
bazel mod deps # direct and indirect module deps
bazel mod tidy # fix up MODULE.bazel declarations
- Query the dependency graph. Done when: the query answers the question asked.
bazel query "deps(//src:main)" # transitive deps
bazel query "rdeps(//..., //lib:mylib)" # reverse deps
bazel query "somepath(//src:main, //lib:mylib)" # dependency path
bazel cquery "deps(//src:main)" --output=files # configuration-aware
bazel cquery "//lib:mylib" --output=build # effective rule
bazel aquery "//src:main" # action graph: flags, inputs, outputs
- Register toolchains with platforms. Define a
platformwith constraint values, atoolchainbinding a toolchain target to a toolchain type, thenregister_toolchainsinMODULE.bazel. The C++ toolchain configuration API lives in rules_cc undercc/toolchains; seereferences/bazel-cpp-toolchain.md. Done when:bazel build --platforms=//platforms:<name>selects the registered toolchain.
# platforms/BUILD
platform(
name = "linux_x86_64",
constraint_values = [
"@platforms//os:linux",
"@platforms//cpu:x86_64",
],
)
# MODULE.bazel
register_toolchains("//toolchains:my_cc_toolchain")
- Configure remote execution or caching when the user supplies an endpoint. Done when: the build runs against the endpoint or the flag is rejected and reported.
bazel build //... \
--remote_executor=grpc://build.example.com:50051 \
--remote_instance_name=main
# Cache only, no remote execution
bazel build //... --remote_cache=grpc://cache.example.com:9092
- Debug sandbox failures. Done when: the failing action is identified and its missing input or disallowed write is fixed.
bazel build //src:main --sandbox_debug # show sandbox inputs/outputs
bazel build //src:main --verbose_failures --sandbox_debug
bazel build //src:main --spawn_strategy=local # bypass sandbox to isolate it
bazel build //src:main --subcommands # print each command run
Common sandbox causes: "No such file or directory" means a missing data or srcs entry; "Permission denied" means a write outside the sandbox, fixed by routing outputs through declared rule outputs.
Failure and recovery
bazel buildfails on a missing load: addload("@rules_cc//cc:defs.bzl", ...)for the rule used; Bazel 9 has no native C++ rules.bazel_depversion not found: runbazel mod graphto see the error, then pick a version listed in the Bazel Central Registry.- Sandbox error persists after adding inputs: reproduce with
--spawn_strategy=local; if the local run passes, the sandbox is missing a declared input. - Remote execution unreachable: drop
--remote_executorand rebuild locally; report the endpoint failure rather than retrying blindly. - Query returns empty: check the target pattern with
bazel query "//..."first; an empty pattern means the package path is wrong. - Migration from WORKSPACE: run the Bzlmod migration path (
bazel mod tidyafter declaring deps); do not recreate WORKSPACE, Bazel 9 ignores it.
Output
Working BUILD files and MODULE.bazel declarations, a verified bazel build/bazel test invocation, and for debugging tasks the identified failing action with its fix. For toolchain work, a registered toolchain plus platform pair verified by --platforms.
Files (outline-driven-development)
-
agents
-
openai.yaml 288 B
interface: display_name: "Bazel" short_description: "Use when writing Bazel BUILD files with cc_library or cc_binary rules, Bzlmod dependencies, toolchain registration, remote execution, sandbox debugging, or bazel query and cquery graphs." policy: allow_implicit_invocation: false
-
-
references
-
bazel-cpp-toolchain.md 2.9 KB
# Bazel C++ toolchain reference Grounded against Bazel 9.2.0 and rules_cc 0.2.x. Bazel 9 removed the native C++ rules and the old `@bazel_tools//tools/cpp:cc_toolchain_config.bzl` macro. C++ rules and toolchain support now live in `rules_cc`. ## Loading C++ rules Every BUILD file that uses a C++ rule loads it explicitly: ```python load("@rules_cc//cc:defs.bzl", "cc_library", "cc_binary", "cc_test", "cc_toolchain") ``` `rules_cc` must be a `bazel_dep` in `MODULE.bazel`: ```python bazel_dep(name = "rules_cc", version = "0.2.17") bazel_dep(name = "platforms", version = "1.0.0") ``` ## Platform and toolchain registration ```python # platforms/BUILD platform( name = "linux_x86_64", constraint_values = [ "@platforms//os:linux", "@platforms//cpu:x86_64", ], ) ``` ```python # toolchains/BUILD load("@rules_cc//cc:defs.bzl", "cc_toolchain") cc_toolchain( name = "k8_toolchain", all_files = ":empty", ar_files = ":empty", as_files = ":empty", compiler_files = ":empty", dwp_files = ":empty", linker_files = ":empty", objcopy_files = ":empty", strip_files = ":empty", toolchain_config = ":k8_toolchain_config", toolchain_identifier = "k8-toolchain", ) toolchain( name = "cc_toolchain_k8", exec_compatible_with = [ "@platforms//cpu:x86_64", "@platforms//os:linux", ], target_compatible_with = [ "@platforms//cpu:x86_64", "@platforms//os:linux", ], toolchain = ":k8_toolchain", toolchain_type = "@rules_cc//cc:toolchain_type", ) filegroup(name = "empty") ``` ```python # MODULE.bazel register_toolchains("//toolchains:cc_toolchain_k8") ``` The `toolchain_config` attribute takes a target providing `CcToolchainConfigInfo`. Build one with the primitives in `@rules_cc//cc:cc_toolchain_config_lib.bzl` (`feature`, `flag_set`, `flag_group`, `action_config`, `tool_path`, `env_set`), or use the rule-based toolchain API under `@rules_cc//cc/toolchains`. Read the rules_cc source for the current signatures; the API changed between Bazel 8 and 9 and examples written for `@bazel_tools` no longer apply. ## Common build flags ```bash bazel build //... -c opt # optimized build bazel build //... -c dbg # debug build # Select a registered toolchain explicitly bazel build //... --extra_toolchains=//toolchains:cc_toolchain_k8 # Pass compiler and linker flags bazel build //... --copt=-fsanitize=address --linkopt=-fsanitize=address # Target a specific platform bazel build //... --platforms=//platforms:linux_x86_64 ``` ## Cross-compilation sketch A cross toolchain pairs a `platform` for the target (for example `@platforms//cpu:aarch64` plus `@platforms//os:linux`) with a `cc_toolchain` whose tool paths point at the cross prefix (`aarch64-linux-gnu-gcc` and friends) and whose config passes `--sysroot` through `compile_flags` and `link_flags`. Register it the same way and select it with `--platforms`.
-
-
SKILL.md 7.1 KB
--- name: bazel description: 'Use when writing Bazel BUILD files with cc_library or cc_binary rules, Bzlmod dependencies, toolchain registration, remote execution, sandbox debugging, or bazel query and cquery graphs.' disable-model-invocation: true --- # Bazel Bazel for C/C++ projects: BUILD files, Bzlmod dependencies, toolchain registration, remote execution, dependency graph queries, and sandbox debugging. Grounded against Bazel 9.2.0, where Bzlmod is always enabled, all WORKSPACE logic is removed, and every C++ rule loads from `@rules_cc`. ## Contract | Field | Bound contract | |---|---| | Trigger | The task writes or debugs Bazel BUILD files, `cc_library`/`cc_binary`/`cc_test` rules, Bzlmod dependencies, toolchain registration, remote execution, sandbox failures, or `bazel query`/`cquery`/`aquery` dependency graphs. | | Authority | Reversible local: writes only BUILD files, `MODULE.bazel`, `.bzl` files, and Bazel output directories (`bazel-out`, `bazel-bin`); rollback is version control plus `bazel clean`. No remote mutation. | | Side effect | Local builds write to the Bazel output base; remote execution and remote cache flags contact a user-supplied endpoint. | | Done | The requested targets build or test with `bazel build`/`bazel test`, or the blocker is reported with the failing command and output. | ## Inputs - Project layout (required): the source tree and where BUILD files should live. - Bazel version (required if not inferrable): run `bazel version`. Bazel 9 removed WORKSPACE and the native C++ rules; instructions below assume Bazel 9. - External dependencies (optional): library names; versions come from the Bazel Central Registry. - Remote execution endpoint (optional): a user-supplied remote execution or cache service URL. ## Procedure 1. Lay out the workspace. Bazel 9 uses `MODULE.bazel` as the only dependency file; there is no WORKSPACE. Put a `BUILD` file in each package directory. Done when: `MODULE.bazel` exists at the root and each package has a `BUILD` file. ```text my-project/ ├── MODULE.bazel ├── BUILD ├── src/ │ ├── BUILD │ └── main.cc └── lib/ ├── BUILD ├── mylib.cc └── mylib.h ``` 2. Write BUILD rules. Load every C++ rule from `@rules_cc`; the native `cc_library`/`cc_binary`/`cc_test` rules were removed from Bazel 9. Done when: every target builds with `bazel build`. ```python # lib/BUILD load("@rules_cc//cc:defs.bzl", "cc_library", "cc_test") cc_library( name = "mylib", srcs = ["mylib.cc"], hdrs = ["mylib.h"], copts = ["-Wall", "-Wextra", "-std=c++23"], visibility = ["//visibility:public"], deps = [ "@abseil-cpp//absl/strings", "//util:helpers", ], ) cc_test( name = "mylib_test", srcs = ["mylib_test.cc"], deps = [ ":mylib", "@googletest//:gtest_main", ], ) ``` ```python # src/BUILD load("@rules_cc//cc:defs.bzl", "cc_binary") cc_binary( name = "main", srcs = ["main.cc"], deps = ["//lib:mylib"], linkopts = ["-lpthread"], ) ``` ```bash bazel build //src:main bazel build //... bazel test //lib:mylib_test bazel run //src:main -- arg1 arg2 # Binary lands at bazel-bin/src/main ``` 3. Declare dependencies in `MODULE.bazel` with `bazel_dep`. Versions come from the Bazel Central Registry; the pins below are the versions Bazel 9.2.0 itself depends on. Done when: `bazel mod graph` resolves without errors. ```python # MODULE.bazel module(name = "my_project", version = "1.0") bazel_dep(name = "rules_cc", version = "0.2.17") bazel_dep(name = "platforms", version = "1.0.0") bazel_dep(name = "abseil-cpp", version = "20250814.1") bazel_dep(name = "googletest", version = "1.17.0.bcr.2") ``` ```bash bazel mod graph # full resolved dependency graph bazel mod deps # direct and indirect module deps bazel mod tidy # fix up MODULE.bazel declarations ``` 4. Query the dependency graph. Done when: the query answers the question asked. ```bash bazel query "deps(//src:main)" # transitive deps bazel query "rdeps(//..., //lib:mylib)" # reverse deps bazel query "somepath(//src:main, //lib:mylib)" # dependency path bazel cquery "deps(//src:main)" --output=files # configuration-aware bazel cquery "//lib:mylib" --output=build # effective rule bazel aquery "//src:main" # action graph: flags, inputs, outputs ``` 5. Register toolchains with platforms. Define a `platform` with constraint values, a `toolchain` binding a toolchain target to a toolchain type, then `register_toolchains` in `MODULE.bazel`. The C++ toolchain configuration API lives in rules_cc under `cc/toolchains`; see `references/bazel-cpp-toolchain.md`. Done when: `bazel build --platforms=//platforms:<name>` selects the registered toolchain. ```python # platforms/BUILD platform( name = "linux_x86_64", constraint_values = [ "@platforms//os:linux", "@platforms//cpu:x86_64", ], ) ``` ```python # MODULE.bazel register_toolchains("//toolchains:my_cc_toolchain") ``` 6. Configure remote execution or caching when the user supplies an endpoint. Done when: the build runs against the endpoint or the flag is rejected and reported. ```bash bazel build //... \ --remote_executor=grpc://build.example.com:50051 \ --remote_instance_name=main # Cache only, no remote execution bazel build //... --remote_cache=grpc://cache.example.com:9092 ``` 7. Debug sandbox failures. Done when: the failing action is identified and its missing input or disallowed write is fixed. ```bash bazel build //src:main --sandbox_debug # show sandbox inputs/outputs bazel build //src:main --verbose_failures --sandbox_debug bazel build //src:main --spawn_strategy=local # bypass sandbox to isolate it bazel build //src:main --subcommands # print each command run ``` Common sandbox causes: "No such file or directory" means a missing `data` or `srcs` entry; "Permission denied" means a write outside the sandbox, fixed by routing outputs through declared rule outputs. ## Failure and recovery - `bazel build` fails on a missing load: add `load("@rules_cc//cc:defs.bzl", ...)` for the rule used; Bazel 9 has no native C++ rules. - `bazel_dep` version not found: run `bazel mod graph` to see the error, then pick a version listed in the Bazel Central Registry. - Sandbox error persists after adding inputs: reproduce with `--spawn_strategy=local`; if the local run passes, the sandbox is missing a declared input. - Remote execution unreachable: drop `--remote_executor` and rebuild locally; report the endpoint failure rather than retrying blindly. - Query returns empty: check the target pattern with `bazel query "//..."` first; an empty pattern means the package path is wrong. - Migration from WORKSPACE: run the Bzlmod migration path (`bazel mod tidy` after declaring deps); do not recreate WORKSPACE, Bazel 9 ignores it. ## Output Working BUILD files and `MODULE.bazel` declarations, a verified `bazel build`/`bazel test` invocation, and for debugging tasks the identified failing action with its fix. For toolchain work, a registered `toolchain` plus `platform` pair verified by `--platforms`.
Comments (0)
Sign in to join the conversation.
Reviews (0)
No reviews yet.
No comments yet.