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>
112 lines
3.4 KiB
Python
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)
|