mirror of https://github.com/ArduPilot/ardupilot
waf: add support for generating compile_commands.json
This commit is contained in:
parent
7d2000f3d5
commit
b93ba1ae68
|
@ -29,7 +29,7 @@ vehicle-related headers and fails the build if they do.
|
||||||
import os
|
import os
|
||||||
import re
|
import re
|
||||||
|
|
||||||
from waflib import Errors, Task, Utils
|
from waflib import Errors, Task, Utils, Logs
|
||||||
from waflib.Configure import conf
|
from waflib.Configure import conf
|
||||||
from waflib.TaskGen import after_method, before_method, feature
|
from waflib.TaskGen import after_method, before_method, feature
|
||||||
from waflib.Tools import c_preproc
|
from waflib.Tools import c_preproc
|
||||||
|
@ -321,6 +321,125 @@ def ap_library_register_for_check(self):
|
||||||
tsk = self.create_task('ap_library_check_headers')
|
tsk = self.create_task('ap_library_check_headers')
|
||||||
tsk.compiled_task = t
|
tsk.compiled_task = t
|
||||||
|
|
||||||
|
def write_compilation_database(bld):
|
||||||
|
"""
|
||||||
|
Write the compilation database as JSON
|
||||||
|
"""
|
||||||
|
database_file = bld.bldnode.find_or_declare('compile_commands.json')
|
||||||
|
# don't remove the file at clean
|
||||||
|
|
||||||
|
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)
|
||||||
|
|
||||||
|
def target_list_changed(bld, targets):
|
||||||
|
"""
|
||||||
|
Check if the list of targets has changed recorded in target_list file
|
||||||
|
"""
|
||||||
|
# target_list file is in the root build directory
|
||||||
|
target_list_file = bld.bldnode.find_or_declare('target_list')
|
||||||
|
try:
|
||||||
|
with open(target_list_file.abspath(), 'r') as f:
|
||||||
|
old_targets = f.read().strip().split(',')
|
||||||
|
except IOError:
|
||||||
|
Logs.info('No target_list file found, creating')
|
||||||
|
old_targets = []
|
||||||
|
if old_targets != targets:
|
||||||
|
with open(target_list_file.abspath(), 'w') as f:
|
||||||
|
f.write(','.join(targets))
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
|
@conf
|
||||||
|
def remove_target_list(cfg):
|
||||||
|
target_list_file = cfg.bldnode.make_node(cfg.options.board + '/target_list')
|
||||||
|
try:
|
||||||
|
Logs.info('Removing target_list file %s', target_list_file.abspath())
|
||||||
|
os.remove(target_list_file.abspath())
|
||||||
|
except OSError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
@feature('cxxprogram', 'cxxstlib')
|
||||||
|
@after_method('propagate_uselib_vars')
|
||||||
|
def dry_run_compilation_database(self):
|
||||||
|
if not hasattr(self, 'bld'):
|
||||||
|
return
|
||||||
|
bld = self.bld
|
||||||
|
bld.compilation_database_tasks = []
|
||||||
|
targets = bld.targets.split(',')
|
||||||
|
use = self.use
|
||||||
|
if isinstance(use, str):
|
||||||
|
use = [use]
|
||||||
|
# if targets have not changed and neither has configuration,
|
||||||
|
# we can skip compilation database generation
|
||||||
|
if not target_list_changed(bld, targets + use):
|
||||||
|
Logs.info('Targets have not changed, skipping compilation database compile_commands.json generation')
|
||||||
|
return
|
||||||
|
Logs.info('Generating compile_commands.json')
|
||||||
|
# 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:
|
||||||
|
# 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 configure(cfg):
|
def configure(cfg):
|
||||||
cfg.env.AP_LIBRARIES_OBJECTS_KW = dict()
|
cfg.env.AP_LIBRARIES_OBJECTS_KW = dict()
|
||||||
cfg.env.AP_LIB_EXTRA_SOURCES = dict()
|
cfg.env.AP_LIB_EXTRA_SOURCES = dict()
|
||||||
|
|
1
wscript
1
wscript
|
@ -636,6 +636,7 @@ def configure(cfg):
|
||||||
# add in generated flags
|
# add in generated flags
|
||||||
cfg.env.CXXFLAGS += ['-include', 'ap_config.h']
|
cfg.env.CXXFLAGS += ['-include', 'ap_config.h']
|
||||||
|
|
||||||
|
cfg.remove_target_list()
|
||||||
_collect_autoconfig_files(cfg)
|
_collect_autoconfig_files(cfg)
|
||||||
|
|
||||||
def collect_dirs_to_recurse(bld, globs, **kw):
|
def collect_dirs_to_recurse(bld, globs, **kw):
|
||||||
|
|
Loading…
Reference in New Issue