4 from __future__ import print_function
12 sys.path.insert(0, 'Tools/ardupilotwaf/')
13 sys.path.insert(0, 'Tools/scripts/')
20 from waflib import Build, ConfigSet, Configure, Context, Utils
21 from waflib.Configure import conf
23 # Ref: https://stackoverflow.com/questions/40590192/getting-an-error-attributeerror-module-object-has-no-attribute-run-while
25 from subprocess import CompletedProcess
28 class CompletedProcess:
30 def __init__(self, args, returncode, stdout=None, stderr=None):
32 self.returncode = returncode
36 def check_returncode(self):
37 if self.returncode != 0:
38 err = subprocess.CalledProcessError(self.returncode, self.args, output=self.stdout)
40 return self.returncode
42 def sp_run(*popenargs, **kwargs):
43 input = kwargs.pop("input", None)
44 check = kwargs.pop("handle", False)
45 kwargs.pop("capture_output", True)
48 raise ValueError('stdin and input arguments may not both be used.')
49 kwargs['stdin'] = subprocess.PIPE
50 process = subprocess.Popen(*popenargs, **kwargs)
52 outs, errs = process.communicate(input)
57 returncode = process.poll()
58 if check and returncode:
59 raise subprocess.CalledProcessError(returncode, popenargs, output=outs)
60 return CompletedProcess(popenargs, returncode, stdout=outs, stderr=errs)
62 subprocess.run = sp_run
63 # ^ This monkey patch allows it work on Python 2 or 3 the same way
66 # TODO: implement a command 'waf help' that shows the basic tasks a
67 # developer might want to do: e.g. how to configure a board, compile a
68 # vehicle, compile all the examples, add a new example. Should fit in
69 # less than a terminal screen, ideally commands should be copy
70 # pastable. Add the 'export waf="$PWD/waf"' trick to be copy-pastable
73 # TODO: replace defines with the use of the generated ap_config.h file
74 # this makes recompilation at least when defines change. which might
77 # Default installation prefix for Linux boards
78 default_prefix = '/usr/'
80 # Override Build execute and Configure post_recurse methods for autoconfigure purposes
81 Build.BuildContext.execute = ardupilotwaf.ap_autoconfigure(Build.BuildContext.execute)
82 Configure.ConfigurationContext.post_recurse = ardupilotwaf.ap_configure_post_recurse()
85 def _set_build_context_variant(board):
86 for c in Context.classes:
87 if not issubclass(c, Build.BuildContext):
91 # Remove all submodules and then sync
93 def submodule_force_clean(ctx):
99 # Get all items in the modules folder
100 module_list = os.scandir('modules')
102 # Delete all directories except those in the whitelist
103 for module in module_list:
104 if (module.is_dir()) and (module.name not in whitelist):
105 shutil.rmtree(module)
109 # run Tools/gittools/submodule-sync.sh to sync submodules
111 def submodulesync(ctx):
112 subprocess.call(['Tools/gittools/submodule-sync.sh'])
115 # Generate Task List, so that VS Code extension can keep track
116 # of changes to possible build targets
117 generate_tasklist(ctx, False)
118 env = ConfigSet.ConfigSet()
120 p = os.path.join(Context.out_dir, Build.CACHE_DIR, Build.CACHE_SUFFIX)
122 except EnvironmentError:
125 Configure.autoconfig = 'clobber' if env.AUTOCONFIG else False
127 board = ctx.options.board or env.BOARD
132 # define the variant build commands according to the board
133 _set_build_context_variant(board)
136 opt.load('compiler_cxx compiler_c waf_unit_test python')
137 opt.load('ardupilotwaf')
138 opt.load('build_summary')
140 g = opt.ap_groups['configure']
142 boards_names = boards.get_boards_names()
143 removed_names = boards.get_removed_boards()
144 g.add_option('--board',
147 help='Target board to build, choices are %s.' % ', '.join(boards_names))
149 g.add_option('--debug',
152 help='Configure as debug variant.')
154 g.add_option('--debug-symbols', '-g',
157 help='Add debug symbolds to build.')
159 g.add_option('--vs-launch',
162 help='Generate wscript environment variable to .vscode/setting.json for Visual Studio Code')
164 g.add_option('--disable-watchdog',
167 help='Build with watchdog disabled.')
169 g.add_option('--coverage',
172 help='Configure coverage flags.')
174 g.add_option('--Werror',
177 help='build with -Werror.')
179 g.add_option('--disable-Werror',
182 help='Disable -Werror.')
184 g.add_option('--toolchain',
187 help='Override default toolchain used for the board. Use "native" for using the host toolchain.')
189 g.add_option('--disable-gccdeps',
192 help='Disable the use of GCC dependencies output method and use waf default method.')
194 g.add_option('--enable-asserts',
197 help='enable OS level asserts.')
199 g.add_option('--save-temps',
202 help='save compiler temporary files.')
204 g.add_option('--enable-malloc-guard',
207 help='enable malloc guard regions.')
209 g.add_option('--enable-stats',
212 help='enable OS level thread statistics.')
214 g.add_option('--bootloader',
217 help='Configure for building a bootloader.')
219 g.add_option('--signed-fw',
222 help='Configure for signed firmware support.')
224 g.add_option('--private-key',
227 help='path to private key for signing firmware.')
229 g.add_option('--no-autoconfig',
231 action='store_false',
233 help='''Disable autoconfiguration feature. By default, the build system
234 triggers a reconfiguration whenever it thinks it's necessary - this
235 option disables that.
238 g.add_option('--no-submodule-update',
239 dest='submodule_update',
240 action='store_false',
242 help='''Don't update git submodules. Useful for building with
243 submodules at specific revisions.
246 g.add_option('--enable-header-checks', action='store_true',
248 help="Enable checking of headers")
250 g.add_option('--default-parameters',
252 help='set default parameters to embed in the firmware')
254 g.add_option('--enable-math-check-indexes',
257 help="Enable checking of math indexes")
259 g.add_option('--disable-scripting', action='store_true',
261 help="Disable onboard scripting engine")
263 g.add_option('--enable-scripting', action='store_true',
265 help="Enable onboard scripting engine")
267 g.add_option('--no-gcs', action='store_true',
269 help="Disable GCS code")
271 g.add_option('--scripting-checks', action='store_true',
273 help="Enable runtime scripting sanity checks")
275 g.add_option('--enable-onvif', action='store_true',
277 help="Enables and sets up ONVIF camera control")
279 g.add_option('--scripting-docs', action='store_true',
281 help="enable generation of scripting documentation")
283 g.add_option('--enable-opendroneid', action='store_true',
285 help="Enables OpenDroneID")
287 g.add_option('--enable-check-firmware', action='store_true',
289 help="Enables firmware ID checking on boot")
291 g.add_option('--enable-custom-controller', action='store_true',
293 help="Enables custom controller")
295 g.add_option('--enable-gps-logging', action='store_true',
297 help="Enables GPS logging")
299 g.add_option('--enable-dds', action='store_true',
300 help="Enable the dds client to connect with ROS2/DDS.")
302 g.add_option('--disable-networking', action='store_true',
303 help="Disable the networking API code")
305 g.add_option('--enable-networking-tests', action='store_true',
306 help="Enable the networking test code. Automatically enables networking.")
308 g.add_option('--enable-dronecan-tests', action='store_true',
310 help="Enables DroneCAN tests in sitl")
312 g.add_option('--sitl-littlefs', action='store_true',
314 help="Enable littlefs for filesystem access on SITL (under construction)")
316 g = opt.ap_groups['linux']
318 linux_options = ('--prefix', '--destdir', '--bindir', '--libdir')
319 for k in linux_options:
320 option = opt.parser.get_option(k)
322 opt.parser.remove_option(k)
325 g.add_option('--apstatedir',
328 help='''Where to save data like parameters, log and terrain.
329 This is the --localstatedir + ArduPilots subdirectory [default:
330 board-dependent, usually /var/lib/ardupilot]''')
332 g.add_option('--rsync-dest',
336 help='''Destination for the rsync Waf command. It can be passed during
337 configuration in order to save typing.
340 g.add_option('--enable-benchmarks',
343 help='Enable benchmarks.')
345 g.add_option('--enable-lttng', action='store_true',
347 help="Enable lttng integration")
349 g.add_option('--disable-libiio', action='store_true',
351 help="Don't use libiio even if supported by board and dependencies available")
353 g.add_option('--disable-tests', action='store_true',
355 help="Disable compilation and test execution")
357 g.add_option('--enable-sfml', action='store_true',
359 help="Enable SFML graphics library")
361 g.add_option('--enable-sfml-joystick', action='store_true',
363 help="Enable SFML joystick input library")
365 g.add_option('--enable-sfml-audio', action='store_true',
367 help="Enable SFML audio library")
369 g.add_option('--osd', action='store_true',
371 help="Enable OSD support")
373 g.add_option('--osd-fonts', action='store_true',
375 help="Enable OSD support with fonts")
377 g.add_option('--sitl-osd', action='store_true',
379 help="Enable SITL OSD")
381 g.add_option('--sitl-rgbled', action='store_true',
383 help="Enable SITL RGBLed")
385 g.add_option('--force-32bit', action='store_true',
387 help="Force 32bit build")
389 g.add_option('--build-dates', action='store_true',
391 help="Include build date in binaries. Appears in AUTOPILOT_VERSION.os_sw_version")
393 g.add_option('--sitl-flash-storage',
396 help='Use flash storage emulation.')
398 g.add_option('--ekf-double',
401 help='Configure EKF as double precision.')
403 g.add_option('--ekf-single',
406 help='Configure EKF as single precision.')
408 g.add_option('--static',
411 help='Force a static build')
413 g.add_option('--postype-single',
416 help='force single precision postype_t')
418 g.add_option('--consistent-builds',
421 help='force consistent build outputs for things like __LINE__')
423 g.add_option('--extra-hwdef',
426 help='Extra hwdef.dat file for custom build.')
428 g.add_option('--assert-cc-version',
430 help='fail configure if not using the specified gcc version')
432 g.add_option('--num-aux-imus',
435 help='number of auxiliary IMUs')
437 g.add_option('--board-start-time',
440 help='zero time on boot in microseconds')
442 g.add_option('--enable-iomcu-profiled-support',
445 help='enable iomcu profiled support')
447 g.add_option('--enable-new-checking',
450 help='enables checking of new to ensure NEW_NOTHROW is used')
452 # support enabling any option in build_options.py
453 for opt in build_options.BUILD_OPTIONS:
454 enable_option = "--" + opt.config_option()
455 disable_option = enable_option.replace("--enable", "--disable")
456 enable_description = opt.description
457 if not enable_description.lower().startswith("enable"):
458 enable_description = "Enable " + enable_description
459 disable_description = "Disable " + enable_description[len("Enable "):]
460 g.add_option(enable_option,
463 help=enable_description)
464 g.add_option(disable_option,
467 help=disable_description)
470 def _collect_autoconfig_files(cfg):
471 for m in sys.modules.values():
473 if hasattr(m, '__file__') and m.__file__ is not None:
474 paths.append(m.__file__)
475 elif hasattr(m, '__path__'):
481 if p in cfg.files or not os.path.isfile(p):
484 with open(p, 'rb') as f:
485 cfg.hash = Utils.h_list((cfg.hash, f.read()))
489 # we need to enable debug mode when building for gconv, and force it to sitl
490 if cfg.options.board is None:
491 cfg.options.board = 'sitl'
493 boards_names = boards.get_boards_names()
494 if not cfg.options.board in boards_names:
495 for b in boards_names:
496 if b.upper() == cfg.options.board.upper():
497 cfg.options.board = b
500 cfg.env.BOARD = cfg.options.board
501 cfg.env.DEBUG = cfg.options.debug
502 cfg.env.DEBUG_SYMBOLS = cfg.options.debug_symbols
503 cfg.env.COVERAGE = cfg.options.coverage
504 cfg.env.AUTOCONFIG = cfg.options.autoconfig
506 _set_build_context_variant(cfg.env.BOARD)
507 cfg.setenv(cfg.env.BOARD)
509 if cfg.options.signed_fw:
510 cfg.env.AP_SIGNED_FIRMWARE = True
511 cfg.options.enable_check_firmware = True
513 cfg.env.BOARD = cfg.options.board
514 cfg.env.DEBUG = cfg.options.debug
515 cfg.env.VS_LAUNCH = cfg.options.vs_launch
516 cfg.env.DEBUG_SYMBOLS = cfg.options.debug_symbols
517 cfg.env.COVERAGE = cfg.options.coverage
518 cfg.env.FORCE32BIT = cfg.options.force_32bit
519 cfg.env.ENABLE_ASSERTS = cfg.options.enable_asserts
520 cfg.env.BOOTLOADER = cfg.options.bootloader
521 cfg.env.ENABLE_MALLOC_GUARD = cfg.options.enable_malloc_guard
522 cfg.env.ENABLE_STATS = cfg.options.enable_stats
523 cfg.env.SAVE_TEMPS = cfg.options.save_temps
525 extra_hwdef = cfg.options.extra_hwdef
526 if extra_hwdef is not None and not os.path.exists(extra_hwdef):
527 raise FileNotFoundError(f"extra-hwdef file NOT found: '{cfg.options.extra_hwdef}'")
528 cfg.env.HWDEF_EXTRA = cfg.options.extra_hwdef
529 if cfg.env.HWDEF_EXTRA:
530 cfg.env.HWDEF_EXTRA = os.path.abspath(cfg.env.HWDEF_EXTRA)
532 cfg.env.OPTIONS = cfg.options.__dict__
534 # Allow to differentiate our build from the make build
535 cfg.define('WAF_BUILD', 1)
537 cfg.msg('Autoconfiguration', 'enabled' if cfg.options.autoconfig else 'disabled')
539 if cfg.options.static:
540 cfg.msg('Using static linking', 'yes', color='YELLOW')
541 cfg.env.STATIC_LINKING = True
543 if cfg.options.num_aux_imus > 0:
544 cfg.define('INS_AUX_INSTANCES', cfg.options.num_aux_imus)
546 if cfg.options.board_start_time != 0:
547 cfg.define('AP_BOARD_START_TIME', cfg.options.board_start_time)
548 # also in env for hrt.c
549 cfg.env.AP_BOARD_START_TIME = cfg.options.board_start_time
551 # require python 3.8.x or later
553 cfg.check_python_version(minver=(3,6,9))
555 cfg.load('ap_library')
557 cfg.msg('Setting board to', cfg.options.board)
558 cfg.get_board().configure(cfg)
560 cfg.load('waf_unit_test')
562 cfg.load('dronecangen')
564 cfg.env.SUBMODULE_UPDATE = cfg.options.submodule_update
566 cfg.start_msg('Source is git repository')
567 if cfg.srcnode.find_node('.git'):
571 cfg.env.SUBMODULE_UPDATE = False
573 cfg.msg('Update submodules', 'yes' if cfg.env.SUBMODULE_UPDATE else 'no')
574 cfg.load('git_submodule')
576 if cfg.options.enable_benchmarks:
577 cfg.load('gbenchmark')
580 if cfg.env.BOARD == "sitl":
581 cfg.start_msg('Littlefs')
583 if cfg.options.sitl_littlefs:
584 cfg.end_msg('enabled')
586 cfg.end_msg('disabled', color='YELLOW')
589 cfg.load('static_linking')
590 cfg.load('build_summary')
592 cfg.start_msg('Benchmarks')
593 if cfg.env.HAS_GBENCHMARK:
594 cfg.end_msg('enabled')
596 cfg.end_msg('disabled', color='YELLOW')
598 cfg.start_msg('Unit tests')
599 if cfg.env.HAS_GTEST:
600 cfg.end_msg('enabled')
602 cfg.end_msg('disabled', color='YELLOW')
604 cfg.start_msg('Scripting')
605 if cfg.options.disable_scripting:
606 cfg.end_msg('disabled', color='YELLOW')
607 elif cfg.options.enable_scripting:
608 cfg.end_msg('enabled')
611 cfg.recurse('libraries/AP_Scripting')
613 cfg.recurse('libraries/AP_GPS')
614 cfg.recurse('libraries/AP_HAL_SITL')
615 cfg.recurse('libraries/SITL')
617 cfg.recurse('libraries/AP_Networking')
619 cfg.start_msg('Scripting runtime checks')
620 if cfg.options.scripting_checks:
621 cfg.end_msg('enabled')
623 cfg.end_msg('disabled', color='YELLOW')
625 cfg.start_msg('Debug build')
627 cfg.end_msg('enabled')
629 cfg.end_msg('disabled', color='YELLOW')
632 cfg.start_msg('VS Code launch')
633 if cfg.env.VS_LAUNCH:
634 cfg.end_msg('enabled')
636 cfg.end_msg('disabled', color='YELLOW')
638 cfg.start_msg('Coverage build')
640 cfg.end_msg('enabled')
642 cfg.end_msg('disabled', color='YELLOW')
644 cfg.start_msg('Force 32-bit build')
645 if cfg.env.FORCE32BIT:
646 cfg.end_msg('enabled')
648 cfg.end_msg('disabled', color='YELLOW')
650 cfg.env.append_value('GIT_SUBMODULES', 'mavlink')
652 cfg.env.prepend_value('INCLUDES', [
653 cfg.srcnode.abspath() + '/libraries/',
656 cfg.find_program('rsync', mandatory=False)
657 if cfg.options.rsync_dest:
658 cfg.msg('Setting rsync destination to', cfg.options.rsync_dest)
659 cfg.env.RSYNC_DEST = cfg.options.rsync_dest
661 if cfg.options.enable_header_checks:
662 cfg.msg('Enabling header checks', cfg.options.enable_header_checks)
663 cfg.env.ENABLE_HEADER_CHECKS = True
665 cfg.env.ENABLE_HEADER_CHECKS = False
667 # Always use system extensions
668 cfg.define('_GNU_SOURCE', 1)
670 if cfg.options.Werror:
671 # print(cfg.options.Werror)
672 if cfg.options.disable_Werror:
673 cfg.options.Werror = False
675 cfg.write_config_header(os.path.join(cfg.variant, 'ap_config.h'), guard='_AP_CONFIG_H_')
677 # add in generated flags
678 cfg.env.CXXFLAGS += ['-include', 'ap_config.h']
680 cfg.remove_target_list()
681 _collect_autoconfig_files(cfg)
683 if cfg.env.DEBUG and cfg.env.VS_LAUNCH:
685 vscode_helper.init_launch_json_if_not_exist(cfg)
686 vscode_helper.update_openocd_cfg(cfg)
688 def collect_dirs_to_recurse(bld, globs, **kw):
690 globs = Utils.to_list(globs)
692 if bld.bldnode.is_child_of(bld.srcnode):
693 kw['excl'] = Utils.to_list(kw.get('excl', []))
694 kw['excl'].append(bld.bldnode.path_from(bld.srcnode))
697 for d in bld.srcnode.ant_glob(g + '/wscript', **kw):
698 dirs.append(d.parent.relpath())
701 def list_boards(ctx):
702 print(*boards.get_boards_names())
704 def list_ap_periph_boards(ctx):
705 print(*boards.get_ap_periph_boards())
708 def ap_periph_boards(ctx):
709 return boards.get_ap_periph_boards()
711 vehicles = ['antennatracker', 'blimp', 'copter', 'heli', 'plane', 'rover', 'sub']
713 def generate_tasklist(ctx, do_print=True):
714 boardlist = boards.get_boards_names()
715 ap_periph_targets = boards.get_ap_periph_boards()
717 with open(os.path.join(Context.top_dir, "tasklist.json"), "w") as tlist:
718 for board in boardlist:
720 task['configure'] = board
721 if board in ap_periph_targets:
722 if 'sitl' not in board:
723 # we only support AP_Periph and bootloader builds
724 task['targets'] = ['AP_Periph', 'bootloader']
726 task['targets'] = ['AP_Periph']
727 elif 'iofirmware' in board:
728 task['targets'] = ['iofirmware', 'bootloader']
730 if boards.is_board_based(board, boards.sitl):
731 task['targets'] = vehicles + ['replay']
732 elif boards.is_board_based(board, boards.linux):
733 task['targets'] = vehicles
735 task['targets'] = vehicles + ['bootloader']
736 task['buildOptions'] = '--upload'
738 tlist.write(json.dumps(tasks))
740 print(json.dumps(tasks))
743 env = ConfigSet.ConfigSet()
745 p = os.path.join(Context.out_dir, Build.CACHE_DIR, Build.CACHE_SUFFIX)
748 print('No board currently configured')
751 print('Board configured to: {}'.format(env.BOARD))
753 def _build_cmd_tweaks(bld):
754 if bld.cmd == 'check-all':
755 bld.options.all_tests = True
758 if bld.cmd == 'check':
759 if not bld.env.HAS_GTEST:
760 bld.fatal('check: gtest library is required')
761 bld.options.clear_failed_tests = True
763 def _build_dynamic_sources(bld):
764 if not bld.env.BOOTLOADER:
767 source='modules/mavlink/message_definitions/v1.0/all.xml',
768 output_dir='libraries/GCS_MAVLink/include/mavlink/v2.0/',
770 # this below is not ideal, mavgen tool should set this, but that's not
773 bld.bldnode.make_node('libraries').abspath(),
774 bld.bldnode.make_node('libraries/GCS_MAVLink').abspath(),
778 if (bld.get_board().with_can or bld.env.HAL_NUM_CAN_IFACES) and not bld.env.AP_PERIPH:
780 features='dronecangen',
781 source=bld.srcnode.ant_glob('modules/DroneCAN/DSDL/[a-z]* libraries/AP_DroneCAN/dsdl/[a-z]*', dir=True, src=False),
782 output_dir='modules/DroneCAN/libcanard/dsdlc_generated/',
785 bld.bldnode.make_node('modules/DroneCAN/libcanard/dsdlc_generated/include').abspath(),
786 bld.srcnode.find_dir('modules/DroneCAN/libcanard/').abspath(),
787 bld.srcnode.find_dir('libraries/AP_DroneCAN/canard/').abspath(),
790 elif bld.env.AP_PERIPH:
792 features='dronecangen',
793 source=bld.srcnode.ant_glob('modules/DroneCAN/DSDL/* libraries/AP_DroneCAN/dsdl/*', dir=True, src=False),
794 output_dir='modules/DroneCAN/libcanard/dsdlc_generated/',
797 bld.bldnode.make_node('modules/DroneCAN/libcanard/dsdlc_generated/include').abspath(),
798 bld.srcnode.find_dir('modules/DroneCAN/libcanard/').abspath(),
802 if bld.env.ENABLE_DDS:
803 bld.recurse("libraries/AP_DDS")
805 def write_version_header(tsk):
806 bld = tsk.generator.bld
807 return bld.write_version_header(tsk.outputs[0].abspath())
811 target='ap_version.h',
812 vars=['AP_VERSION_ITEMS'],
813 rule=write_version_header,
816 bld.env.prepend_value('INCLUDES', [
817 bld.bldnode.abspath(),
820 def _build_common_taskgens(bld):
821 # NOTE: Static library with vehicle set to UNKNOWN, shared by all
822 # the tools and examples. This is the first step until the
823 # dependency on the vehicles is reduced. Later we may consider
824 # split into smaller pieces with well defined boundaries.
827 ap_vehicle='UNKNOWN',
828 ap_libraries=bld.ap_get_all_libraries(),
831 if bld.env.HAS_GTEST:
832 bld.libgtest(cxxflags=['-include', 'ap_config.h'])
834 if bld.env.HAS_GBENCHMARK:
837 def _build_recursion(bld):
838 common_dirs_patterns = [
839 # TODO: Currently each vehicle also generate its own copy of the
840 # libraries. Fix this, or at least reduce the amount of
841 # vehicle-dependent libraries.
844 'libraries/*/examples/*',
846 'libraries/*/utility/tests',
847 'libraries/*/benchmarks',
852 'libraries/AP_HAL_*',
855 hal_dirs_patterns = [
856 'libraries/%s/tests',
857 'libraries/%s/*/tests',
858 'libraries/%s/*/benchmarks',
859 'libraries/%s/examples/*',
862 dirs_to_recurse = collect_dirs_to_recurse(
864 common_dirs_patterns,
865 excl=common_dirs_excl,
867 if bld.env.IOMCU_FW is not None:
869 dirs_to_recurse.append('libraries/AP_IOMCU/iofirmware')
871 if bld.env.PERIPH_FW is not None:
872 if bld.env.PERIPH_FW:
873 dirs_to_recurse.append('Tools/AP_Periph')
875 dirs_to_recurse.append('libraries/AP_Scripting')
877 if bld.env.ENABLE_ONVIF:
878 dirs_to_recurse.append('libraries/AP_ONVIF')
880 for p in hal_dirs_patterns:
881 dirs_to_recurse += collect_dirs_to_recurse(
883 [p % l for l in bld.env.AP_LIBRARIES],
886 # NOTE: we need to sort to ensure the repeated sources get the
887 # same index, and random ordering of the filesystem doesn't cause
889 dirs_to_recurse.sort()
891 for d in dirs_to_recurse:
894 def _build_post_funs(bld):
895 if bld.cmd == 'check':
896 bld.add_post_fun(ardupilotwaf.test_summary)
898 bld.build_summary_post_fun()
900 if bld.env.SUBMODULE_UPDATE:
901 bld.git_submodule_post_fun()
903 def _load_pre_build(bld):
904 '''allow for a pre_build() function in build modules'''
905 if bld.cmd == 'clean':
907 brd = bld.get_board()
908 if getattr(brd, 'pre_build', None):
912 config_hash = Utils.h_file(bld.bldnode.make_node('ap_config.h').abspath())
913 bld.env.CCDEPS = config_hash
914 bld.env.CXXDEPS = config_hash
916 bld.post_mode = Build.POST_LAZY
918 bld.load('ardupilotwaf')
920 bld.env.AP_LIBRARIES_OBJECTS_KW.update(
922 cxxflags=['-include', 'ap_config.h'],
927 if bld.get_board().with_can:
928 bld.env.AP_LIBRARIES_OBJECTS_KW['use'] += ['dronecan']
930 if bld.get_board().with_littlefs:
931 bld.env.AP_LIBRARIES_OBJECTS_KW['use'] += ['littlefs']
934 _build_cmd_tweaks(bld)
936 if bld.env.SUBMODULE_UPDATE:
937 bld.add_group('git_submodules')
938 for name in bld.env.GIT_SUBMODULES:
939 bld.git_submodule(name)
941 bld.add_group('dynamic_sources')
942 _build_dynamic_sources(bld)
944 bld.add_group('build')
945 bld.get_board().build(bld)
946 _build_common_taskgens(bld)
948 _build_recursion(bld)
950 _build_post_funs(bld)
952 if bld.env.DEBUG and bld.env.VS_LAUNCH:
954 vscode_helper.update_settings(bld)
956 ardupilotwaf.build_command('check',
957 program_group_list='all',
958 doc='builds all programs and run tests',
960 ardupilotwaf.build_command('check-all',
961 program_group_list='all',
962 doc='shortcut for `waf check --alltests`',
965 for name in (vehicles + ['bootloader','iofirmware','AP_Periph','replay']):
966 ardupilotwaf.build_command(name,
967 program_group_list=name,
968 doc='builds %s programs' % name,
971 for program_group in ('all', 'bin', 'tool', 'examples', 'tests', 'benchmarks'):
972 ardupilotwaf.build_command(program_group,
973 program_group_list=program_group,
974 doc='builds all programs of %s group' % program_group,
977 class LocalInstallContext(Build.InstallContext):
978 """runs install using BLD/install as destdir, where BLD is the build variant directory"""
981 def __init__(self, **kw):
982 super(LocalInstallContext, self).__init__(**kw)
983 self.local_destdir = os.path.join(self.variant_dir, 'install')
986 old_destdir = self.options.destdir
987 self.options.destdir = self.local_destdir
988 r = super(LocalInstallContext, self).execute()
989 self.options.destdir = old_destdir
992 class RsyncContext(LocalInstallContext):
993 """runs localinstall and then rsyncs BLD/install with the target system"""
996 def __init__(self, **kw):
997 super(RsyncContext, self).__init__(**kw)
998 self.add_pre_fun(RsyncContext.create_rsync_taskgen)
1000 def create_rsync_taskgen(self):
1001 if 'RSYNC' not in self.env:
1002 self.fatal('rsync program seems not to be installed, can\'t continue')
1008 rule='${RSYNC} -a ${RSYNC_SRC}/ ${RSYNC_DEST}',
1012 tg.env.RSYNC_SRC = self.local_destdir
1013 if self.options.rsync_dest:
1014 self.env.RSYNC_DEST = self.options.rsync_dest
1016 if 'RSYNC_DEST' not in tg.env:
1017 self.fatal('Destination for rsync not defined. Either pass --rsync-dest here or during configuration.')