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  args = parser.parse_args()
52
53  full_deps = parseFullDeps(json.load(open(args.full_deps_file, 'r')))
54
55  try:
56    cmd = []
57
58    if args.module_name:
59      cmd = findModule(args.module_name, full_deps)['command-line']
60    elif args.tu_index != None:
61      cmd = full_deps.translation_units[args.tu_index]['command-line']
62
63    print(" ".join(map(quote, cmd)))
64  except:
65    print("Unexpected error:", sys.exc_info()[0])
66    raise
67
68if __name__ == '__main__':
69  main()
70