Skip to content

Commit 83f93d9

Browse files
committed
Add output_dir parameter to control where compile_commands.json is written
New macro/rule parameter `output_dir` (default empty == workspace root, matching the historical behaviour). When set, both the pre-write unlink and the open() target are rerouted to `<output_dir>/compile_commands.json`. Backport of hedronvision#210 (ilev4ik).
1 parent 3e56690 commit 83f93d9

2 files changed

Lines changed: 10 additions & 4 deletions

File tree

refresh.template.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1454,16 +1454,19 @@ def main():
14541454
There should be actionable warnings, above, that led to this.""")
14551455
sys.exit(1)
14561456

1457+
# Resolve the output path; `output_dir` is the macro parameter (empty == cwd).
1458+
output_path = os.path.join({output_dir}, 'compile_commands.json')
1459+
14571460
# Remove any existing compile_commands.json before opening; handles the common
14581461
# case where it's a symlink (e.g. pointing into a cmake build dir), which would
14591462
# otherwise produce an inscrutable open() error. https://github.com/hedronvision/bazel-compile-commands-extractor/issues/105
14601463
try:
1461-
os.remove('compile_commands.json')
1464+
os.remove(output_path)
14621465
except FileNotFoundError:
14631466
pass
14641467

14651468
# Chain output into compile_commands.json
1466-
with open('compile_commands.json', 'w') as output_file:
1469+
with open(output_path, 'w') as output_file:
14671470
json.dump(
14681471
compile_command_entries,
14691472
output_file,

refresh_compile_commands.bzl

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ def refresh_compile_commands(
6565
targets = None,
6666
exclude_headers = None,
6767
exclude_external_sources = False,
68+
output_dir = "",
6869
**kwargs): # For the other common attributes. Tags, compatible_with, etc. https://docs.bazel.build/versions/main/be/common-definitions.html#common-attributes.
6970
# Convert the various, acceptable target shorthands into the dictionary format
7071
# In Python, `type(x) == y` is an antipattern, but [Starlark doesn't support inheritance](https://bazel.build/rules/language), so `isinstance` doesn't exist, and this is the correct way to switch on type.
@@ -90,7 +91,7 @@ def refresh_compile_commands(
9091

9192
# Generate the core, runnable python script from refresh.template.py
9293
script_name = name + ".py"
93-
_expand_template(name = script_name, labels_to_flags = targets, exclude_headers = exclude_headers, exclude_external_sources = exclude_external_sources, **kwargs)
94+
_expand_template(name = script_name, labels_to_flags = targets, exclude_headers = exclude_headers, exclude_external_sources = exclude_external_sources, output_dir = output_dir, **kwargs)
9495

9596
# Combine them so the wrapper calls the main script.
9697
# Tag "manual" so `bazel build //...` won't try to build this when
@@ -121,8 +122,9 @@ def _expand_template_impl(ctx):
121122
# Note, don't delete whitespace. Correctly doing multiline indenting.
122123
" {target_flag_pairs}": "\n".join([" {},".format(pair) for pair in ctx.attr.labels_to_flags.items()]),
123124
" {windows_default_include_paths}": "\n".join([" %r," % path for path in find_cpp_toolchain(ctx).built_in_include_directories]), # find_cpp_toolchain is from https://docs.bazel.build/versions/main/integrating-with-rules-cc.html
124-
"{exclude_headers}": repr(ctx.attr.exclude_headers),
125125
"{exclude_external_sources}": repr(ctx.attr.exclude_external_sources),
126+
"{exclude_headers}": repr(ctx.attr.exclude_headers),
127+
"{output_dir}": repr(ctx.attr.output_dir),
126128
"{print_args_executable}": repr(ctx.executable._print_args_executable.path),
127129
},
128130
)
@@ -133,6 +135,7 @@ _expand_template = rule(
133135
"labels_to_flags": attr.string_dict(mandatory = True), # string keys instead of label_keyed because Bazel doesn't support parsing wildcard target patterns (..., *, :all) in BUILD attributes.
134136
"exclude_external_sources": attr.bool(default = False),
135137
"exclude_headers": attr.string(values = ["all", "external", ""]), # "" needed only for compatibility with Bazel < 3.6.0
138+
"output_dir": attr.string(default = ""), # Empty means: write to the workspace root (cwd, the historical behaviour).
136139
"_script_template": attr.label(allow_single_file = True, default = "refresh.template.py"),
137140
"_print_args_executable": attr.label(executable = True, cfg = "target", default = "//:print_args"),
138141
# For Windows INCLUDE. If this were eliminated, for example by the resolution of https://github.com/clangd/clangd/issues/123, we'd be able to just use a macro and skylib's expand_template rule: https://github.com/bazelbuild/bazel-skylib/pull/330

0 commit comments

Comments
 (0)