zephyr/scripts/meta/west/main.py
Marti Bolivar b611e5b1ea scripts: west: add flash, debug, debugserver commands
When run without any arguments, the commands work the same way that
their CMake equivalents do. For example, if using the Ninja CMake
generator, these are equivalent:

    west flash        <----> ninja flash
    west debug        <----> ninja debug
    west debugserver  <----> ninja debugserver

Like CMake's build tool mode, you can also run them from any directory
in the system by passing the path to the build directory using
--build-dir (-d):

    west flash -d build/my-board

The commands will run the CMake-generated build system, so they keep
dependencies up to date and users don't have to manually compile
binaries between running CMake and using this tool.

The commands also support important use cases that CMake can't:

1) Any arguments not handled by 'west flash' et al. are passed to the
   underlying runner. For example, if the runner supports --gdb-port,
   the default can be overridden like so:

   west debugserver --gdb-port=1234

   Command processing by the 'west' command can also be halted using
   '--'; anything after that point (even if it's an option recognized
   by the west command) will be passed to the runner. Example:

   west debug -- --this-option-goes-to-the-debug-runner=foo

2) Any runner supported by the board can be selected at runtime using
   the -r (--runner) option. For example, if the board's flash runner
   defaults to nrfjprog but jlink is supported as well, it can be
   selected with:

   west flash -r jlink

3) The runner configuration can be persisted elsewhere, edited
   offline, and selected at runtime, using --cmake-cache (-c):

   west flash -c /home/me/some/other/CMakeCache.txt

Signed-off-by: Marti Bolivar <marti@opensourcefoundries.com>
2018-05-19 07:01:39 +03:00

112 lines
3.4 KiB
Python

# Copyright 2018 Open Source Foundries Limited.
#
# SPDX-License-Identifier: Apache-2.0
'''Zephyr RTOS meta-tool (west) main module
'''
import argparse
from functools import partial
import os
import sys
from subprocess import CalledProcessError
from . import log
from .cmd import CommandContextError
from .cmd.flash import Flash
from .cmd.debug import Debug, DebugServer
from .util import quote_sh_list
COMMANDS = (Flash(), Debug(), DebugServer())
'''Supported top-level commands.'''
class InvalidWestContext(RuntimeError):
pass
def command_handler(command, known_args, unknown_args):
command.run(known_args, unknown_args)
def validate_context(args, unknown):
'''Validate the run-time context expected by west.'''
if args.zephyr_base:
os.environ['ZEPHYR_BASE'] = args.zephyr_base
else:
if 'ZEPHYR_BASE' not in os.environ:
raise InvalidWestContext(
'--zephyr-base missing and no ZEPHYR_BASE '
'in the environment')
else:
args.zephyr_base = os.environ['ZEPHYR_BASE']
def parse_args(argv):
west_parser = argparse.ArgumentParser(
prog='west', description='The Zephyr RTOS meta-tool.',
epilog='Run "west <command> -h" for help on each command.')
west_parser.add_argument('-z', '--zephyr-base', default=None,
help='''Path to the Zephyr base directory. If not
given, ZEPHYR_BASE must be defined in the
environment, and will be used instead.''')
west_parser.add_argument('-v', '--verbose', default=0, action='count',
help='''Display verbose output. May be given
multiple times to increase verbosity.''')
subparser_gen = west_parser.add_subparsers(title='commands',
dest='command')
for command in COMMANDS:
parser = command.add_parser(subparser_gen)
parser.set_defaults(handler=partial(command_handler, command))
args, unknown = west_parser.parse_known_args(args=argv)
# Set up logging verbosity before doing anything else, so
# e.g. verbose messages related to argument handling errors
# work properly.
log.set_verbosity(args.verbose)
try:
validate_context(args, unknown)
except InvalidWestContext as iwc:
log.err(*iwc.args, fatal=True)
west_parser.print_usage(file=sys.stderr)
sys.exit(1)
if 'handler' not in args:
log.err('you must specify a command', fatal=True)
west_parser.print_usage(file=sys.stderr)
sys.exit(1)
return args, unknown
def main(argv):
args, unknown = parse_args(argv)
for_stack_trace = 'run as "west -v ... {} ..." for a stack trace'.format(
args.command)
try:
args.handler(args, unknown)
except KeyboardInterrupt:
sys.exit(0)
except CalledProcessError as cpe:
log.err('command exited with status {}: {}'.format(
cpe.args[0], quote_sh_list(cpe.args[1])))
if args.verbose:
raise
else:
log.inf(for_stack_trace)
except CommandContextError as cce:
log.die('command', args.command, 'cannot be run in this context:',
*cce.args)
except Exception as exc:
log.err(*exc.args, fatal=True)
if args.verbose:
raise
else:
log.inf(for_stack_trace)