blob: 04df592d942094c5c98bf3b9f6adc90d4b203f73 [file] [log] [blame]
Brian Silvermand4aea1d2015-12-09 00:24:18 -05001#!/usr/bin/python3
2
3# This reads the _compile_command files :generate_compile_commands_action
4# generates a outputs a compile_commands.json file at the top of the source
5# tree for things like clang-tidy to read.
6
7# Overall usage directions: run bazel with
8# --experimental_action_listener=//tools/actions:generate_compile_commands_listener
9# for all the files you want to use clang-tidy with and then run this script.
10# Afer that, `clang-tidy build_tests/gflags.cc` should work.
11
12import sys
13import pathlib
14import os.path
15import subprocess
Brian Silvermand4aea1d2015-12-09 00:24:18 -050016'''
17Args:
18 path: The pathlib.Path to _compile_command file.
19 command_directory: The directory commands are run from.
20
21Returns a string to stick in compile_commands.json.
22'''
Ravago Jones5127ccc2022-07-31 16:32:45 -070023
24
Brian Silvermand4aea1d2015-12-09 00:24:18 -050025def _get_command(path, command_directory):
Ravago Jones5127ccc2022-07-31 16:32:45 -070026 with path.open('r') as f:
27 contents = f.read().split('\0')
28 if len(contents) != 2:
29 # Old/incomplete file or something; silently ignore it.
30 return None
31 return '''{
Brian Silvermand4aea1d2015-12-09 00:24:18 -050032 "directory": "%s",
33 "command": "%s",
34 "file": "%s",
35 },''' % (command_directory, contents[0].replace('"', '\\"'), contents[1])
36
Ravago Jones5127ccc2022-07-31 16:32:45 -070037
Brian Silvermand4aea1d2015-12-09 00:24:18 -050038'''
39Args:
40 path: A directory pathlib.Path to look for _compile_command files under.
41 command_directory: The directory commands are run from.
42
43Yields strings to stick in compile_commands.json.
44'''
Ravago Jones5127ccc2022-07-31 16:32:45 -070045
46
Brian Silvermand4aea1d2015-12-09 00:24:18 -050047def _get_compile_commands(path, command_directory):
Ravago Jones5127ccc2022-07-31 16:32:45 -070048 for f in path.iterdir():
49 if f.is_dir():
50 yield from _get_compile_commands(f, command_directory)
51 elif f.name.endswith('_compile_command'):
52 command = _get_command(f, command_directory)
53 if command:
54 yield command
55
Brian Silvermand4aea1d2015-12-09 00:24:18 -050056
57def main(argv):
Ravago Jones5127ccc2022-07-31 16:32:45 -070058 source_path = os.path.join(os.path.dirname(__file__), '../..')
59 action_outs = os.path.join(
60 source_path, 'bazel-bin/../extra_actions',
61 'tools/actions/generate_compile_commands_action')
62 command_directory = subprocess.check_output(
63 ('bazel', 'info', 'execution_root'),
64 cwd=source_path).decode('utf-8').rstrip()
65 commands = _get_compile_commands(pathlib.Path(action_outs),
66 command_directory)
67 with open(os.path.join(source_path, 'compile_commands.json'), 'w') as f:
68 f.write('[')
69 for command in commands:
70 f.write(command)
71 f.write(']')
72
Brian Silvermand4aea1d2015-12-09 00:24:18 -050073
74if __name__ == '__main__':
Ravago Jones5127ccc2022-07-31 16:32:45 -070075 sys.exit(main(sys.argv))