2015-10-09 11:03:59 -03:00
|
|
|
#!/usr/bin/env python
|
|
|
|
# encoding: utf-8
|
|
|
|
|
2015-10-30 13:14:28 -03:00
|
|
|
from __future__ import print_function
|
2016-01-15 12:02:21 -04:00
|
|
|
from waflib import Logs, Options, Utils
|
2016-01-27 08:22:24 -04:00
|
|
|
from waflib.Build import BuildContext
|
2016-01-21 09:30:22 -04:00
|
|
|
from waflib.Configure import conf
|
2016-01-17 14:57:31 -04:00
|
|
|
import os.path
|
2015-10-30 12:50:44 -03:00
|
|
|
|
2015-10-09 11:03:59 -03:00
|
|
|
SOURCE_EXTS = [
|
|
|
|
'*.S',
|
|
|
|
'*.c',
|
|
|
|
'*.cpp',
|
|
|
|
]
|
|
|
|
|
|
|
|
UTILITY_SOURCE_EXTS = [ 'utility/' + glob for glob in SOURCE_EXTS ]
|
|
|
|
|
|
|
|
COMMON_VEHICLE_DEPENDENT_LIBRARIES = [
|
2015-12-30 08:42:20 -04:00
|
|
|
'AP_AccelCal',
|
2015-10-09 11:03:59 -03:00
|
|
|
'AP_ADC',
|
|
|
|
'AP_AHRS',
|
|
|
|
'AP_Airspeed',
|
|
|
|
'AP_Baro',
|
|
|
|
'AP_BattMonitor',
|
|
|
|
'AP_BoardConfig',
|
|
|
|
'AP_Buffer',
|
|
|
|
'AP_Common',
|
|
|
|
'AP_Compass',
|
|
|
|
'AP_Declination',
|
|
|
|
'AP_GPS',
|
|
|
|
'AP_HAL',
|
|
|
|
'AP_HAL_Empty',
|
|
|
|
'AP_InertialSensor',
|
|
|
|
'AP_Math',
|
|
|
|
'AP_Mission',
|
|
|
|
'AP_NavEKF',
|
|
|
|
'AP_NavEKF2',
|
|
|
|
'AP_Notify',
|
|
|
|
'AP_OpticalFlow',
|
|
|
|
'AP_Param',
|
|
|
|
'AP_Rally',
|
|
|
|
'AP_RangeFinder',
|
|
|
|
'AP_Scheduler',
|
|
|
|
'AP_SerialManager',
|
|
|
|
'AP_Terrain',
|
|
|
|
'AP_Vehicle',
|
|
|
|
'DataFlash',
|
|
|
|
'Filter',
|
|
|
|
'GCS_MAVLink',
|
|
|
|
'RC_Channel',
|
|
|
|
'StorageManager',
|
|
|
|
]
|
|
|
|
|
2016-01-22 16:21:09 -04:00
|
|
|
def _get_legacy_defines(sketch_name):
|
2015-10-09 11:03:59 -03:00
|
|
|
return [
|
2016-01-22 16:21:09 -04:00
|
|
|
'APM_BUILD_DIRECTORY=APM_BUILD_' + sketch_name,
|
|
|
|
'SKETCH="' + sketch_name + '"',
|
|
|
|
'SKETCHNAME="' + sketch_name + '"',
|
2015-10-09 11:03:59 -03:00
|
|
|
]
|
|
|
|
|
|
|
|
IGNORED_AP_LIBRARIES = [
|
|
|
|
'doc',
|
|
|
|
'GCS_Console',
|
|
|
|
]
|
|
|
|
|
2016-01-21 09:30:22 -04:00
|
|
|
@conf
|
2016-01-22 17:00:13 -04:00
|
|
|
def ap_get_all_libraries(bld):
|
2015-10-09 11:03:59 -03:00
|
|
|
libraries = []
|
|
|
|
for lib_node in bld.srcnode.ant_glob('libraries/*', dir=True):
|
|
|
|
name = lib_node.name
|
|
|
|
if name in IGNORED_AP_LIBRARIES:
|
|
|
|
continue
|
|
|
|
if name.startswith('AP_HAL'):
|
|
|
|
continue
|
2016-02-24 14:35:46 -04:00
|
|
|
if name == 'SITL':
|
|
|
|
continue
|
2015-10-09 11:03:59 -03:00
|
|
|
libraries.append(name)
|
|
|
|
libraries.extend(['AP_HAL', 'AP_HAL_Empty'])
|
|
|
|
return libraries
|
|
|
|
|
2016-01-21 09:30:22 -04:00
|
|
|
@conf
|
2016-01-22 17:00:13 -04:00
|
|
|
def ap_common_vehicle_libraries(bld):
|
2016-01-21 09:30:22 -04:00
|
|
|
return COMMON_VEHICLE_DEPENDENT_LIBRARIES
|
|
|
|
|
2016-01-22 08:26:08 -04:00
|
|
|
_grouped_programs = {}
|
|
|
|
|
2016-01-21 09:30:22 -04:00
|
|
|
@conf
|
2016-03-24 16:47:30 -03:00
|
|
|
def ap_program(bld,
|
2016-03-24 16:58:15 -03:00
|
|
|
program_groups='bin',
|
2016-03-24 16:47:30 -03:00
|
|
|
program_dir=None,
|
|
|
|
use_legacy_defines=True,
|
|
|
|
program_name=None,
|
|
|
|
**kw):
|
2015-10-09 11:03:59 -03:00
|
|
|
if 'target' in kw:
|
|
|
|
bld.fatal('Do not pass target for program')
|
|
|
|
if 'defines' not in kw:
|
|
|
|
kw['defines'] = []
|
|
|
|
if 'source' not in kw:
|
|
|
|
kw['source'] = bld.path.ant_glob(SOURCE_EXTS)
|
|
|
|
|
2016-01-11 16:23:59 -04:00
|
|
|
if not program_name:
|
|
|
|
program_name = bld.path.name
|
2016-01-08 17:28:04 -04:00
|
|
|
|
|
|
|
if use_legacy_defines:
|
2016-01-22 16:21:09 -04:00
|
|
|
kw['defines'].extend(_get_legacy_defines(bld.path.name))
|
2015-10-09 11:03:59 -03:00
|
|
|
|
2016-03-02 17:08:39 -04:00
|
|
|
kw['features'] = kw.get('features', []) + bld.env.AP_PROGRAM_FEATURES
|
2016-03-02 17:20:45 -04:00
|
|
|
|
2016-03-24 16:58:15 -03:00
|
|
|
program_groups = Utils.to_list(program_groups)
|
|
|
|
|
2016-03-24 16:47:30 -03:00
|
|
|
if not program_dir:
|
2016-03-24 16:58:15 -03:00
|
|
|
program_dir = program_groups[0]
|
2016-03-24 16:47:30 -03:00
|
|
|
|
|
|
|
name = os.path.join(program_dir, program_name)
|
2016-01-11 17:47:40 -04:00
|
|
|
|
2016-02-25 08:50:41 -04:00
|
|
|
tg_constructor = bld.program
|
|
|
|
if bld.env.AP_PROGRAM_AS_STLIB:
|
|
|
|
tg_constructor = bld.stlib
|
|
|
|
else:
|
|
|
|
if bld.env.STATIC_LINKING:
|
|
|
|
kw['features'].append('static_linking')
|
|
|
|
|
|
|
|
|
|
|
|
tg = tg_constructor(
|
2016-02-26 15:29:34 -04:00
|
|
|
target='#%s' % name,
|
2016-01-16 22:33:00 -04:00
|
|
|
name=name,
|
2016-02-25 09:04:46 -04:00
|
|
|
program_name=program_name,
|
2016-03-24 16:47:30 -03:00
|
|
|
program_dir=program_dir,
|
2015-10-09 11:03:59 -03:00
|
|
|
**kw
|
|
|
|
)
|
2016-03-24 16:58:15 -03:00
|
|
|
|
|
|
|
for group in program_groups:
|
|
|
|
_grouped_programs.setdefault(group, []).append(tg)
|
2015-10-09 11:03:59 -03:00
|
|
|
|
2016-01-21 09:30:22 -04:00
|
|
|
@conf
|
2016-01-22 17:00:13 -04:00
|
|
|
def ap_example(bld, **kw):
|
2016-03-24 16:58:15 -03:00
|
|
|
kw['program_groups'] = 'examples'
|
2016-01-21 08:10:44 -04:00
|
|
|
ap_program(bld, **kw)
|
2016-01-08 16:47:35 -04:00
|
|
|
|
2015-10-09 11:03:59 -03:00
|
|
|
# NOTE: Code in libraries/ is compiled multiple times. So ensure each
|
|
|
|
# compilation is independent by providing different index for each.
|
|
|
|
# The need for this should disappear when libraries change to be
|
|
|
|
# independent of vehicle type.
|
|
|
|
LAST_IDX = 0
|
|
|
|
|
|
|
|
def _get_next_idx():
|
|
|
|
global LAST_IDX
|
|
|
|
LAST_IDX += 1
|
|
|
|
return LAST_IDX
|
|
|
|
|
2016-01-21 09:30:22 -04:00
|
|
|
@conf
|
2016-01-21 08:53:08 -04:00
|
|
|
def ap_stlib(bld, **kw):
|
2015-10-09 11:03:59 -03:00
|
|
|
if 'name' not in kw:
|
2016-01-21 08:53:08 -04:00
|
|
|
bld.fatal('Missing name for ap_stlib')
|
2015-10-09 11:03:59 -03:00
|
|
|
if 'vehicle' not in kw:
|
2016-01-21 08:53:08 -04:00
|
|
|
bld.fatal('Missing vehicle for ap_stlib')
|
2015-10-09 11:03:59 -03:00
|
|
|
if 'libraries' not in kw:
|
2016-01-21 08:53:08 -04:00
|
|
|
bld.fatal('Missing libraries for ap_stlib')
|
2015-10-09 11:03:59 -03:00
|
|
|
|
|
|
|
sources = []
|
|
|
|
libraries = kw['libraries'] + bld.env.AP_LIBRARIES
|
|
|
|
|
|
|
|
for lib_name in libraries:
|
|
|
|
lib_node = bld.srcnode.find_dir('libraries/' + lib_name)
|
|
|
|
if lib_node is None:
|
|
|
|
bld.fatal('Could not find library ' + lib_name)
|
|
|
|
lib_sources = lib_node.ant_glob(SOURCE_EXTS + UTILITY_SOURCE_EXTS)
|
|
|
|
sources.extend(lib_sources)
|
|
|
|
|
2016-03-02 17:08:39 -04:00
|
|
|
kw['features'] = kw.get('features', []) + bld.env.AP_STLIB_FEATURES
|
2016-01-13 16:29:22 -04:00
|
|
|
kw['source'] = sources
|
|
|
|
kw['target'] = kw['name']
|
|
|
|
kw['defines'] = _get_legacy_defines(kw['vehicle'])
|
|
|
|
kw['idx'] = _get_next_idx()
|
|
|
|
|
|
|
|
bld.stlib(**kw)
|
2015-10-30 12:50:44 -03:00
|
|
|
|
2016-01-21 09:30:22 -04:00
|
|
|
@conf
|
2016-01-22 17:00:13 -04:00
|
|
|
def ap_find_tests(bld, use=[]):
|
2015-10-30 13:14:28 -03:00
|
|
|
if not bld.env.HAS_GTEST:
|
|
|
|
return
|
|
|
|
|
2016-03-02 17:16:14 -04:00
|
|
|
features = []
|
2015-10-30 12:50:44 -03:00
|
|
|
if bld.cmd == 'check':
|
2016-01-07 07:16:53 -04:00
|
|
|
features.append('test')
|
2015-10-30 12:50:44 -03:00
|
|
|
|
2015-10-30 13:14:28 -03:00
|
|
|
use = Utils.to_list(use)
|
|
|
|
use.append('GTEST')
|
|
|
|
|
|
|
|
includes = [bld.srcnode.abspath() + '/tests/']
|
|
|
|
|
2015-10-30 12:50:44 -03:00
|
|
|
for f in bld.path.ant_glob(incl='*.cpp'):
|
2016-01-21 08:10:44 -04:00
|
|
|
ap_program(
|
2016-01-11 08:19:29 -04:00
|
|
|
bld,
|
2015-10-30 12:50:44 -03:00
|
|
|
features=features,
|
2015-10-30 13:14:28 -03:00
|
|
|
includes=includes,
|
2015-10-30 12:50:44 -03:00
|
|
|
source=[f],
|
|
|
|
use=use,
|
2016-01-11 09:21:57 -04:00
|
|
|
program_name=f.change_ext('').name,
|
2016-03-24 16:58:15 -03:00
|
|
|
program_groups='tests',
|
2016-01-11 08:19:29 -04:00
|
|
|
use_legacy_defines=False,
|
2016-02-18 10:45:21 -04:00
|
|
|
cxxflags=['-Wno-undef'],
|
2015-10-30 12:50:44 -03:00
|
|
|
)
|
|
|
|
|
2016-01-21 09:30:22 -04:00
|
|
|
@conf
|
2016-01-22 17:00:13 -04:00
|
|
|
def ap_find_benchmarks(bld, use=[]):
|
2015-11-12 17:39:30 -04:00
|
|
|
if not bld.env.HAS_GBENCHMARK:
|
|
|
|
return
|
|
|
|
|
|
|
|
includes = [bld.srcnode.abspath() + '/benchmarks/']
|
|
|
|
|
|
|
|
for f in bld.path.ant_glob(incl='*.cpp'):
|
2016-01-21 08:10:44 -04:00
|
|
|
ap_program(
|
2016-01-11 08:19:29 -04:00
|
|
|
bld,
|
2016-03-02 17:16:14 -04:00
|
|
|
features=['gbenchmark'],
|
2015-11-12 17:39:30 -04:00
|
|
|
includes=includes,
|
|
|
|
source=[f],
|
|
|
|
use=use,
|
2016-01-11 09:21:57 -04:00
|
|
|
program_name=f.change_ext('').name,
|
2016-03-24 16:58:15 -03:00
|
|
|
program_groups='benchmarks',
|
2016-01-11 08:19:29 -04:00
|
|
|
use_legacy_defines=False,
|
2015-11-12 17:39:30 -04:00
|
|
|
)
|
|
|
|
|
2015-10-30 12:50:44 -03:00
|
|
|
def test_summary(bld):
|
|
|
|
from io import BytesIO
|
|
|
|
import sys
|
|
|
|
|
|
|
|
if not hasattr(bld, 'utest_results'):
|
|
|
|
Logs.info('check: no test run')
|
|
|
|
return
|
|
|
|
|
|
|
|
fails = []
|
|
|
|
|
|
|
|
for filename, exit_code, out, err in bld.utest_results:
|
|
|
|
Logs.pprint('GREEN' if exit_code == 0 else 'YELLOW',
|
|
|
|
' %s' % filename,
|
|
|
|
'returned %d' % exit_code)
|
|
|
|
|
|
|
|
if exit_code != 0:
|
|
|
|
fails.append(filename)
|
|
|
|
elif not bld.options.check_verbose:
|
|
|
|
continue
|
|
|
|
|
|
|
|
if len(out):
|
|
|
|
buf = BytesIO(out)
|
|
|
|
for line in buf:
|
|
|
|
print(" OUT: %s" % line.decode(), end='', file=sys.stderr)
|
|
|
|
print()
|
|
|
|
|
|
|
|
if len(err):
|
|
|
|
buf = BytesIO(err)
|
|
|
|
for line in buf:
|
|
|
|
print(" ERR: %s" % line.decode(), end='', file=sys.stderr)
|
|
|
|
print()
|
|
|
|
|
|
|
|
if not fails:
|
|
|
|
Logs.info('check: All %u tests passed!' % len(bld.utest_results))
|
|
|
|
return
|
|
|
|
|
|
|
|
Logs.error('check: %u of %u tests failed' %
|
|
|
|
(len(fails), len(bld.utest_results)))
|
|
|
|
|
|
|
|
for filename in fails:
|
|
|
|
Logs.error(' %s' % filename)
|
2016-01-15 12:02:21 -04:00
|
|
|
|
2016-01-18 13:57:32 -04:00
|
|
|
bld.fatal('check: some tests failed')
|
|
|
|
|
2016-01-27 12:16:37 -04:00
|
|
|
_build_commands = {}
|
2016-01-15 12:02:21 -04:00
|
|
|
|
2016-01-27 12:16:37 -04:00
|
|
|
def _process_build_command(bld):
|
|
|
|
if bld.cmd not in _build_commands:
|
2016-01-27 08:22:24 -04:00
|
|
|
return
|
|
|
|
|
2016-01-27 12:16:37 -04:00
|
|
|
params = _build_commands[bld.cmd]
|
2016-01-27 08:22:24 -04:00
|
|
|
|
|
|
|
targets = params['targets']
|
|
|
|
if targets:
|
|
|
|
if bld.targets:
|
|
|
|
bld.targets += ',' + targets
|
|
|
|
else:
|
|
|
|
bld.targets = targets
|
|
|
|
|
2016-01-27 08:56:30 -04:00
|
|
|
program_group_list = Utils.to_list(params['program_group_list'])
|
|
|
|
bld.options.program_group.extend(program_group_list)
|
|
|
|
|
2016-01-27 12:16:37 -04:00
|
|
|
def build_command(name,
|
2016-01-27 11:45:46 -04:00
|
|
|
targets=None,
|
|
|
|
program_group_list=[],
|
|
|
|
doc='build shortcut'):
|
2016-01-27 12:16:37 -04:00
|
|
|
_build_commands[name] = dict(
|
2016-01-27 08:22:24 -04:00
|
|
|
targets=targets,
|
2016-01-27 08:56:30 -04:00
|
|
|
program_group_list=program_group_list,
|
2016-01-27 08:22:24 -04:00
|
|
|
)
|
2016-01-15 12:02:21 -04:00
|
|
|
|
2016-01-27 08:22:24 -04:00
|
|
|
class context_class(BuildContext):
|
|
|
|
cmd = name
|
2016-01-27 11:45:46 -04:00
|
|
|
context_class.__doc__ = doc
|
2016-01-22 08:26:08 -04:00
|
|
|
|
|
|
|
def _select_programs_from_group(bld):
|
|
|
|
groups = bld.options.program_group
|
|
|
|
if not groups:
|
|
|
|
if bld.targets:
|
|
|
|
groups = []
|
|
|
|
else:
|
|
|
|
groups = ['bin']
|
|
|
|
|
|
|
|
if 'all' in groups:
|
|
|
|
groups = _grouped_programs.keys()
|
|
|
|
|
|
|
|
for group in groups:
|
|
|
|
if group not in _grouped_programs:
|
|
|
|
bld.fatal('Group %s not found' % group)
|
|
|
|
|
|
|
|
tg = _grouped_programs[group][0]
|
|
|
|
if bld.targets:
|
|
|
|
bld.targets += ',' + tg.name
|
|
|
|
else:
|
|
|
|
bld.targets = tg.name
|
|
|
|
|
|
|
|
for tg in _grouped_programs[group][1:]:
|
|
|
|
bld.targets += ',' + tg.name
|
|
|
|
|
|
|
|
def options(opt):
|
2016-02-17 08:48:08 -04:00
|
|
|
g = opt.ap_groups['build']
|
2016-01-22 08:26:08 -04:00
|
|
|
g.add_option('--program-group',
|
|
|
|
action='append',
|
|
|
|
default=[],
|
|
|
|
help='Select all programs that go in <PROGRAM_GROUP>/ for the ' +
|
|
|
|
'build. Example: `waf --program-group examples` builds all ' +
|
|
|
|
'examples. The special group "all" selects all programs.',
|
|
|
|
)
|
|
|
|
|
2016-03-02 18:09:58 -04:00
|
|
|
g.add_option('--upload',
|
|
|
|
action='store_true',
|
|
|
|
help='Upload applicable targets to a connected device. Not all ' +
|
|
|
|
'platforms may support this. Example: `waf copter --upload` ' +
|
|
|
|
'means "build arducopter and upload it to my board".',
|
|
|
|
)
|
|
|
|
|
2016-02-17 08:55:59 -04:00
|
|
|
g = opt.ap_groups['check']
|
|
|
|
g.add_option('--check-verbose',
|
|
|
|
action='store_true',
|
|
|
|
help='Output all test programs')
|
|
|
|
|
2016-03-02 18:09:58 -04:00
|
|
|
|
2016-01-22 08:26:08 -04:00
|
|
|
def build(bld):
|
2016-02-03 09:00:35 -04:00
|
|
|
global LAST_IDX
|
|
|
|
# FIXME: This is done to prevent same task generators being created with
|
|
|
|
# different idx when build() is called multiple times (e.g. waf bin tests).
|
|
|
|
# Ideally, task generators should be created just once.
|
|
|
|
LAST_IDX = 0
|
2016-01-27 12:16:37 -04:00
|
|
|
bld.add_pre_fun(_process_build_command)
|
2016-01-22 08:26:08 -04:00
|
|
|
bld.add_pre_fun(_select_programs_from_group)
|