7 Writes the c and cpp compile commands into build/compile_commands.json
8 see http://clang.llvm.org/docs/JSONCompilationDatabase.html
12 Load this tool in `options` to be able to generate database
13 by request in command-line and before build:
18 opt.load('clang_compilation_database')
20 Otherwise, load only in `configure` to generate it always before build.
23 conf.load('compiler_cxx')
25 conf.load('clang_compilation_database')
28 from waflib import Logs, TaskGen, Task, Build, Scripting
30 Task.Task.keep_last_cmd = True
32 class ClangDbContext(Build.BuildContext):
33 '''generates compile_commands.json by request'''
36 def write_compilation_database(self):
38 Write the clang compilation database as JSON
40 database_file = self.bldnode.make_node('compile_commands.json')
41 Logs.info('Build commands will be stored in %s', database_file.path_from(self.path))
43 root = database_file.read_json()
46 clang_db = dict((x['file'], x) for x in root)
47 for task in self.clang_compilation_database_tasks:
50 except AttributeError:
52 f_node = task.inputs[0]
53 filename = f_node.path_from(task.get_cwd())
55 "directory": task.get_cwd().abspath(),
59 clang_db[filename] = entry
60 root = list(clang_db.values())
61 database_file.write_json(root)
69 self.clang_compilation_database_tasks = []
74 self.recurse([self.run_dir])
77 # we need only to generate last_cmd, so override
78 # exec_command temporarily
79 def exec_command(self, *k, **kw):
86 except AttributeError:
91 if isinstance(tg, Task.Task):
95 if tsk.__class__.__name__ == "swig":
97 if hasattr(tsk, 'more_tasks'):
98 lst.extend(tsk.more_tasks)
99 # Not all dynamic tasks can be processed, in some cases
100 # one may have to call the method "run()" like this:
101 #elif tsk.__class__.__name__ == 'src2c':
103 # if hasattr(tsk, 'more_tasks'):
104 # lst.extend(tsk.more_tasks)
106 tup = tuple(y for y in [Task.classes.get(x) for x in ('c', 'cxx')] if y)
107 if isinstance(tsk, tup):
108 self.clang_compilation_database_tasks.append(tsk)
110 old_exec = tsk.exec_command
111 tsk.exec_command = exec_command
113 tsk.exec_command = old_exec
115 self.write_compilation_database()
117 EXECUTE_PATCHED = False
119 global EXECUTE_PATCHED
124 def new_execute_build(self):
126 Invoke clangdb command before build
128 if self.cmd.startswith('build'):
129 Scripting.run_command(self.cmd.replace('build','clangdb'))
131 old_execute_build(self)
133 old_execute_build = getattr(Build.BuildContext, 'execute_build', None)
134 setattr(Build.BuildContext, 'execute_build', new_execute_build)
135 EXECUTE_PATCHED = True