Boot Linux faster!

Check our new training course

Boot Linux faster!

Check our new training course
and Creative Commons CC-BY-SA
lecture and lab materials

Bootlin logo

Elixir Cross Referencer

#! /usr/bin/env python3

# Copyright (c) 2017 Linaro Limited.
# Copyright (c) 2017 Open Source Foundries Limited.
#
# SPDX-License-Identifier: Apache-2.0

"""Zephyr flash/debug script

This helper script is the build system's entry point to Zephyr's
"runner" Python package. This package provides ZephyrBinaryRunner,
which is a standard interface for flashing and debugging boards
supported by Zephyr, as well as backend-specific scripts for tools
such as OpenOCD, pyOCD, etc.
"""

import argparse
import functools
import sys
import os

from runner.core import ZephyrBinaryRunner


def print_runners_handler(args):
    for cls in ZephyrBinaryRunner.get_runners():
        print(cls.name())


def runner_handler(cls, args):
    runner = cls.create_from_args(args)
    # This relies on ZephyrBinaryRunner.add_parser() having command as
    # its single positional argument; see its docstring for details.
    runner.run(args.command)


def main():
    # Argument handling is split into a two-level structure, with
    # common options to the script first, then a sub-command (i.e.  a
    # runner name), then options and arguments for that sub-command
    # (like 'flash --some-option=value').
    #
    # For top-level help (including a list of runners), run:
    #
    # $ZEPHYR_BASE/.../SCRIPT.py -h
    #
    # For help on a particular RUNNER (like 'pyocd'), run:
    #
    # $ZEPHYR_BASE/.../SCRIPT.py RUNNER -h
    #
    # For verbose output, use:
    #
    # $ZEPHYR_BASE/.../SCRIPT.py [-v|--verbose] RUNNER [--runner-options]
    #
    # Note that --verbose comes *before* RUNNER, not after!
    #
    # Other commands (for now just the "runners" command, which prints
    # the available runners) are handled the same way:
    #
    # $ZEPHYR_BASE/.../SCRIPT.py runners
    top_parser = argparse.ArgumentParser()
    top_parser.add_argument('-v', '--verbose',
                            default=False, action='store_true',
                            help='If set, enable verbose output.')
    sub_parsers = top_parser.add_subparsers(dest='top_command')

    # Handlers for each subcommand.
    handlers = {}

    # The 'runners' command just prints the runners. It takes no arguments.
    sub_parsers.add_parser('runners')
    handlers['runners'] = print_runners_handler

    # Add a sub-command for each runner. (It's a bit hackish for runners
    # to know about argparse, but it's good enough for now.)
    for cls in ZephyrBinaryRunner.get_runners():
        if cls.name() in handlers:
            print('Runner {} name is already a top-level command'.format(
                      cls.name()),
                  file=sys.sterr)
            sys.exit(1)
        sub_parser = sub_parsers.add_parser(cls.name())
        cls.add_parser(sub_parser)
        handlers[cls.name()] = functools.partial(runner_handler, cls)

    args = top_parser.parse_args()
    if "VERBOSE" in os.environ:
        args.verbose = 1

    if args.top_command is None:
        choices = ', '.join(handlers.keys())
        print('Missing command or runner; choices: {}'.format(choices),
              file=sys.stderr)
        sys.exit(1)
    try:
        handlers[args.top_command](args)
    except Exception as e:
        if args.verbose:
            raise
        else:
            print('Error: {}'.format(e), file=sys.stderr)
            print(('(Re-run as "{} --verbose {} ..." '
                   'or set CMAKE_VERBOSE_MAKEFILE for a stack trace.)').format(
                       sys.argv[0], args.top_command),
                  file=sys.stderr)
            sys.exit(1)


if __name__ == '__main__':
    main()