diff --git a/scripts/west_commands/runners/core.py b/scripts/west_commands/runners/core.py index 611848f671cd..a47f76f1e9e0 100644 --- a/scripts/west_commands/runners/core.py +++ b/scripts/west_commands/runners/core.py @@ -318,6 +318,7 @@ class RunnerCaps: hide_load_files: bool = False rtt: bool = False # This capability exists separately from the rtt command # to allow other commands to use the rtt address + dry_run: bool = False def __post_init__(self): if self.mult_dev_ids and not self.dev_id: @@ -492,6 +493,9 @@ def __init__(self, cfg: RunnerConfig): self.logger = logging.getLogger(f'runners.{self.name()}') '''logging.Logger for this instance.''' + self.dry_run = _DRY_RUN + '''log commands instead of executing them. Can be set by subclasses''' + @staticmethod def get_runners() -> list[type['ZephyrBinaryRunner']]: '''Get a list of all currently defined runner classes.''' @@ -639,6 +643,10 @@ def add_parser(cls, parser): else: parser.add_argument('--rtt-address', help=argparse.SUPPRESS) + parser.add_argument('--dry-run', action='store_true', + help=('''Print all the commands without actually + executing them''' if caps.dry_run else argparse.SUPPRESS)) + # Runner-specific options. cls.do_add_parser(parser) @@ -685,6 +693,8 @@ def create(cls, cfg: RunnerConfig, _missing_cap(cls, '--file-type') if args.rtt_address and not caps.rtt: _missing_cap(cls, '--rtt-address') + if args.dry_run and not caps.dry_run: + _missing_cap(cls, '--dry-run') ret = cls.do_create(cfg, args) if args.erase: @@ -860,7 +870,7 @@ def run_client(self, client, **kwargs): def _log_cmd(self, cmd: list[str]): escaped = ' '.join(shlex.quote(s) for s in cmd) - if not _DRY_RUN: + if not self.dry_run: self.logger.debug(escaped) else: self.logger.info(escaped) @@ -873,7 +883,7 @@ def call(self, cmd: list[str], **kwargs) -> int: using subprocess directly, to keep accurate debug logs. ''' self._log_cmd(cmd) - if _DRY_RUN: + if self.dry_run: return 0 return subprocess.call(cmd, **kwargs) @@ -885,7 +895,7 @@ def check_call(self, cmd: list[str], **kwargs): using subprocess directly, to keep accurate debug logs. ''' self._log_cmd(cmd) - if _DRY_RUN: + if self.dry_run: return subprocess.check_call(cmd, **kwargs) @@ -897,7 +907,7 @@ def check_output(self, cmd: list[str], **kwargs) -> bytes: using subprocess directly, to keep accurate debug logs. ''' self._log_cmd(cmd) - if _DRY_RUN: + if self.dry_run: return b'' return subprocess.check_output(cmd, **kwargs) @@ -918,7 +928,7 @@ def popen_ignore_int(self, cmd: list[str], **kwargs) -> subprocess.Popen: preexec = os.setsid # type: ignore self._log_cmd(cmd) - if _DRY_RUN: + if self.dry_run: return _DebugDummyPopen() # type: ignore return subprocess.Popen(cmd, creationflags=cflags, preexec_fn=preexec, **kwargs) diff --git a/scripts/west_commands/runners/nrf_common.py b/scripts/west_commands/runners/nrf_common.py index 75ad66aed99f..5cdca1e6b3f6 100644 --- a/scripts/west_commands/runners/nrf_common.py +++ b/scripts/west_commands/runners/nrf_common.py @@ -75,10 +75,10 @@ def __init__(self, cfg, family, softreset, pinreset, dev_id, erase=False, self.tool_opt += opts @classmethod - def _capabilities(cls, mult_dev_ids=False): + def _capabilities(cls, mult_dev_ids=False, dry_run=False): return RunnerCaps(commands={'flash'}, dev_id=True, mult_dev_ids=mult_dev_ids, erase=True, reset=True, - tool_opt=True) + tool_opt=True, dry_run=dry_run) @classmethod def _dev_id_help(cls) -> str: diff --git a/scripts/west_commands/runners/nrfutil.py b/scripts/west_commands/runners/nrfutil.py index 9deb32e06a02..051a686f5a1a 100644 --- a/scripts/west_commands/runners/nrfutil.py +++ b/scripts/west_commands/runners/nrfutil.py @@ -5,12 +5,10 @@ '''Runner for flashing with nrfutil.''' import json -import shlex import subprocess import sys from pathlib import Path -from runners.core import _DRY_RUN from runners.nrf_common import NrfBinaryRunner @@ -37,7 +35,7 @@ def name(cls): @classmethod def capabilities(cls): - return NrfBinaryRunner._capabilities(mult_dev_ids=True) + return NrfBinaryRunner._capabilities(mult_dev_ids=True, dry_run=True) @classmethod def dev_id_help(cls) -> str: @@ -65,23 +63,15 @@ def do_add_parser(cls, parser): parser.add_argument('--ext-mem-config-file', required=False, dest='ext_mem_config_file', help='path to an JSON file with external memory configuration') - parser.add_argument('--dry-run', required=False, - action='store_true', - help='''Generate all the commands without actually - executing them''') def _exec(self, args, force=False): jout_all = [] cmd = ['nrfutil', '--json', 'device'] + args + self._log_cmd(cmd) - escaped = ' '.join(shlex.quote(s) for s in cmd) - if _DRY_RUN or (self.dry_run): - self.logger.info(escaped) - if not force: - return {} - else: - self.logger.debug(escaped) + if self.dry_run and not force: + return {} with subprocess.Popen(cmd, stdout=subprocess.PIPE) as p: for line in iter(p.stdout.readline, b''): @@ -162,7 +152,7 @@ def _append_batch(self, op, json_file): def _exec_batch(self): # Use x-append-batch to get the JSON from nrfutil itself - json_file = Path(self.hex_).parent / 'generated_nrfutil_batch.json' + json_file = Path(self.cfg.build_dir) / 'zephyr' / 'generated_nrfutil_batch.json' json_file.unlink(missing_ok=True) for op in self._ops: self._append_batch(op, json_file)