scripts: create meta-tool package, "west"
We have agreed to develop a meta-tool named "west", which will be a
swiss-army knife of Zephyr development. It will support use cases like
building, flashing and debugging; bootloader integration; emulator
support; and integration with multiple git repositories.
The basic usage for the tool is similar to git(1):
west [common opts] <command-name> [command opts] [<command args>]
There are common options, such as verbosity control, followed by a
mandatory sub-command. The sub-command then takes its own options and
arguments.
This patch adds the basic framework for this tool, as follows:
- a Python 3 package named 'west', in scripts/meta. There is no PyPI
integration for now; the tool will be improving quickly, so we need
to keep users up to date by having it in tree.
- an main entry point, main.py, and a package-level shim, __main__.py
- a cmd subpackage, which defines the abstract base class for commands
- logging (log.py)
- catch-all utilities (util.py)
- Windows and Unix launchers so users can type "west" to run the tool
after sourcing the appropriate zephyr-env script for their
environment.
Subsequent patches will start to add individual commands.
Signed-off-by: Marti Bolivar <marti@opensourcefoundries.com>
2018-05-09 23:08:38 +08:00
|
|
|
# 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
|
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-10 06:16:30 +08:00
|
|
|
from .cmd.flash import Flash
|
|
|
|
from .cmd.debug import Debug, DebugServer
|
scripts: create meta-tool package, "west"
We have agreed to develop a meta-tool named "west", which will be a
swiss-army knife of Zephyr development. It will support use cases like
building, flashing and debugging; bootloader integration; emulator
support; and integration with multiple git repositories.
The basic usage for the tool is similar to git(1):
west [common opts] <command-name> [command opts] [<command args>]
There are common options, such as verbosity control, followed by a
mandatory sub-command. The sub-command then takes its own options and
arguments.
This patch adds the basic framework for this tool, as follows:
- a Python 3 package named 'west', in scripts/meta. There is no PyPI
integration for now; the tool will be improving quickly, so we need
to keep users up to date by having it in tree.
- an main entry point, main.py, and a package-level shim, __main__.py
- a cmd subpackage, which defines the abstract base class for commands
- logging (log.py)
- catch-all utilities (util.py)
- Windows and Unix launchers so users can type "west" to run the tool
after sourcing the appropriate zephyr-env script for their
environment.
Subsequent patches will start to add individual commands.
Signed-off-by: Marti Bolivar <marti@opensourcefoundries.com>
2018-05-09 23:08:38 +08:00
|
|
|
from .util import quote_sh_list
|
|
|
|
|
|
|
|
|
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-10 06:16:30 +08:00
|
|
|
COMMANDS = (Flash(), Debug(), DebugServer())
|
scripts: create meta-tool package, "west"
We have agreed to develop a meta-tool named "west", which will be a
swiss-army knife of Zephyr development. It will support use cases like
building, flashing and debugging; bootloader integration; emulator
support; and integration with multiple git repositories.
The basic usage for the tool is similar to git(1):
west [common opts] <command-name> [command opts] [<command args>]
There are common options, such as verbosity control, followed by a
mandatory sub-command. The sub-command then takes its own options and
arguments.
This patch adds the basic framework for this tool, as follows:
- a Python 3 package named 'west', in scripts/meta. There is no PyPI
integration for now; the tool will be improving quickly, so we need
to keep users up to date by having it in tree.
- an main entry point, main.py, and a package-level shim, __main__.py
- a cmd subpackage, which defines the abstract base class for commands
- logging (log.py)
- catch-all utilities (util.py)
- Windows and Unix launchers so users can type "west" to run the tool
after sourcing the appropriate zephyr-env script for their
environment.
Subsequent patches will start to add individual commands.
Signed-off-by: Marti Bolivar <marti@opensourcefoundries.com>
2018-05-09 23:08:38 +08:00
|
|
|
'''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:
|
2018-05-21 21:08:08 +08:00
|
|
|
log.wrn('--zephyr-base missing and no ZEPHYR_BASE',
|
|
|
|
'in the environment')
|
scripts: create meta-tool package, "west"
We have agreed to develop a meta-tool named "west", which will be a
swiss-army knife of Zephyr development. It will support use cases like
building, flashing and debugging; bootloader integration; emulator
support; and integration with multiple git repositories.
The basic usage for the tool is similar to git(1):
west [common opts] <command-name> [command opts] [<command args>]
There are common options, such as verbosity control, followed by a
mandatory sub-command. The sub-command then takes its own options and
arguments.
This patch adds the basic framework for this tool, as follows:
- a Python 3 package named 'west', in scripts/meta. There is no PyPI
integration for now; the tool will be improving quickly, so we need
to keep users up to date by having it in tree.
- an main entry point, main.py, and a package-level shim, __main__.py
- a cmd subpackage, which defines the abstract base class for commands
- logging (log.py)
- catch-all utilities (util.py)
- Windows and Unix launchers so users can type "west" to run the tool
after sourcing the appropriate zephyr-env script for their
environment.
Subsequent patches will start to add individual commands.
Signed-off-by: Marti Bolivar <marti@opensourcefoundries.com>
2018-05-09 23:08:38 +08:00
|
|
|
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)
|