If fbuild produced a fresher ELF than PlatformIO's `prog_path`, rewrite the path to point at the fbuild artifact so symbol/size analysis reads the build we just produced — not whatever an older `pio run` left in `.pio/build/ /`. fbuild emits to `.fbuild/build/ /<release|debu
(
build_dir: Path, data: dict[str, dict[str, Any]], board: "Board"
)
| 90 | |
| 91 | |
| 92 | def _override_prog_path_for_fbuild( |
| 93 | build_dir: Path, data: dict[str, dict[str, Any]], board: "Board" |
| 94 | ) -> None: |
| 95 | """If fbuild produced a fresher ELF than PlatformIO's `prog_path`, |
| 96 | rewrite the path to point at the fbuild artifact so symbol/size |
| 97 | analysis reads the build we just produced — not whatever an older |
| 98 | `pio run` left in `.pio/build/<env>/`. |
| 99 | |
| 100 | fbuild emits to `.fbuild/build/<env>/<release|debug>/firmware.elf`, |
| 101 | where the subdir is picked by build mode (`fbuild build` defaults to |
| 102 | `release/`; `fbuild build --quick` lands in `debug/`). We probe both |
| 103 | candidates and pick whichever ELF is newer — that way `--quick` |
| 104 | builds get the same staleness override the default mode does. |
| 105 | |
| 106 | No-op when the fbuild directory is absent (pure PlatformIO build), |
| 107 | when the PIO ELF is newer than all fbuild candidates (PIO was the |
| 108 | active backend), or when the metadata blob has no recognisable |
| 109 | environment entry. |
| 110 | """ |
| 111 | fbuild_root = build_dir / ".fbuild" / "build" |
| 112 | if not fbuild_root.is_dir(): |
| 113 | return |
| 114 | |
| 115 | if not data: |
| 116 | return |
| 117 | |
| 118 | env_name = board.board_name if board.board_name in data else next(iter(data), None) |
| 119 | if env_name is None: |
| 120 | return |
| 121 | env = data[env_name] |
| 122 | |
| 123 | # fbuild lays out artifacts under <env>/<release|debug>/firmware.elf. |
| 124 | # `fbuild build` -> release/ |
| 125 | # `fbuild build --release` -> release/ |
| 126 | # `fbuild build --quick` -> debug/ |
| 127 | # Pick whichever variant is newer so users running --quick still get |
| 128 | # a fresh staleness override (Closes #2852). |
| 129 | fbuild_elf_candidates = [ |
| 130 | fbuild_root / env_name / "release" / "firmware.elf", |
| 131 | fbuild_root / env_name / "debug" / "firmware.elf", |
| 132 | ] |
| 133 | existing = [c for c in fbuild_elf_candidates if c.exists()] |
| 134 | if not existing: |
| 135 | return |
| 136 | fbuild_elf = max(existing, key=lambda p: p.stat().st_mtime) |
| 137 | |
| 138 | current_prog_raw = env.get("prog_path") |
| 139 | if isinstance(current_prog_raw, str) and current_prog_raw: |
| 140 | current_prog = Path(current_prog_raw) |
| 141 | # Only override when fbuild's ELF is strictly newer (or PIO's is |
| 142 | # missing). A successful `pio run` that beats the most recent |
| 143 | # fbuild run should win. |
| 144 | if current_prog.exists(): |
| 145 | try: |
| 146 | if current_prog.stat().st_mtime >= fbuild_elf.stat().st_mtime: |
| 147 | return |
| 148 | except OSError: |
| 149 | pass |