Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
47 changes: 47 additions & 0 deletions docs/users/how_tos/compilation_database.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
---
id: compilation_database
title: Compilation databases
---

# Generating compilation databases

You can generate compilation databases for consumption by tools such as
clangd and clang-tidy by running the following BXL script:

```sh
buck2 bxl prelude//cxx/tools/compilation_database.bxl:generate -- --targets ...
```

The script will generate a compilation database for all source and
header inputs to the targets listed on the command line. The path to the
database is printed to `stdout`. Note that files that are referenced by
multiple targets will have multiple associated entries in the database,
which may not be desirable in all circumstances. For example, clang-tidy
runs analysis for each entry sequentially when the file being linted has
several entries.

It is common to symlink the resulting data at the root of the
repository:

```sh
ln -sf $(buck2 bxl prelude//cxx/tools/compilation_database.bxl:generate -- --targets ...) $(git rev-parse --show-toplevel)
```

Since the path to the script is rather long, consider setting up an
alias in your repository:

```python
# `comp_db.bxl`

load("@prelude//cxx/tools/compilation_database.bxl:generate", "generate")

gen = generate
```

```sh
ln -sf $(buck2 bxl comp_db.bxl:gen -- --targets ...) $(git rev-parse --show-toplevel)
```

Providing better ergonomics for BXL scripts (such as enabling something
like `buck2 comp_db`) is being discussed at
<https://github.com/facebook/buck2/issues/86>.
44 changes: 44 additions & 0 deletions prelude/cxx/tools/compilation_database.bxl
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
load("@prelude//cxx/comp_db.bzl", "CxxCompilationDbInfo")
load("@prelude//cxx/compile.bzl", "CxxSrcCompileCommand")
load("@prelude//utils:utils.bzl", "flatten")

def _make_entry(ctx: bxl.Context, compile_command: CxxSrcCompileCommand) -> dict:
args = compile_command.cxx_compile_cmd.base_compile_cmd.copy()

# This prevents clangd from jumping into `buck-out` when using Go To
# Definition, which significantly improces user experience.
args.add(["-I", "."])
args.add(compile_command.cxx_compile_cmd.argsfile.cmd_form)
args.add(compile_command.args)
ctx.output.ensure_multiple(args)

return {
"arguments": args,
"directory": ctx.fs.abs_path_unsafe(ctx.root()),
"file": compile_command.src,
}

def _impl(ctx: bxl.Context):
actions = ctx.bxl_actions().actions
targets = flatten(ctx.cli_args.targets)

db = []
for name, target in ctx.analysis(ctx.configured_targets(targets)).items():
comp_db_info = target.providers().get(CxxCompilationDbInfo)
if comp_db_info:
db += [_make_entry(ctx, cc) for cc in comp_db_info.info.values()]

db_file = actions.declare_output("compile_commands.json")
actions.write_json(db_file.as_output(), db, with_inputs = True, pretty = True)
ctx.output.print(ctx.output.ensure(db_file))

generate = bxl_main(
doc = "Generate a compilation database for a set of targets and print its path to stdout",
impl = _impl,
cli_args = {
"targets": cli_args.list(
cli_args.target_expr(),
doc = "Targets to generate the database for",
),
},
)