1#!/usr/bin/env python3
2
3# Converts clang-scan-deps output into response files.
4#
5# Usage:
6#
7#   clang-scan-deps -compilation-database compile_commands.json ... > deps.json
8#   module-deps-to-rsp.py deps.json --module-name=ModuleName > module_name.cc1.rsp
9#   module-deps-to-rsp.py deps.json --tu-index=0 > tu.rsp
10#   clang @module_name.cc1.rsp
11#   clang @tu.rsp
12
13import argparse
14import json
15import sys
16
17class ModuleNotFoundError(Exception):
18  def __init__(self, module_name):
19    self.module_name = module_name
20
21class FullDeps:
22  def __init__(self):
23    self.modules = {}
24    self.translation_units = []
25
26def findModule(module_name, full_deps):
27  for m in full_deps.modules.values():
28    if m['name'] == module_name:
29      return m
30  raise ModuleNotFoundError(module_name)
31
32def parseFullDeps(json):
33  ret = FullDeps()
34  for m in json['modules']:
35    ret.modules[m['name'] + '-' + m['context-hash']] = m
36  ret.translation_units = json['translation-units']
37  return ret
38
39def quote(str):
40  return '"' + str.replace("\\", "\\\\") + '"'
41
42def main():
43  parser = argparse.ArgumentParser()
44  parser.add_argument("full_deps_file", help="Path to the full dependencies json file",
45                      type=str)
46  action = parser.add_mutually_exclusive_group(required=True)
47  action.add_argument("--module-name", help="The name of the module to get arguments for",
48                      type=str)
49  action.add_argument("--tu-index", help="The index of the translation unit to get arguments for",
50                      type=int)
51  parser.add_argument("--tu-cmd-index",
52                      help="The index of the command within the translation unit (default=0)",
53                      type=int, default=0)
54  args = parser.parse_args()
55
56  full_deps = parseFullDeps(json.load(open(args.full_deps_file, 'r')))
57
58  try:
59    cmd = []
60
61    if args.module_name:
62      cmd = findModule(args.module_name, full_deps)['command-line']
63    elif args.tu_index != None:
64      tu = full_deps.translation_units[args.tu_index]
65      cmd = tu['commands'][args.tu_cmd_index]['command-line']
66
67    print(" ".join(map(quote, cmd)))
68  except:
69    print("Unexpected error:", sys.exc_info()[0])
70    raise
71
72if __name__ == '__main__':
73  main()
74