4 from __future__ import print_function
12 sys.path.insert(0, 'Tools/ardupilotwaf/')
18 from waflib import Build, ConfigSet, Configure, Context, Utils
19 from waflib.Configure import conf
21 # Ref: https://stackoverflow.com/questions/40590192/getting-an-error-attributeerror-module-object-has-no-attribute-run-while
23 from subprocess import CompletedProcess
26 class CompletedProcess:
28 def __init__(self, args, returncode, stdout=None, stderr=None):
30 self.returncode = returncode
34 def check_returncode(self):
35 if self.returncode != 0:
36 err = subprocess.CalledProcessError(self.returncode, self.args, output=self.stdout)
38 return self.returncode
40 def sp_run(*popenargs, **kwargs):
41 input = kwargs.pop("input", None)
42 check = kwargs.pop("handle", False)
43 kwargs.pop("capture_output", True)
46 raise ValueError('stdin and input arguments may not both be used.')
47 kwargs['stdin'] = subprocess.PIPE
48 process = subprocess.Popen(*popenargs, **kwargs)
50 outs, errs = process.communicate(input)
55 returncode = process.poll()
56 if check and returncode:
57 raise subprocess.CalledProcessError(returncode, popenargs, output=outs)
58 return CompletedProcess(popenargs, returncode, stdout=outs, stderr=errs)
60 subprocess.run = sp_run
61 # ^ This monkey patch allows it work on Python 2 or 3 the same way
64 # TODO: implement a command 'waf help' that shows the basic tasks a
65 # developer might want to do: e.g. how to configure a board, compile a
66 # vehicle, compile all the examples, add a new example. Should fit in
67 # less than a terminal screen, ideally commands should be copy
68 # pastable. Add the 'export waf="$PWD/waf"' trick to be copy-pastable
71 # TODO: replace defines with the use of the generated ap_config.h file
72 # this makes recompilation at least when defines change. which might
75 # Default installation prefix for Linux boards
76 default_prefix = '/usr/'
78 # Override Build execute and Configure post_recurse methods for autoconfigure purposes
79 Build.BuildContext.execute = ardupilotwaf.ap_autoconfigure(Build.BuildContext.execute)
80 Configure.ConfigurationContext.post_recurse = ardupilotwaf.ap_configure_post_recurse()
83 def _set_build_context_variant(board):
84 for c in Context.classes:
85 if not issubclass(c, Build.BuildContext):
89 # Remove all submodules and then sync
91 def submodule_force_clean(ctx):
97 # Get all items in the modules folder
98 module_list = os.scandir('modules')
100 # Delete all directories except those in the whitelist
101 for module in module_list:
102 if (module.is_dir()) and (module.name not in whitelist):
103 shutil.rmtree(module)
107 # run Tools/gittools/submodule-sync.sh to sync submodules
109 def submodulesync(ctx):
110 subprocess.call(['Tools/gittools/submodule-sync.sh'])
113 # Generate Task List, so that VS Code extension can keep track
114 # of changes to possible build targets
115 generate_tasklist(ctx, False)
116 env = ConfigSet.ConfigSet()
118 p = os.path.join(Context.out_dir, Build.CACHE_DIR, Build.CACHE_SUFFIX)
120 except EnvironmentError:
123 Configure.autoconfig = 'clobber' if env.AUTOCONFIG else False
125 board = ctx.options.board or env.BOARD
130 # define the variant build commands according to the board
131 _set_build_context_variant(board)
134 opt.load('compiler_cxx compiler_c waf_unit_test python')
135 opt.load('ardupilotwaf')
136 opt.load('build_summary')
138 g = opt.ap_groups['configure']
140 boards_names = boards.get_boards_names()
141 removed_names = boards.get_removed_boards()
142 g.add_option('--board',
145 help='Target board to build, choices are %s.' % ', '.join(boards_names))
147 g.add_option('--debug',
150 help='Configure as debug variant.')
152 g.add_option('--debug-symbols', '-g',
155 help='Add debug symbolds to build.')
157 g.add_option('--disable-watchdog',
160 help='Build with watchdog disabled.')
162 g.add_option('--coverage',
165 help='Configure coverage flags.')
167 g.add_option('--Werror',
170 help='build with -Werror.')
172 g.add_option('--disable-Werror',
175 help='Disable -Werror.')
177 g.add_option('--toolchain',
180 help='Override default toolchain used for the board. Use "native" for using the host toolchain.')
182 g.add_option('--disable-gccdeps',
185 help='Disable the use of GCC dependencies output method and use waf default method.')
187 g.add_option('--enable-asserts',
190 help='enable OS level asserts.')
192 g.add_option('--save-temps',
195 help='save compiler temporary files.')
197 g.add_option('--enable-malloc-guard',
200 help='enable malloc guard regions.')
202 g.add_option('--enable-stats',
205 help='enable OS level thread statistics.')
207 g.add_option('--enable-ppp',
210 help='enable PPP networking.')
212 g.add_option('--bootloader',
215 help='Configure for building a bootloader.')
217 g.add_option('--signed-fw',
220 help='Configure for signed firmware support.')
222 g.add_option('--private-key',
225 help='path to private key for signing firmware.')
227 g.add_option('--no-autoconfig',
229 action='store_false',
231 help='''Disable autoconfiguration feature. By default, the build system
232 triggers a reconfiguration whenever it thinks it's necessary - this
233 option disables that.
236 g.add_option('--no-submodule-update',
237 dest='submodule_update',
238 action='store_false',
240 help='''Don't update git submodules. Useful for building with
241 submodules at specific revisions.
244 g.add_option('--enable-header-checks', action='store_true',
246 help="Enable checking of headers")
248 g.add_option('--default-parameters',
250 help='set default parameters to embed in the firmware')
252 g.add_option('--enable-math-check-indexes',
255 help="Enable checking of math indexes")
257 g.add_option('--disable-scripting', action='store_true',
259 help="Disable onboard scripting engine")
261 g.add_option('--enable-scripting', action='store_true',
263 help="Enable onboard scripting engine")
265 g.add_option('--no-gcs', action='store_true',
267 help="Disable GCS code")
269 g.add_option('--scripting-checks', action='store_true',
271 help="Enable runtime scripting sanity checks")
273 g.add_option('--enable-onvif', action='store_true',
275 help="Enables and sets up ONVIF camera control")
277 g.add_option('--scripting-docs', action='store_true',
279 help="enable generation of scripting documentation")
281 g.add_option('--enable-opendroneid', action='store_true',
283 help="Enables OpenDroneID")
285 g.add_option('--enable-check-firmware', action='store_true',
287 help="Enables firmware ID checking on boot")
289 g.add_option('--enable-custom-controller', action='store_true',
291 help="Enables custom controller")
293 g.add_option('--enable-gps-logging', action='store_true',
295 help="Enables GPS logging")
297 g.add_option('--enable-dds', action='store_true',
298 help="Enable the dds client to connect with ROS2/DDS.")
300 g.add_option('--disable-networking', action='store_true',
301 help="Disable the networking API code")
303 g.add_option('--enable-networking-tests', action='store_true',
304 help="Enable the networking test code. Automatically enables networking.")
306 g.add_option('--enable-dronecan-tests', action='store_true',
308 help="Enables DroneCAN tests in sitl")
309 g = opt.ap_groups['linux']
311 linux_options = ('--prefix', '--destdir', '--bindir', '--libdir')
312 for k in linux_options:
313 option = opt.parser.get_option(k)
315 opt.parser.remove_option(k)
318 g.add_option('--apstatedir',
321 help='''Where to save data like parameters, log and terrain.
322 This is the --localstatedir + ArduPilots subdirectory [default:
323 board-dependent, usually /var/lib/ardupilot]''')
325 g.add_option('--rsync-dest',
329 help='''Destination for the rsync Waf command. It can be passed during
330 configuration in order to save typing.
333 g.add_option('--enable-benchmarks',
336 help='Enable benchmarks.')
338 g.add_option('--enable-lttng', action='store_true',
340 help="Enable lttng integration")
342 g.add_option('--disable-libiio', action='store_true',
344 help="Don't use libiio even if supported by board and dependencies available")
346 g.add_option('--disable-tests', action='store_true',
348 help="Disable compilation and test execution")
350 g.add_option('--enable-sfml', action='store_true',
352 help="Enable SFML graphics library")
354 g.add_option('--enable-sfml-joystick', action='store_true',
356 help="Enable SFML joystick input library")
358 g.add_option('--enable-sfml-audio', action='store_true',
360 help="Enable SFML audio library")
362 g.add_option('--osd', action='store_true',
364 help="Enable OSD support")
366 g.add_option('--osd-fonts', action='store_true',
368 help="Enable OSD support with fonts")
370 g.add_option('--sitl-osd', action='store_true',
372 help="Enable SITL OSD")
374 g.add_option('--sitl-rgbled', action='store_true',
376 help="Enable SITL RGBLed")
378 g.add_option('--force-32bit', action='store_true',
380 help="Force 32bit build")
382 g.add_option('--build-dates', action='store_true',
384 help="Include build date in binaries. Appears in AUTOPILOT_VERSION.os_sw_version")
386 g.add_option('--sitl-flash-storage',
389 help='Use flash storage emulation.')
391 g.add_option('--enable-ekf2',
394 help='Configure with EKF2.')
396 g.add_option('--disable-ekf3',
399 help='Configure without EKF3.')
401 g.add_option('--ekf-double',
404 help='Configure EKF as double precision.')
406 g.add_option('--ekf-single',
409 help='Configure EKF as single precision.')
411 g.add_option('--static',
414 help='Force a static build')
416 g.add_option('--postype-single',
419 help='force single precision postype_t')
421 g.add_option('--consistent-builds',
424 help='force consistent build outputs for things like __LINE__')
426 g.add_option('--extra-hwdef',
429 help='Extra hwdef.dat file for custom build.')
431 g.add_option('--assert-cc-version',
433 help='fail configure if not using the specified gcc version')
435 g.add_option('--num-aux-imus',
438 help='number of auxiliary IMUs')
440 g.add_option('--board-start-time',
443 help='zero time on boot in microseconds')
445 def _collect_autoconfig_files(cfg):
446 for m in sys.modules.values():
448 if hasattr(m, '__file__') and m.__file__ is not None:
449 paths.append(m.__file__)
450 elif hasattr(m, '__path__'):
456 if p in cfg.files or not os.path.isfile(p):
459 with open(p, 'rb') as f:
460 cfg.hash = Utils.h_list((cfg.hash, f.read()))
464 # we need to enable debug mode when building for gconv, and force it to sitl
465 if cfg.options.board is None:
466 cfg.options.board = 'sitl'
468 boards_names = boards.get_boards_names()
469 if not cfg.options.board in boards_names:
470 for b in boards_names:
471 if b.upper() == cfg.options.board.upper():
472 cfg.options.board = b
475 cfg.env.BOARD = cfg.options.board
476 cfg.env.DEBUG = cfg.options.debug
477 cfg.env.DEBUG_SYMBOLS = cfg.options.debug_symbols
478 cfg.env.COVERAGE = cfg.options.coverage
479 cfg.env.AUTOCONFIG = cfg.options.autoconfig
481 _set_build_context_variant(cfg.env.BOARD)
482 cfg.setenv(cfg.env.BOARD)
484 if cfg.options.signed_fw:
485 cfg.env.AP_SIGNED_FIRMWARE = True
486 cfg.options.enable_check_firmware = True
488 cfg.env.BOARD = cfg.options.board
489 cfg.env.DEBUG = cfg.options.debug
490 cfg.env.DEBUG_SYMBOLS = cfg.options.debug_symbols
491 cfg.env.COVERAGE = cfg.options.coverage
492 cfg.env.FORCE32BIT = cfg.options.force_32bit
493 cfg.env.ENABLE_ASSERTS = cfg.options.enable_asserts
494 cfg.env.BOOTLOADER = cfg.options.bootloader
495 cfg.env.ENABLE_MALLOC_GUARD = cfg.options.enable_malloc_guard
496 cfg.env.ENABLE_STATS = cfg.options.enable_stats
497 cfg.env.SAVE_TEMPS = cfg.options.save_temps
499 cfg.env.HWDEF_EXTRA = cfg.options.extra_hwdef
500 if cfg.env.HWDEF_EXTRA:
501 cfg.env.HWDEF_EXTRA = os.path.abspath(cfg.env.HWDEF_EXTRA)
503 cfg.env.OPTIONS = cfg.options.__dict__
505 # Allow to differentiate our build from the make build
506 cfg.define('WAF_BUILD', 1)
508 cfg.msg('Autoconfiguration', 'enabled' if cfg.options.autoconfig else 'disabled')
510 if cfg.options.static:
511 cfg.msg('Using static linking', 'yes', color='YELLOW')
512 cfg.env.STATIC_LINKING = True
514 if cfg.options.num_aux_imus > 0:
515 cfg.define('INS_AUX_INSTANCES', cfg.options.num_aux_imus)
517 if cfg.options.board_start_time != 0:
518 cfg.define('AP_BOARD_START_TIME', cfg.options.board_start_time)
519 # also in env for hrt.c
520 cfg.env.AP_BOARD_START_TIME = cfg.options.board_start_time
522 # require python 3.8.x or later
524 cfg.check_python_version(minver=(3,6,9))
526 cfg.load('ap_library')
528 cfg.msg('Setting board to', cfg.options.board)
529 cfg.get_board().configure(cfg)
531 cfg.load('waf_unit_test')
533 cfg.load('dronecangen')
535 cfg.env.SUBMODULE_UPDATE = cfg.options.submodule_update
537 cfg.start_msg('Source is git repository')
538 if cfg.srcnode.find_node('.git'):
542 cfg.env.SUBMODULE_UPDATE = False
544 cfg.msg('Update submodules', 'yes' if cfg.env.SUBMODULE_UPDATE else 'no')
545 cfg.load('git_submodule')
547 if cfg.options.enable_benchmarks:
548 cfg.load('gbenchmark')
550 cfg.load('static_linking')
551 cfg.load('build_summary')
553 cfg.start_msg('Benchmarks')
554 if cfg.env.HAS_GBENCHMARK:
555 cfg.end_msg('enabled')
557 cfg.end_msg('disabled', color='YELLOW')
559 cfg.start_msg('Unit tests')
560 if cfg.env.HAS_GTEST:
561 cfg.end_msg('enabled')
563 cfg.end_msg('disabled', color='YELLOW')
565 cfg.start_msg('Scripting')
566 if cfg.options.disable_scripting:
567 cfg.end_msg('disabled', color='YELLOW')
568 elif cfg.options.enable_scripting:
569 cfg.end_msg('enabled')
572 cfg.recurse('libraries/AP_Scripting')
574 cfg.recurse('libraries/AP_GPS')
575 cfg.recurse('libraries/AP_HAL_SITL')
576 cfg.recurse('libraries/SITL')
578 cfg.recurse('libraries/AP_Networking')
580 cfg.start_msg('Scripting runtime checks')
581 if cfg.options.scripting_checks:
582 cfg.end_msg('enabled')
584 cfg.end_msg('disabled', color='YELLOW')
586 cfg.start_msg('Debug build')
588 cfg.end_msg('enabled')
590 cfg.end_msg('disabled', color='YELLOW')
592 cfg.start_msg('Coverage build')
594 cfg.end_msg('enabled')
596 cfg.end_msg('disabled', color='YELLOW')
598 cfg.start_msg('Force 32-bit build')
599 if cfg.env.FORCE32BIT:
600 cfg.end_msg('enabled')
602 cfg.end_msg('disabled', color='YELLOW')
604 cfg.env.append_value('GIT_SUBMODULES', 'mavlink')
606 cfg.env.prepend_value('INCLUDES', [
607 cfg.srcnode.abspath() + '/libraries/',
610 cfg.find_program('rsync', mandatory=False)
611 if cfg.options.rsync_dest:
612 cfg.msg('Setting rsync destination to', cfg.options.rsync_dest)
613 cfg.env.RSYNC_DEST = cfg.options.rsync_dest
615 if cfg.options.enable_header_checks:
616 cfg.msg('Enabling header checks', cfg.options.enable_header_checks)
617 cfg.env.ENABLE_HEADER_CHECKS = True
619 cfg.env.ENABLE_HEADER_CHECKS = False
621 # Always use system extensions
622 cfg.define('_GNU_SOURCE', 1)
624 if cfg.options.Werror:
625 # print(cfg.options.Werror)
626 if cfg.options.disable_Werror:
627 cfg.options.Werror = False
629 cfg.write_config_header(os.path.join(cfg.variant, 'ap_config.h'), guard='_AP_CONFIG_H_')
631 # add in generated flags
632 cfg.env.CXXFLAGS += ['-include', 'ap_config.h']
634 _collect_autoconfig_files(cfg)
636 def collect_dirs_to_recurse(bld, globs, **kw):
638 globs = Utils.to_list(globs)
640 if bld.bldnode.is_child_of(bld.srcnode):
641 kw['excl'] = Utils.to_list(kw.get('excl', []))
642 kw['excl'].append(bld.bldnode.path_from(bld.srcnode))
645 for d in bld.srcnode.ant_glob(g + '/wscript', **kw):
646 dirs.append(d.parent.relpath())
649 def list_boards(ctx):
650 print(*boards.get_boards_names())
652 def list_ap_periph_boards(ctx):
653 print(*boards.get_ap_periph_boards())
656 def ap_periph_boards(ctx):
657 return boards.get_ap_periph_boards()
659 vehicles = ['antennatracker', 'blimp', 'copter', 'heli', 'plane', 'rover', 'sub']
661 def generate_tasklist(ctx, do_print=True):
662 boardlist = boards.get_boards_names()
663 ap_periph_targets = boards.get_ap_periph_boards()
665 with open(os.path.join(Context.top_dir, "tasklist.json"), "w") as tlist:
666 for board in boardlist:
668 task['configure'] = board
669 if board in ap_periph_targets:
670 if 'sitl' not in board:
671 # we only support AP_Periph and bootloader builds
672 task['targets'] = ['AP_Periph', 'bootloader']
674 task['targets'] = ['AP_Periph']
675 elif 'iofirmware' in board:
676 task['targets'] = ['iofirmware', 'bootloader']
678 if boards.is_board_based(board, boards.sitl):
679 task['targets'] = vehicles + ['replay']
680 elif boards.is_board_based(board, boards.linux):
681 task['targets'] = vehicles
683 task['targets'] = vehicles + ['bootloader']
684 task['buildOptions'] = '--upload'
686 tlist.write(json.dumps(tasks))
688 print(json.dumps(tasks))
691 env = ConfigSet.ConfigSet()
693 p = os.path.join(Context.out_dir, Build.CACHE_DIR, Build.CACHE_SUFFIX)
696 print('No board currently configured')
699 print('Board configured to: {}'.format(env.BOARD))
701 def _build_cmd_tweaks(bld):
702 if bld.cmd == 'check-all':
703 bld.options.all_tests = True
706 if bld.cmd == 'check':
707 if not bld.env.HAS_GTEST:
708 bld.fatal('check: gtest library is required')
709 bld.options.clear_failed_tests = True
711 def _build_dynamic_sources(bld):
712 if not bld.env.BOOTLOADER:
715 source='modules/mavlink/message_definitions/v1.0/all.xml',
716 output_dir='libraries/GCS_MAVLink/include/mavlink/v2.0/',
718 # this below is not ideal, mavgen tool should set this, but that's not
721 bld.bldnode.make_node('libraries').abspath(),
722 bld.bldnode.make_node('libraries/GCS_MAVLink').abspath(),
726 if (bld.get_board().with_can or bld.env.HAL_NUM_CAN_IFACES) and not bld.env.AP_PERIPH:
728 features='dronecangen',
729 source=bld.srcnode.ant_glob('modules/DroneCAN/DSDL/[a-z]* libraries/AP_DroneCAN/dsdl/[a-z]*', dir=True, src=False),
730 output_dir='modules/DroneCAN/libcanard/dsdlc_generated/',
733 bld.bldnode.make_node('modules/DroneCAN/libcanard/dsdlc_generated/include').abspath(),
734 bld.srcnode.find_dir('modules/DroneCAN/libcanard/').abspath(),
735 bld.srcnode.find_dir('libraries/AP_DroneCAN/canard/').abspath(),
738 elif bld.env.AP_PERIPH:
740 features='dronecangen',
741 source=bld.srcnode.ant_glob('modules/DroneCAN/DSDL/* libraries/AP_DroneCAN/dsdl/*', dir=True, src=False),
742 output_dir='modules/DroneCAN/libcanard/dsdlc_generated/',
745 bld.bldnode.make_node('modules/DroneCAN/libcanard/dsdlc_generated/include').abspath(),
746 bld.srcnode.find_dir('modules/DroneCAN/libcanard/').abspath(),
750 if bld.env.ENABLE_DDS:
751 bld.recurse("libraries/AP_DDS")
753 def write_version_header(tsk):
754 bld = tsk.generator.bld
755 return bld.write_version_header(tsk.outputs[0].abspath())
759 target='ap_version.h',
760 vars=['AP_VERSION_ITEMS'],
761 rule=write_version_header,
764 bld.env.prepend_value('INCLUDES', [
765 bld.bldnode.abspath(),
768 def _build_common_taskgens(bld):
769 # NOTE: Static library with vehicle set to UNKNOWN, shared by all
770 # the tools and examples. This is the first step until the
771 # dependency on the vehicles is reduced. Later we may consider
772 # split into smaller pieces with well defined boundaries.
775 ap_vehicle='UNKNOWN',
776 ap_libraries=bld.ap_get_all_libraries(),
779 if bld.env.HAS_GTEST:
780 bld.libgtest(cxxflags=['-include', 'ap_config.h'])
782 if bld.env.HAS_GBENCHMARK:
785 def _build_recursion(bld):
786 common_dirs_patterns = [
787 # TODO: Currently each vehicle also generate its own copy of the
788 # libraries. Fix this, or at least reduce the amount of
789 # vehicle-dependent libraries.
792 'libraries/*/examples/*',
794 'libraries/*/utility/tests',
795 'libraries/*/benchmarks',
800 'libraries/AP_HAL_*',
803 hal_dirs_patterns = [
804 'libraries/%s/tests',
805 'libraries/%s/*/tests',
806 'libraries/%s/*/benchmarks',
807 'libraries/%s/examples/*',
810 dirs_to_recurse = collect_dirs_to_recurse(
812 common_dirs_patterns,
813 excl=common_dirs_excl,
815 if bld.env.IOMCU_FW is not None:
817 dirs_to_recurse.append('libraries/AP_IOMCU/iofirmware')
819 if bld.env.PERIPH_FW is not None:
820 if bld.env.PERIPH_FW:
821 dirs_to_recurse.append('Tools/AP_Periph')
823 dirs_to_recurse.append('libraries/AP_Scripting')
825 if bld.env.ENABLE_ONVIF:
826 dirs_to_recurse.append('libraries/AP_ONVIF')
828 for p in hal_dirs_patterns:
829 dirs_to_recurse += collect_dirs_to_recurse(
831 [p % l for l in bld.env.AP_LIBRARIES],
834 # NOTE: we need to sort to ensure the repeated sources get the
835 # same index, and random ordering of the filesystem doesn't cause
837 dirs_to_recurse.sort()
839 for d in dirs_to_recurse:
842 def _build_post_funs(bld):
843 if bld.cmd == 'check':
844 bld.add_post_fun(ardupilotwaf.test_summary)
846 bld.build_summary_post_fun()
848 if bld.env.SUBMODULE_UPDATE:
849 bld.git_submodule_post_fun()
851 def _load_pre_build(bld):
852 '''allow for a pre_build() function in build modules'''
853 if bld.cmd == 'clean':
855 brd = bld.get_board()
856 if getattr(brd, 'pre_build', None):
860 config_hash = Utils.h_file(bld.bldnode.make_node('ap_config.h').abspath())
861 bld.env.CCDEPS = config_hash
862 bld.env.CXXDEPS = config_hash
864 bld.post_mode = Build.POST_LAZY
866 bld.load('ardupilotwaf')
868 bld.env.AP_LIBRARIES_OBJECTS_KW.update(
870 cxxflags=['-include', 'ap_config.h'],
875 if bld.get_board().with_can:
876 bld.env.AP_LIBRARIES_OBJECTS_KW['use'] += ['dronecan']
878 _build_cmd_tweaks(bld)
880 if bld.env.SUBMODULE_UPDATE:
881 bld.add_group('git_submodules')
882 for name in bld.env.GIT_SUBMODULES:
883 bld.git_submodule(name)
885 bld.add_group('dynamic_sources')
886 _build_dynamic_sources(bld)
888 bld.add_group('build')
889 bld.get_board().build(bld)
890 _build_common_taskgens(bld)
892 _build_recursion(bld)
894 _build_post_funs(bld)
896 ardupilotwaf.build_command('check',
897 program_group_list='all',
898 doc='builds all programs and run tests',
900 ardupilotwaf.build_command('check-all',
901 program_group_list='all',
902 doc='shortcut for `waf check --alltests`',
905 for name in (vehicles + ['bootloader','iofirmware','AP_Periph','replay']):
906 ardupilotwaf.build_command(name,
907 program_group_list=name,
908 doc='builds %s programs' % name,
911 for program_group in ('all', 'bin', 'tool', 'examples', 'tests', 'benchmarks'):
912 ardupilotwaf.build_command(program_group,
913 program_group_list=program_group,
914 doc='builds all programs of %s group' % program_group,
917 class LocalInstallContext(Build.InstallContext):
918 """runs install using BLD/install as destdir, where BLD is the build variant directory"""
921 def __init__(self, **kw):
922 super(LocalInstallContext, self).__init__(**kw)
923 self.local_destdir = os.path.join(self.variant_dir, 'install')
926 old_destdir = self.options.destdir
927 self.options.destdir = self.local_destdir
928 r = super(LocalInstallContext, self).execute()
929 self.options.destdir = old_destdir
932 class RsyncContext(LocalInstallContext):
933 """runs localinstall and then rsyncs BLD/install with the target system"""
936 def __init__(self, **kw):
937 super(RsyncContext, self).__init__(**kw)
938 self.add_pre_fun(RsyncContext.create_rsync_taskgen)
940 def create_rsync_taskgen(self):
941 if 'RSYNC' not in self.env:
942 self.fatal('rsync program seems not to be installed, can\'t continue')
948 rule='${RSYNC} -a ${RSYNC_SRC}/ ${RSYNC_DEST}',
952 tg.env.RSYNC_SRC = self.local_destdir
953 if self.options.rsync_dest:
954 self.env.RSYNC_DEST = self.options.rsync_dest
956 if 'RSYNC_DEST' not in tg.env:
957 self.fatal('Destination for rsync not defined. Either pass --rsync-dest here or during configuration.')