Skip to content

Latest commit

 

History

153 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

carve

Release website

Carve compile_commands.json out of Bazel build graphs for clangd-style tooling, licensed under Apache-2.0. Carve is a clean-slate C++23 replacement for the maintained helly25 fork of Hedron's bazel-compile-commands-extractor. (Note that the original Hedron repository is no longer maintained.)

Test Coverage report

Status

Working, pre-release. All three layers are implemented and tested - Layer A (carve refresh), Layer B (bazel run //:refresh), and Layer C (the cc_carve_aspect aspect emitting per-action shards) - along with the refresh, aggregate, shard, and prune subcommands. Not yet published to the Bazel Central Registry; the release tooling is in place. See CARVE_DESIGN.md for the architecture and docs/IMPLEMENTATION_PLAN.md for milestone status.

What it does

  1. Walks Bazel's action graph via bazel aquery.
  2. Filters to C/C++/Objective-C/CUDA compile actions.
  3. Resolves each action's header set in-process via clang's DependencyScanningTool.
  4. De-Bazels each compile command so clangd can introspect it without Bazel-specific environment.
  5. Writes an atomic compile_commands.json plus a persistent sidecar cache that skips re-scanning unchanged actions on re-refresh.

A working CDB does not require a full build; clangd resolves most headers itself. Generated headers, however, must exist on disk for the scan to resolve them - codegen-heavy targets may need a build first. Sub-second incremental refresh on large monorepos is a Layer C (aspect) property: Layers A/B re-run bazel aquery each time and so pay the graph-query cost regardless of edit size. See CARVE_DESIGN.md section 3.1.

Usage

# Refresh the whole repo's compilation database (writes compile_commands.json to
# the workspace root). This is the carve_refresh rule (Layer B).
bazel run //:refresh

# Or drive the binary directly (Layer A), choosing targets/output on the CLI.
bazel run //:carve -- refresh --targets=//foo/... --output=compile_commands.json

In a consumer workspace, depend on carve in MODULE.bazel (once it is published to the Bazel Central Registry):

bazel_dep(name = "mboworks_carve", version = "0.1.1")

# The official LLVM static archives contain LLVM bitcode, so select the
# matching compiler as well as its C++ standard library.
bazel_dep(name = "toolchains_llvm", version = "1.9.0")
llvm = use_extension("@toolchains_llvm//toolchain/extensions:llvm.bzl", "llvm")
llvm.toolchain(
    name = "llvm_toolchain",
    llvm_version = "22.1.8",
    stdlib = {
        "": "builtin-libc++",
        "linux-aarch64": "stdc++",
        "linux-x86_64": "stdc++",
    },
)
use_repo(llvm, "llvm_toolchain")
register_toolchains("@llvm_toolchain//:all")

Carve links LLVM's prebuilt dependency-scanning libraries. Copy carve.bazelrc into the consumer workspace and import it from the workspace .bazelrc so Carve is compiled as C++23 with its required LLVM link settings and warning policy:

try-import %workspace%/carve.bazelrc

The fragment is part of every source archive. The consumer registers the matching toolchain because toolchains_llvm 1.9.0 only permits its toolchain extension in the root module. Bazel's include() likewise cannot load a fragment from an external repository, so this stanza cannot live inside Carve. The checked-in examples/bcr module is the authoritative consumer example used by both source-archive CI and the optional BCR presubmit.

Then add the rule from a BUILD file:

load("@mboworks_carve//rules:carve.bzl", "carve_refresh")

carve_refresh(name = "refresh", targets = ["//..."])

carve_refresh is a bazel run target, not a build artifact: carve invokes bazel aquery, and spawning bazel inside a build action is the nested-bazel trap. For huge repos there is also Layer C - cc_carve_aspect + carve_aspect_refresh (rules/cc_carve_aspect.bzl, rules/carve.bzl) schedule one individually-cacheable shard per compile action and aggregate them.

Build requirements

  • Bazel 9.1+
  • Clang 22.x (LLVM 22.1.8); root development uses toolchains_llvm 1.9.0, while scan_deps downloads and links the matching static Clang/LLVM archives
  • A consumer toolchain using LLVM 22.1.8 with libstdc++ on Linux or libc++ on macOS, matching the official LLVM distributions
  • Apple Silicon / x86_64 Linux supported; Windows planned

License

Copyright M. Boerger, the MBO Works authors. Licensed under the Apache License 2.0; see LICENSE for details.

About

Carve compile_commands.json out of Bazel build graphs for clangd-style tooling. Clean-slate C++23 rewrite, Apache-2.0.

Resources

Code of conduct

Contributing

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages