13
13
from .. import cmake
14
14
from .. import log
15
15
from ..runner import get_runner_cls
16
+ from ..runner .core import RunnerConfig
16
17
from . import CommandContextError
17
18
18
19
@@ -22,24 +23,56 @@ def add_parser_common(parser_adder, command):
22
23
formatter_class = argparse .RawDescriptionHelpFormatter ,
23
24
description = command .description )
24
25
25
- parser .add_argument ('-d' , '--build-dir' ,
26
- help = '''Build directory to obtain runner information
27
- from; default is the current working directory.''' )
28
- parser .add_argument ('-c' , '--cmake-cache' , default = cmake .DEFAULT_CACHE ,
29
- help = '''Path to CMake cache file containing runner
30
- configuration (this is generated by the Zephyr
31
- build system when compiling binaries);
32
- default: {}.
33
-
34
- If this is a relative path, it is assumed relative to
35
- the build directory. An absolute path can also be
36
- given instead.''' .format (cmake .DEFAULT_CACHE ))
37
- parser .add_argument ('-r' , '--runner' ,
38
- help = '''If given, overrides any cached {}
39
- runner.''' .format (command .name ))
40
- parser .add_argument ('--skip-rebuild' , action = 'store_true' ,
41
- help = '''If given, do not rebuild the application
42
- before running {} commands.''' .format (command .name ))
26
+ group = parser .add_argument_group (title = 'General Options' )
27
+ group .add_argument ('-d' , '--build-dir' ,
28
+ help = '''Build directory to obtain runner information
29
+ from; default is the current working directory.''' )
30
+ group .add_argument ('-c' , '--cmake-cache' , default = cmake .DEFAULT_CACHE ,
31
+ help = '''Path to CMake cache file containing runner
32
+ configuration (this is generated by the Zephyr
33
+ build system when compiling binaries);
34
+ default: {}.
35
+
36
+ If this is a relative path, it is assumed relative to
37
+ the build directory. An absolute path can also be
38
+ given instead.''' .format (cmake .DEFAULT_CACHE ))
39
+ group .add_argument ('-r' , '--runner' ,
40
+ help = '''If given, overrides any cached {}
41
+ runner.''' .format (command .name ))
42
+ group .add_argument ('--skip-rebuild' , action = 'store_true' ,
43
+ help = '''If given, do not rebuild the application
44
+ before running {} commands.''' .format (command .name ))
45
+
46
+ group = parser .add_argument_group (
47
+ title = 'Configuration overrides' ,
48
+ description = dedent ('''\
49
+ These values usually come from the Zephyr build system itself
50
+ as stored in the CMake cache; providing these options
51
+ overrides those settings.''' ))
52
+
53
+ # Important:
54
+ #
55
+ # 1. The destination variables of these options must match
56
+ # the RunnerConfig slots.
57
+ # 2. The default values for all of these must be None.
58
+ #
59
+ # This is how we detect if the user provided them or not when
60
+ # overriding values from the cached configuration.
61
+ group .add_argument ('--board-dir' ,
62
+ help = 'Zephyr board directory' )
63
+ group .add_argument ('--kernel-elf' ,
64
+ help = 'Path to kernel binary in .elf format' )
65
+ group .add_argument ('--kernel-hex' ,
66
+ help = 'Path to kernel binary in .hex format' )
67
+ group .add_argument ('--kernel-bin' ,
68
+ help = 'Path to kernel binary in .bin format' )
69
+ group .add_argument ('--gdb' ,
70
+ help = 'Path to GDB, if applicable' )
71
+ group .add_argument ('--openocd' ,
72
+ help = 'Path to OpenOCD, if applicable' )
73
+ group .add_argument (
74
+ '--openocd-search' ,
75
+ help = 'Path to add to OpenOCD search path, if applicable' )
43
76
44
77
return parser
45
78
@@ -57,6 +90,30 @@ def desc_common(command_name):
57
90
''' .format (** {'command' : command_name }))
58
91
59
92
93
+ def cached_runner_config (cache ):
94
+ '''Parse the RunnerConfig from a CMake Cache.'''
95
+ board_dir = cache ['ZEPHYR_RUNNER_CONFIG_BOARD_DIR' ]
96
+ kernel_elf = cache ['ZEPHYR_RUNNER_CONFIG_KERNEL_ELF' ]
97
+ kernel_hex = cache ['ZEPHYR_RUNNER_CONFIG_KERNEL_HEX' ]
98
+ kernel_bin = cache ['ZEPHYR_RUNNER_CONFIG_KERNEL_BIN' ]
99
+ gdb = cache .get ('ZEPHYR_RUNNER_CONFIG_GDB' )
100
+ openocd = cache .get ('ZEPHYR_RUNNER_CONFIG_OPENOCD' )
101
+ openocd_search = cache .get ('ZEPHYR_RUNNER_CONFIG_OPENOCD_SEARCH' )
102
+
103
+ return RunnerConfig (board_dir , kernel_elf , kernel_hex , kernel_bin ,
104
+ gdb = gdb , openocd = openocd ,
105
+ openocd_search = openocd_search )
106
+
107
+
108
+ def _override_config_from_namespace (cfg , namespace ):
109
+ '''Override a RunnerConfig's contents with command-line values.'''
110
+ for var in cfg .__slots__ :
111
+ if var in namespace :
112
+ val = getattr (namespace , var )
113
+ if val is not None :
114
+ setattr (cfg , var , val )
115
+
116
+
60
117
def do_run_common (command , args , runner_args , cached_runner_var ):
61
118
command_name = command .name
62
119
build_dir = args .build_dir or getcwd ()
@@ -79,6 +136,12 @@ def do_run_common(command, args, runner_args, cached_runner_var):
79
136
# places.
80
137
chdir (build_dir )
81
138
139
+ # Runner creation, phase 1.
140
+ #
141
+ # Get the default runner name from the cache, allowing a command
142
+ # line override. Get the ZephyrBinaryRunner class by name, and
143
+ # make sure it supports the command.
144
+
82
145
# TODO: build this by joining with build_dir once the above chdir
83
146
# goes away.
84
147
cache_file = args .cmake_cache
@@ -104,22 +167,38 @@ def do_run_common(command, args, runner_args, cached_runner_var):
104
167
log .die ('Runner {} does not support command {}' .format (
105
168
runner , command_name ))
106
169
107
- cached_common_args = cache .get_list ('ZEPHYR_RUNNER_ARGS_COMMON' )
170
+ # Runner creation, phase 2.
171
+ #
172
+ # At this point, the common options above are already parsed in
173
+ # 'args', and unrecognized arguments are in 'runner_args'.
174
+ #
175
+ # - Pull the RunnerConfig out of the cache
176
+ # - Override cached values with applicable command-line options
177
+
178
+ cfg = cached_runner_config (cache )
179
+ _override_config_from_namespace (cfg , args )
180
+
181
+ # Runner creation, phase 3.
182
+ #
183
+ # - Pull out cached runner arguments, and append command-line
184
+ # values (which should override the cache)
185
+ # - Construct a runner-specific argument parser to handle cached
186
+ # values plus overrides given in runner_args
187
+ # - Parse arguments and create runner instance from final
188
+ # RunnerConfig and parsed arguments.
189
+
108
190
cached_runner_args = cache .get_list (
109
191
'ZEPHYR_RUNNER_ARGS_{}' .format (cmake .make_c_identifier (runner )))
110
- # Construct the final command line arguments, create a
111
- # runner-specific parser to handle them, and run the command.
112
192
assert isinstance (runner_args , list ), runner_args
113
- final_runner_args = cached_common_args + cached_runner_args + runner_args
114
-
115
- # Having the runners themselves be the place where their argument
116
- # parsing is handled is hackish; it's an artifact of the time
117
- # before the runner package was part of west.
118
- #
119
- # TODO: refactor runner argument parsing higher up into west.
193
+ # If the user passed -- to force the parent argument parser to stop
194
+ # parsing, it will show up here, and needs to be filtered out.
195
+ runner_args = [arg for arg in runner_args if arg != '--' ]
196
+ final_runner_args = cached_runner_args + runner_args
120
197
parser = argparse .ArgumentParser (prog = runner )
121
198
runner_cls .add_parser (parser )
122
- parsed_args = parser .parse_args (args = final_runner_args )
123
- parsed_args .verbose = args .verbose
124
- runner = runner_cls .create_from_args (parsed_args )
199
+ parsed_args , unknown = parser .parse_known_args (args = final_runner_args )
200
+ if unknown :
201
+ raise CommandContextError ('Runner' , runner ,
202
+ 'received unknown arguments' , unknown )
203
+ runner = runner_cls .create (cfg , parsed_args )
125
204
runner .run (command_name )
0 commit comments