Copy the build artifact to the specified output path. For ESP32 boards with QEMU-style output paths, this will copy all required QEMU artifacts. For other cases, copies only the main firmware file. Args: build_dir: Build directory path board: Board configuration
(
build_dir: Path, board: Board, sketch_name: str, output_path: str
)
| 149 | |
| 150 | |
| 151 | def copy_build_artifact( |
| 152 | build_dir: Path, board: Board, sketch_name: str, output_path: str |
| 153 | ) -> bool: |
| 154 | """Copy the build artifact to the specified output path. |
| 155 | |
| 156 | For ESP32 boards with QEMU-style output paths, this will copy all required |
| 157 | QEMU artifacts. For other cases, copies only the main firmware file. |
| 158 | |
| 159 | Args: |
| 160 | build_dir: Build directory path |
| 161 | board: Board configuration |
| 162 | sketch_name: Name of the sketch |
| 163 | output_path: Target output path |
| 164 | |
| 165 | Returns: |
| 166 | True if successful, False otherwise |
| 167 | """ |
| 168 | import shutil |
| 169 | |
| 170 | # Detect ESP32 QEMU mode |
| 171 | is_esp32 = board.board_name.startswith("esp32") |
| 172 | is_qemu_mode = ( |
| 173 | "qemu" in output_path.lower() |
| 174 | or output_path.endswith("/") |
| 175 | or output_path.endswith("\\") |
| 176 | ) |
| 177 | |
| 178 | if is_esp32 and is_qemu_mode: |
| 179 | return copy_esp32_qemu_artifacts(build_dir, board, sketch_name, output_path) |
| 180 | |
| 181 | # Original single-file copy logic for non-QEMU cases |
| 182 | expected_ext = get_board_artifact_extension(board) |
| 183 | |
| 184 | # Find the source artifact |
| 185 | # PlatformIO builds are in .build/pio/{board}/.pio/build/{board}/firmware.{ext} |
| 186 | artifact_dir = build_dir / ".pio" / "build" / board.board_name |
| 187 | source_artifact = artifact_dir / f"firmware{expected_ext}" |
| 188 | |
| 189 | if not source_artifact.exists(): |
| 190 | print(f"ERROR: Build artifact not found: {source_artifact}") |
| 191 | return False |
| 192 | |
| 193 | # Ensure output directory exists |
| 194 | output_path_obj = Path(output_path) |
| 195 | output_path_obj.parent.mkdir(parents=True, exist_ok=True) |
| 196 | |
| 197 | try: |
| 198 | print(f"Copying {source_artifact} to {output_path}") |
| 199 | shutil.copy2(source_artifact, output_path) |
| 200 | print(f"✅ Build artifact saved to: {output_path}") |
| 201 | return True |
| 202 | except KeyboardInterrupt as ki: |
| 203 | handle_keyboard_interrupt(ki) |
| 204 | raise |
| 205 | except Exception as e: |
| 206 | print(f"ERROR: Failed to copy build artifact: {e}") |
| 207 | return False |
no test coverage detected