Skip to content

Commit

Permalink
waf: add support for generating compile_commands.json
Browse files Browse the repository at this point in the history
  • Loading branch information
bugobliterator committed Jun 7, 2024
1 parent cb22a63 commit 21ae64c
Showing 1 changed file with 88 additions and 1 deletion.
89 changes: 88 additions & 1 deletion Tools/ardupilotwaf/ardupilotwaf.py
Original file line number Diff line number Diff line change
Expand Up @@ -680,7 +680,94 @@ 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')
@after_method('process_use') # run it after we have collated all the libraries in ap_library
def dry_run_compilation_database(self):
if not hasattr(self, 'bld'):
return
if GEN_COMPILE_JSON:
return
GEN_COMPILE_JSON = True
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

targets = bld.targets.split(',')
for g in bld.groups:
for tg in g:
# we only care to list targets and library objects
if not hasattr(tg, 'name'):
continue
if (tg.name not in targets) and (tg.name not in self.use):
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)

0 comments on commit 21ae64c

Please sign in to comment.