The throw_stubs force-include now comes from the build_src_flags option
esp8266/__init__ pins, collapsing the two spellings to one source of
truth; -include paths resolve against the source root. The ldscript
fallback consumes boards.board_ld_script instead of duplicating the
per-board rule, flash_mode is checked against its closed set before
landing unquoted in the elf2bin command, and the board-gate comment no
longer names a nonexistent validator.
LOW_MEMORY is upstream's else branch, so the default variant stands in
for it and every listed knob wins -- pinned for the ordinary SNTP
multi-server config where esp8266's HIGHER_BANDWIDTH_LOW_FLASH must
prevail. A stale warn note that cannot be removed now vetoes the stamp
(mirror of the lost-note case), and the unreadable-cached-note warning
names its cause.
CPPDEFINES joins the quoted buckets (a spaced define no longer splits
across tokens) and its tuple branch validates the pair elements. The
fake env warns on attribute access rather than call, so hasattr/
truthiness branches are diagnosable, with dunder probes excluded; an
unmodelled subscript warns and returns '' instead of a KeyError
discarding the whole capture. Malformed platforms/frameworks values
raise plain InvalidLibrary, giving the non-platform warning branches a
real producer, and their tests use real manifests instead of
monkeypatched raisers. The version-less dependency drop moves to debug:
bundled names (Wire, SPI) made it per-build noise nobody can act on.
The registry response already carries each package file's size, so the
combined bar is sized from URLSource instead of a HEAD sweep; the probe,
its all-or-nothing fallback, and its duplicate Content-Length parsing are
gone, and archives without a reported size simply stay on the sequential
path. run_batch_downloads now takes (name, size, fetch) jobs and builds
the (now private) progress bar itself, collecting failures from future
results instead of a shared list; both call sites use functools.partial
instead of lambda factories. The prefetch touches only URLSource, so the
progress parameter comes off Source/Git/Local/ConvertedLibrary, and the
wave prefetch is wrapped best-effort like its ESP-IDF twin, which also
dedupes by dest only after the verifiability check. ProgressBar.done()
itself now skips the newline when no frame was drawn or the 100% frame
already ended the line, collapsing the batch wrapper's guard and fixing
the stray blank line after OTA uploads.
Split out of #18662: the converter/manifest hardening without the
download parallelization, which stays there.
The PIO extra-script shim moves from espidf/ to platformio/ and gains
type checks for every manifest field, capture of the Append variants and
CPPPATH, warn-once diagnostics for unmodelled env reads, and uniform
shlex quoting so captured values survive the lex_build_flags round-trip.
The dependency walk normalizes every spelling PIO accepts, splits the
routine cross-platform skip (IncompatiblePlatform) from real manifest
problems, validates manifest shape once, and the shared flag lexer
warns and drops trailing or empty glued arguments.
A failed stderr-sidecar write no longer stamps the cache: the next build
re-runs -E and re-derives the preprocessor diagnostic honestly instead
of losing it for the life of the build dir. The sidecar unlink joins the
best-effort contract. The plain-linker denylist gains the
-nodefaultlibs/-nostdlib/-rdynamic family and the -fuse-ld=/--specs=
prefixes, with a comment naming it best-effort rather than complete.
The damaged-file helper test now lives only in test_helpers.py beside
the OSError-branch coverage.