From 1e9fc80fb090e6cac37c0a281cc7845074ed1449 Mon Sep 17 00:00:00 2001 From: bugobliterator Date: Wed, 5 Jun 2024 22:14:26 +1000 Subject: [PATCH] waf: add support for generating compile_commands.json --- Tools/ardupilotwaf/ardupilotwaf.py | 85 +++++++++++++++++++++++++++++- 1 file changed, 84 insertions(+), 1 deletion(-) diff --git a/Tools/ardupilotwaf/ardupilotwaf.py b/Tools/ardupilotwaf/ardupilotwaf.py index 1f5a628ff50d14..d3a32f62e9ab93 100644 --- a/Tools/ardupilotwaf/ardupilotwaf.py +++ b/Tools/ardupilotwaf/ardupilotwaf.py @@ -680,7 +680,90 @@ def options(opt): g.add_option('--ubsan-abort', action='store_true', help='''Build using the gcc undefined behaviour sanitizer and abort on error''') - + + +def write_compilation_database(bld): + """ + Write the compilation database as JSON + """ + database_file = bld.bldnode.make_node('compile_commands.json') + Logs.info('Build commands will be stored in %s', database_file.path_from(bld.path)) + try: + root = database_file.read_json() + except IOError: + root = [] + compile_cmd_db = dict((x['file'], x) for x in root) + for task in bld.compilation_database_tasks: + try: + cmd = task.last_cmd + except AttributeError: + continue + f_node = task.inputs[0] + filename = f_node.path_from(task.get_cwd()) + entry = { + "directory": task.get_cwd().abspath(), + "arguments": cmd, + "file": filename, + } + compile_cmd_db[filename] = entry + root = list(compile_cmd_db.values()) + database_file.write_json(root) + +GEN_COMPILE_JSON = False + +@feature('cxxstlib') +@before_method('process_rule') +def dry_run_compilation_database(self): + if not hasattr(self, 'bld'): + return + # we don't support more than one targets at a time + if len(self.bld.targets.split(',')) > 1: + return + bld = self.bld + bld.compilation_database_tasks = [] + # we need only to generate last_cmd, so override + # exec_command temporarily + def exec_command(bld, *k, **kw): + return 0 + + for g in bld.groups: + for tg in g: + if (not hasattr(tg, 'name')) or (tg.name not in bld.targets): + continue + try: + f = tg.post + except AttributeError: + pass + else: + f() + + if isinstance(tg, Task.Task): + lst = [tg] + else: + lst = tg.tasks + for tsk in lst: + if tsk.__class__.__name__ == "swig": + tsk.runnable_status() + if hasattr(tsk, 'more_tasks'): + lst.extend(tsk.more_tasks) + # Not all dynamic tasks can be processed, in some cases + # one may have to call the method "run()" like this: + # elif tsk.__class__.__name__ == 'src2c': + # tsk.run() + # if hasattr(tsk, 'more_tasks'): + # lst.extend(tsk.more_tasks) + + tup = tuple(y for y in [Task.classes.get(x) for x in ('c', 'cxx')] if y) + if isinstance(tsk, tup): + bld.compilation_database_tasks.append(tsk) + tsk.nocache = True + old_exec = tsk.exec_command + tsk.exec_command = exec_command + tsk.run() + tsk.exec_command = old_exec + + write_compilation_database(bld) + def build(bld): bld.add_pre_fun(_process_build_command) bld.add_pre_fun(_select_programs_from_group)