# 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: log.wrn('--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 -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)