scripts: west: introduce common runner configuration
Continue better integration of the runner subpackage into west by moving the common runner configuration options into the command core. This allows commands like "west flash -h" to display help for common overrides like --kernel-hex. Adjustments needed to make this happen are: - Change the build system to separate common configuration values from runner-specific options and arguments - Prepare the runner core by defining a new RunnerConfig class that represents the common configuration, and accepting that from a new create() method, which replaces create_from_args(). - Convert all concrete runner classes to use the new style of argument parsing and initialization. - Group the command options appropriately for help output readability There's still a bit of tool-specific stuff in the common configuration (gdb and openocd configuration in particular); a more generic way to deal with that will be necessary to better support things like non-GDB debuggers, but that's out of scope of this patch. All the runner-specific options are still in the runner packge, which currently prevents them from being included in "west flash -h" etc. Fixing that is also out of scope of this patch. This has the ancillary benefit of getting rid of the legacy 'debug' argument to ZephyrBinaryRunner, which is no longer appropriate since verbose debug logging is handled by log.py in west. Signed-off-by: Marti Bolivar <marti@opensourcefoundries.com>
This commit is contained in:
parent
c9dfbfaf02
commit
5317f76dec
15 changed files with 314 additions and 224 deletions
|
@ -13,6 +13,7 @@ from textwrap import dedent
|
|||
from .. import cmake
|
||||
from .. import log
|
||||
from ..runner import get_runner_cls
|
||||
from ..runner.core import RunnerConfig
|
||||
from . import CommandContextError
|
||||
|
||||
|
||||
|
@ -22,24 +23,56 @@ def add_parser_common(parser_adder, command):
|
|||
formatter_class=argparse.RawDescriptionHelpFormatter,
|
||||
description=command.description)
|
||||
|
||||
parser.add_argument('-d', '--build-dir',
|
||||
help='''Build directory to obtain runner information
|
||||
from; default is the current working directory.''')
|
||||
parser.add_argument('-c', '--cmake-cache', default=cmake.DEFAULT_CACHE,
|
||||
help='''Path to CMake cache file containing runner
|
||||
configuration (this is generated by the Zephyr
|
||||
build system when compiling binaries);
|
||||
default: {}.
|
||||
group = parser.add_argument_group(title='General Options')
|
||||
group.add_argument('-d', '--build-dir',
|
||||
help='''Build directory to obtain runner information
|
||||
from; default is the current working directory.''')
|
||||
group.add_argument('-c', '--cmake-cache', default=cmake.DEFAULT_CACHE,
|
||||
help='''Path to CMake cache file containing runner
|
||||
configuration (this is generated by the Zephyr
|
||||
build system when compiling binaries);
|
||||
default: {}.
|
||||
|
||||
If this is a relative path, it is assumed relative to
|
||||
the build directory. An absolute path can also be
|
||||
given instead.'''.format(cmake.DEFAULT_CACHE))
|
||||
parser.add_argument('-r', '--runner',
|
||||
help='''If given, overrides any cached {}
|
||||
runner.'''.format(command.name))
|
||||
parser.add_argument('--skip-rebuild', action='store_true',
|
||||
help='''If given, do not rebuild the application
|
||||
before running {} commands.'''.format(command.name))
|
||||
If this is a relative path, it is assumed relative to
|
||||
the build directory. An absolute path can also be
|
||||
given instead.'''.format(cmake.DEFAULT_CACHE))
|
||||
group.add_argument('-r', '--runner',
|
||||
help='''If given, overrides any cached {}
|
||||
runner.'''.format(command.name))
|
||||
group.add_argument('--skip-rebuild', action='store_true',
|
||||
help='''If given, do not rebuild the application
|
||||
before running {} commands.'''.format(command.name))
|
||||
|
||||
group = parser.add_argument_group(
|
||||
title='Configuration overrides',
|
||||
description=dedent('''\
|
||||
These values usually come from the Zephyr build system itself
|
||||
as stored in the CMake cache; providing these options
|
||||
overrides those settings.'''))
|
||||
|
||||
# Important:
|
||||
#
|
||||
# 1. The destination variables of these options must match
|
||||
# the RunnerConfig slots.
|
||||
# 2. The default values for all of these must be None.
|
||||
#
|
||||
# This is how we detect if the user provided them or not when
|
||||
# overriding values from the cached configuration.
|
||||
group.add_argument('--board-dir',
|
||||
help='Zephyr board directory')
|
||||
group.add_argument('--kernel-elf',
|
||||
help='Path to kernel binary in .elf format')
|
||||
group.add_argument('--kernel-hex',
|
||||
help='Path to kernel binary in .hex format')
|
||||
group.add_argument('--kernel-bin',
|
||||
help='Path to kernel binary in .bin format')
|
||||
group.add_argument('--gdb',
|
||||
help='Path to GDB, if applicable')
|
||||
group.add_argument('--openocd',
|
||||
help='Path to OpenOCD, if applicable')
|
||||
group.add_argument(
|
||||
'--openocd-search',
|
||||
help='Path to add to OpenOCD search path, if applicable')
|
||||
|
||||
return parser
|
||||
|
||||
|
@ -57,6 +90,30 @@ def desc_common(command_name):
|
|||
'''.format(**{'command': command_name}))
|
||||
|
||||
|
||||
def cached_runner_config(cache):
|
||||
'''Parse the RunnerConfig from a CMake Cache.'''
|
||||
board_dir = cache['ZEPHYR_RUNNER_CONFIG_BOARD_DIR']
|
||||
kernel_elf = cache['ZEPHYR_RUNNER_CONFIG_KERNEL_ELF']
|
||||
kernel_hex = cache['ZEPHYR_RUNNER_CONFIG_KERNEL_HEX']
|
||||
kernel_bin = cache['ZEPHYR_RUNNER_CONFIG_KERNEL_BIN']
|
||||
gdb = cache.get('ZEPHYR_RUNNER_CONFIG_GDB')
|
||||
openocd = cache.get('ZEPHYR_RUNNER_CONFIG_OPENOCD')
|
||||
openocd_search = cache.get('ZEPHYR_RUNNER_CONFIG_OPENOCD_SEARCH')
|
||||
|
||||
return RunnerConfig(board_dir, kernel_elf, kernel_hex, kernel_bin,
|
||||
gdb=gdb, openocd=openocd,
|
||||
openocd_search=openocd_search)
|
||||
|
||||
|
||||
def _override_config_from_namespace(cfg, namespace):
|
||||
'''Override a RunnerConfig's contents with command-line values.'''
|
||||
for var in cfg.__slots__:
|
||||
if var in namespace:
|
||||
val = getattr(namespace, var)
|
||||
if val is not None:
|
||||
setattr(cfg, var, val)
|
||||
|
||||
|
||||
def do_run_common(command, args, runner_args, cached_runner_var):
|
||||
command_name = command.name
|
||||
build_dir = args.build_dir or getcwd()
|
||||
|
@ -79,6 +136,12 @@ def do_run_common(command, args, runner_args, cached_runner_var):
|
|||
# places.
|
||||
chdir(build_dir)
|
||||
|
||||
# Runner creation, phase 1.
|
||||
#
|
||||
# Get the default runner name from the cache, allowing a command
|
||||
# line override. Get the ZephyrBinaryRunner class by name, and
|
||||
# make sure it supports the command.
|
||||
|
||||
# TODO: build this by joining with build_dir once the above chdir
|
||||
# goes away.
|
||||
cache_file = args.cmake_cache
|
||||
|
@ -104,22 +167,38 @@ def do_run_common(command, args, runner_args, cached_runner_var):
|
|||
log.die('Runner {} does not support command {}'.format(
|
||||
runner, command_name))
|
||||
|
||||
cached_common_args = cache.get_list('ZEPHYR_RUNNER_ARGS_COMMON')
|
||||
# Runner creation, phase 2.
|
||||
#
|
||||
# At this point, the common options above are already parsed in
|
||||
# 'args', and unrecognized arguments are in 'runner_args'.
|
||||
#
|
||||
# - Pull the RunnerConfig out of the cache
|
||||
# - Override cached values with applicable command-line options
|
||||
|
||||
cfg = cached_runner_config(cache)
|
||||
_override_config_from_namespace(cfg, args)
|
||||
|
||||
# Runner creation, phase 3.
|
||||
#
|
||||
# - Pull out cached runner arguments, and append command-line
|
||||
# values (which should override the cache)
|
||||
# - Construct a runner-specific argument parser to handle cached
|
||||
# values plus overrides given in runner_args
|
||||
# - Parse arguments and create runner instance from final
|
||||
# RunnerConfig and parsed arguments.
|
||||
|
||||
cached_runner_args = cache.get_list(
|
||||
'ZEPHYR_RUNNER_ARGS_{}'.format(cmake.make_c_identifier(runner)))
|
||||
# Construct the final command line arguments, create a
|
||||
# runner-specific parser to handle them, and run the command.
|
||||
assert isinstance(runner_args, list), runner_args
|
||||
final_runner_args = cached_common_args + cached_runner_args + runner_args
|
||||
|
||||
# Having the runners themselves be the place where their argument
|
||||
# parsing is handled is hackish; it's an artifact of the time
|
||||
# before the runner package was part of west.
|
||||
#
|
||||
# TODO: refactor runner argument parsing higher up into west.
|
||||
# If the user passed -- to force the parent argument parser to stop
|
||||
# parsing, it will show up here, and needs to be filtered out.
|
||||
runner_args = [arg for arg in runner_args if arg != '--']
|
||||
final_runner_args = cached_runner_args + runner_args
|
||||
parser = argparse.ArgumentParser(prog=runner)
|
||||
runner_cls.add_parser(parser)
|
||||
parsed_args = parser.parse_args(args=final_runner_args)
|
||||
parsed_args.verbose = args.verbose
|
||||
runner = runner_cls.create_from_args(parsed_args)
|
||||
parsed_args, unknown = parser.parse_known_args(args=final_runner_args)
|
||||
if unknown:
|
||||
raise CommandContextError('Runner', runner,
|
||||
'received unknown arguments', unknown)
|
||||
runner = runner_cls.create(cfg, parsed_args)
|
||||
runner.run(command_name)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue