From 7a81a5d010d93be0135d3f86c1ad4ce8806cfd01 Mon Sep 17 00:00:00 2001 From: Jan Beran Date: Tue, 14 Apr 2026 15:11:03 +0200 Subject: [PATCH] fix: support linux target not generating flasher_args.json This allows testing IDF_TARGET_LINUX builds (APP_BUILD_TYPE_ELF_ONLY) even without an esptool flasher_args file present, by skipping flash- related operations (serial flash, JTAG flash, flash args parsing) when the build is a Linux host ELF-only output. Made-with: Cursor --- .../pytest_embedded_idf/app.py | 19 +++++++++++++++---- .../pytest_embedded_idf/dut.py | 5 +++++ .../pytest_embedded_idf/serial.py | 4 ++++ 3 files changed, 24 insertions(+), 4 deletions(-) diff --git a/pytest-embedded-idf/pytest_embedded_idf/app.py b/pytest-embedded-idf/pytest_embedded_idf/app.py index b2e3a029..09f6391a 100644 --- a/pytest-embedded-idf/pytest_embedded_idf/app.py +++ b/pytest-embedded-idf/pytest_embedded_idf/app.py @@ -24,6 +24,9 @@ class IdfApp(App): flash_args (dict[str, Any]): dict of flasher_args.json flash_files (list[FlashFile]): list of (offset, file path, encrypted) of files need to be flashed in flash_settings (dict[str, Any]): dict of flash settings + is_loadable_elf (bool): Chip RAM app (``APP_BUILD_TYPE_RAM`` / ``APP_BUILD_TYPE_ELF_RAM``); esptool + ``load_ram`` path. + is_linux_elf (bool): Linux host ELF-only build (``APP_BUILD_TYPE_ELF_ONLY``), no flasher_args.json. """ XTENSA_TARGETS: ClassVar[list[str]] = ['esp32', 'esp32s2', 'esp32s3'] @@ -74,10 +77,13 @@ def __init__( else: self.is_loadable_elf = False + # Linux target: ELF-only output, no flasher_args.json. + self.is_linux_elf = bool(self.sdkconfig.get('APP_BUILD_TYPE_ELF_ONLY')) + self.bin_file = self._get_bin_file() self.flash_args, self.flash_files, self.flash_settings = {}, [], {} - if not self.is_loadable_elf: + if not (self.is_loadable_elf or self.is_linux_elf): self.flash_args, self.flash_files, self.flash_settings = self._parse_flash_args_json() @property @@ -153,10 +159,15 @@ def partition_table(self) -> dict[str, Any]: if self._partition_table is not None: return self._partition_table - partition_file = os.path.join( - self.binary_path, - self.flash_args.get('partition_table', self.flash_args.get('partition-table', {})).get('file', ''), + # see - vs _ in 'partition table' key name + partition_rel_path = self.flash_args.get('partition_table', self.flash_args.get('partition-table', {})).get( + 'file', '' ) + if not partition_rel_path: + self._partition_table = {} + return self._partition_table + + partition_file = os.path.join(self.binary_path, partition_rel_path) process = subprocess.Popen( [sys.executable, self.parttool_path, partition_file], stdout=subprocess.PIPE, diff --git a/pytest-embedded-idf/pytest_embedded_idf/dut.py b/pytest-embedded-idf/pytest_embedded_idf/dut.py index a0e325c2..5385ccf5 100644 --- a/pytest-embedded-idf/pytest_embedded_idf/dut.py +++ b/pytest-embedded-idf/pytest_embedded_idf/dut.py @@ -270,6 +270,11 @@ def flash_via_jtag(self): # >>> self.gdb.write('load') return + if self.app.is_linux_elf: + # linux ELF file. OpenOCD is meaningless + logging.debug('Linux ELF-only build; skipping OpenOCD program_esp.') + return + for _f in self.app.flash_files: if _f.encrypted: raise ValueError("Encrypted files can't be flashed in via JTAG") diff --git a/pytest-embedded-idf/pytest_embedded_idf/serial.py b/pytest-embedded-idf/pytest_embedded_idf/serial.py index 22ba3a63..a4b6994d 100644 --- a/pytest-embedded-idf/pytest_embedded_idf/serial.py +++ b/pytest-embedded-idf/pytest_embedded_idf/serial.py @@ -72,6 +72,10 @@ def _start(self): else: if self.app.is_loadable_elf: self.load_ram() + elif self.app.is_linux_elf: + # Host Linux ELF (IDF_TARGET_LINUX); no flasher_args.json. + logging.info('Linux ELF-only build; skipping auto flash.') + super()._start() else: self.flash()