From ff77000d939c8c3dab615fb87b5797b8c69a95b6 Mon Sep 17 00:00:00 2001 From: Francisco Ferreira Date: Sun, 2 Sep 2018 01:30:36 +0100 Subject: [PATCH] waf: support changing board to build without re-configure This allows to use the board option when building as long as it has been configured before As we don't want to force configuration of all boards each single time, auto-configuration support now has to be done per-board --- Tools/ardupilotwaf/ardupilotwaf.py | 83 +++++++++++++++++++++++++++++- wscript | 37 ++++++++----- 2 files changed, 105 insertions(+), 15 deletions(-) diff --git a/Tools/ardupilotwaf/ardupilotwaf.py b/Tools/ardupilotwaf/ardupilotwaf.py index 5ac9aaa4be..489130474e 100644 --- a/Tools/ardupilotwaf/ardupilotwaf.py +++ b/Tools/ardupilotwaf/ardupilotwaf.py @@ -2,8 +2,9 @@ # encoding: utf-8 from __future__ import print_function -from waflib import Build, Logs, Options, Utils +from waflib import Build, ConfigSet, Configure, Context, Errors, Logs, Options, Utils from waflib.Configure import conf +from waflib.Scripting import run_command from waflib.TaskGen import before_method, feature import os.path, os from collections import OrderedDict @@ -92,6 +93,86 @@ IGNORED_AP_LIBRARIES = [ 'AP_Scripting', # this gets explicitly included when it is needed and should otherwise never be globbed in ] + +def ap_autoconfigure(execute_method): + """ + Decorator that enables context commands to run *configure* as needed. + """ + def execute(self): + """ + Wraps :py:func:`waflib.Context.Context.execute` on the context class + """ + if not Configure.autoconfig: + return execute_method(self) + + # Disable autoconfig so waf's version doesn't run (and don't end up on loop of bad configure) + Configure.autoconfig = False + + if self.variant == '': + raise Errors.WafError('The project is badly configured: run "waf configure" again!') + + env = ConfigSet.ConfigSet() + do_config = False + + try: + p = os.path.join(Context.out_dir, Build.CACHE_DIR, self.variant + Build.CACHE_SUFFIX) + env.load(p) + except EnvironmentError: + raise Errors.WafError('The project is not configured for board {0}: run "waf configure --board {0} [...]" first!'.format(self.variant)) + + lock_env = ConfigSet.ConfigSet() + + try: + lock_env.load(os.path.join(Context.top_dir, Options.lockfile)) + except EnvironmentError: + Logs.warn('Configuring the project') + do_config = True + else: + if lock_env.run_dir != Context.run_dir: + do_config = True + else: + h = 0 + + for f in env.CONFIGURE_FILES: + try: + h = Utils.h_list((h, Utils.readf(f, 'rb'))) + except EnvironmentError: + do_config = True + break + else: + do_config = h != env.CONFIGURE_HASH + + if do_config: + cmd = lock_env.config_cmd or 'configure' + tmp = Options.options.__dict__ + + if env.OPTIONS and sorted(env.OPTIONS.keys()) == sorted(tmp.keys()): + Options.options.__dict__ = env.OPTIONS + else: + raise Errors.WafError('The project configure options have changed: run "waf configure" again!') + + try: + run_command(cmd) + finally: + Options.options.__dict__ = tmp + + run_command(self.cmd) + else: + return execute_method(self) + + return execute + +def ap_configure_post_recurse(): + post_recurse_orig = Configure.ConfigurationContext.post_recurse + + def post_recurse(self, node): + post_recurse_orig(self, node) + + self.all_envs[self.variant].CONFIGURE_FILES = self.files + self.all_envs[self.variant].CONFIGURE_HASH = self.hash + + return post_recurse + @conf def ap_get_all_libraries(bld): if bld.env.BOOTLOADER: diff --git a/wscript b/wscript index d6dd42fb86..468f34e29c 100644 --- a/wscript +++ b/wscript @@ -26,27 +26,34 @@ from waflib import Build, ConfigSet, Configure, Context, Utils # Default installation prefix for Linux boards default_prefix = '/usr/' -def _set_build_context_variant(variant): +# Override Build execute and Configure post_recurse methods for autoconfigure purposes +Build.BuildContext.execute = ardupilotwaf.ap_autoconfigure(Build.BuildContext.execute) +Configure.ConfigurationContext.post_recurse = ardupilotwaf.ap_configure_post_recurse() + + +def _set_build_context_variant(board): for c in Context.classes: if not issubclass(c, Build.BuildContext): continue - c.variant = variant + c.variant = board def init(ctx): env = ConfigSet.ConfigSet() try: p = os.path.join(Context.out_dir, Build.CACHE_DIR, Build.CACHE_SUFFIX) env.load(p) - except: + except EnvironmentError: return Configure.autoconfig = 'clobber' if env.AUTOCONFIG else False - if 'VARIANT' not in env: + board = ctx.options.board or env.BOARD + + if not board: return # define the variant build commands according to the board - _set_build_context_variant(env.VARIANT) + _set_build_context_variant(board) def options(opt): opt.load('compiler_cxx compiler_c waf_unit_test python') @@ -59,8 +66,8 @@ def options(opt): g.add_option('--board', action='store', choices=boards_names, - default='sitl', - help='Target board to build, choices are %s.' % boards_names) + default=None, + help='Target board to build, choices are %s.' % ', '.join(boards_names)) g.add_option('--debug', action='store_true', @@ -81,7 +88,7 @@ def options(opt): action='store_true', default=False, help='use old NuttX IO firmware for IOMCU') - + g.add_option('--bootloader', action='store_true', default=False, @@ -190,14 +197,14 @@ def _collect_autoconfig_files(cfg): cfg.files.append(p) def configure(cfg): + if cfg.options.board is None: + cfg.options.board = 'sitl' + cfg.env.BOARD = cfg.options.board - cfg.env.DEBUG = cfg.options.debug cfg.env.AUTOCONFIG = cfg.options.autoconfig - cfg.env.VARIANT = cfg.env.BOARD - - _set_build_context_variant(cfg.env.VARIANT) - cfg.setenv(cfg.env.VARIANT) + _set_build_context_variant(cfg.env.BOARD) + cfg.setenv(cfg.env.BOARD) cfg.env.BOARD = cfg.options.board cfg.env.DEBUG = cfg.options.debug @@ -205,6 +212,8 @@ def configure(cfg): cfg.env.BOOTLOADER = cfg.options.bootloader cfg.env.USE_NUTTX_IOFW = cfg.options.use_nuttx_iofw + cfg.env.OPTIONS = cfg.options.__dict__ + # Allow to differentiate our build from the make build cfg.define('WAF_BUILD', 1) @@ -315,7 +324,7 @@ def board(ctx): print('No board currently configured') return - print('Board configured to: {}'.format(env.VARIANT)) + print('Board configured to: {}'.format(env.BOARD)) def _build_cmd_tweaks(bld): if bld.cmd == 'check-all':