Open pollend opened 3 months ago
You can't have a rule write outside of buck-out
(without hacks anyway), but you can do something like buck2 build //my:target[full-compilation-database] --out .
.
Unsollicited tip: --out -
will print the contents of the output to stdout instead.
that's annoying. I couldn't get full-compilation-database
to work with clangd. I ended up writing this bxl script so i can generate the correct commands for clangd.
cat $(buck2 bxl //compile_command.bxl:gen_compile_command -- --base_dir $(pwd)) > compile_commands.json
# Copyright (c) Meta Platforms, Inc. and affiliates.
#
# This source code is licensed under both the MIT license found in the
# LICENSE-MIT file in the root directory of this source tree and the Apache
# License, Version 2.0 found in the LICENSE-APACHE file in the root directory
# of this source tree.
load(
"@prelude//cxx:comp_db.bzl",
"CxxCompilationDbInfo",
)
load("@prelude//:paths.bzl", "paths")
load("@prelude//paths.bzl", "paths")
def _gen_compile_command(ctx: BxlContext) -> None:
target_filter = ctx.cli_args.targets or "..."
targets = ctx.configured_targets(target_filter, target_platform = ctx.cli_args.platform)
entries = []
infos = {}
for target in targets:
providers = ctx.analysis(target).providers()
compile_db_info = providers.get(CxxCompilationDbInfo)
if compile_db_info != None:
infos |= compile_db_info.info
for key in infos:
cmd_entry = infos[key]
entry = {}
entry["directory"] = ctx.cli_args.base_dir
entry["file"] = cmd_entry.src.short_path
cxx = cmd_entry.cxx_compile_cmd
if cxx:
entry["command"] = cmd_args(cxx.base_compile_cmd, cxx.argsfile.input_args[0], cmd_entry.args, delimiter = " ")
entries.append(entry)
actions = ctx.bxl_actions(target_platform = ctx.cli_args.platform).actions
db_artifact = actions.write_json("compile_commands.json", entries)
db_artifact_ensured = ctx.output.ensure(db_artifact)
ctx.output.print(db_artifact_ensured)
gen_compile_command = bxl_main(
impl = _gen_compile_command,
cli_args = {
"base_dir": cli_args.option(cli_args.string()),
"targets": cli_args.option(cli_args.target_expr()),
"platform": cli_args.option(cli_args.target_label())
},
)
Right, this is something which I've also hit and reported at https://github.com/facebook/buck2/issues/307. I personally worked around it by forking Meta's compile commands generation script and getting it to output absolute paths instead, so that my users don't have to call/learn about BXL.
It's really unfortunate that the defaults are just broken though, every new user is going to hit this. I really wish that Meta would change the defaults and opt into relative paths internally. Please chime in the other issue if you agree!
here is what i do for windows.
$CommandPath = buck2 bxl //compile_command.bxl:gen_compile_command -- --base_dir (Get-Location).Path
cat $CommandPath | Out-File compile_commands.json
I have a PR up that is -- imo anyway -- a better and faster compile_commands generator bxl. Note that it's easy to put outputs anywhere you want if you invoke python from the bxl, perhaps via an anonymous action. The python script can reach out of the sandbox, and you could (for example) pass it a path to the json as well as a path to the desired output location, and the python script can just copy it there.
I've just been updating this script for my own use.
# Copyright (c) Meta Platforms, Inc. and affiliates.
#
# This source code is licensed under both the MIT license found in the
# LICENSE-MIT file in the root directory of this source tree and the Apache
# License, Version 2.0 found in the LICENSE-APACHE file in the root directory
# of this source tree.
load(
"@prelude//cxx:comp_db.bzl",
"CxxCompilationDbInfo",
)
load("@prelude//paths.bzl", "paths")
def _gen_compile_command(ctx: BxlContext) -> None:
entries = []
query_targets = {}
for filter in ctx.cli_args.filter:
targets = ctx.configured_targets(filter, target_platform = ctx.cli_args.platform)
for target in targets:
query_targets[target.label.raw_target()] = target
for key in query_targets:
target = query_targets[key]
providers = ctx.analysis(target).providers()
compile_db_info = providers.get(CxxCompilationDbInfo)
if compile_db_info != None:
for key in compile_db_info.info:
cmd_entry = compile_db_info.info[key]
entry = {}
entry["directory"] = ctx.fs.abs_path_unsafe("root//") #"{}".format(target.label.path))
entry["file"] = cmd_entry.src.short_path
cxx = cmd_entry.cxx_compile_cmd
if cxx:
entry["command"] = cmd_args(cxx.base_compile_cmd, cxx.argsfile.input_args[0], cmd_entry.args, delimiter = " ")
entries.append(entry)
actions = ctx.bxl_actions(target_platform = ctx.cli_args.platform).actions
db_artifact = actions.write_json("compile_commands.json", entries)
db_artifact_ensured = ctx.output.ensure(db_artifact)
ctx.output.print(db_artifact_ensured)
gen_compile_command = bxl_main(
impl = _gen_compile_command,
cli_args = {
"filter": cli_args.list(cli_args.target_expr()),
"platform": cli_args.option(cli_args.target_label())
},
)
Is it possible to have a rule write to the root directory of the project? i can grab the file and copy it back to the root but is there a better way to do this?