toolchain_tool owns the bin path and Windows suffix now; _BuildConfig's
knob and MMU fields are required since the only constructor always
passes both; the tests' set-flags-then-resolve idiom collapses into one
_resolve helper (12 sites).
toolchain_tool carries the bin/xtensa-lx106-elf-<name> pattern and the
Windows suffix that four call sites previously spelled out (only one of
which handled the suffix). ccache_env and get_build_env accept the
already-resolved ccache path so run_compile can resolve once instead of
paying the PATH scan and runnability probe three times per build.
The dict-shorthand bundled preference ran after convert_libraries had
already resolved the dependency through the registry, so a real
{"Wire": "*"} manifest still fetched or failed on a registry Wire (the
mocked test hid it). LibraryBackend gains an optional provides hook the
walk consults for owner-less dependencies; the arduino backend answers
from the framework tree and the bundled copy is added after emit. A
real-converter test with a local library pins that the registry is
never touched. _emit also validates the manifest shape by name before
apply_extra_script dereferences it.
The routed override (published configs pin 160000000L for
timing-sensitive integrations) reaches -DF_CPU via a small _pio_option
reader; the default stays the audited 80 MHz all 45 boards ship.
Published configs override it to reserve a filesystem region
(SmartIntercom's eagle.flash.4m2m.ld) or to correct a board's assumed
flash size (2 MB ESP8285 plugs pinning eagle.flash.2m.ld); dropping it
changes the flash layout under them.
Dropping it was a real regression: many published ESP8266 configs pin
board_build.f_cpu: 160000000L for timing-sensitive integrations
(MHI-AC-Ctrl documents the 160 MHz requirement in its example), and the
warn-and-drop left those devices at 80 MHz. The option now routes into
CORE.platformio_options under toolchain: arduino for the generator to
consume; other native toolchains keep the warning.
F_CPU gets the same drift-audit note as _MMU_DEFAULT: upstream reads it
from the board manifest, and all 45 supported boards ship 80000000L.
The plain-form refusal also covers -e, -s, -static, and -nostartfiles,
which gcc accepts inertly on a -c line.
tokens is a required parameter on _flag_defines and _project_flags now,
so the per-consumer re-lex the shared lexer was meant to end cannot
come back. The cache stamp covers the gcc binary's size and mtime via
a shared _stat_sig (an in-place toolchain re-extraction regenerates
the script like a header edit). A bare -I or -D from an empty argument
is warned and skipped instead of letting gcc eat the next flag.
_defines_flags documents that its tokens carry shell-level escaping and
must be emitted unquoted, and _MMU_DEFAULT notes why the board-manifest
values are hardcoded.
Both testing-mode segment patches get the RuntimeError-to-EsphomeError
wrap the ratetable surgery already had. Plain-form -T/-Xlinker/-u flags
raise naming the -Wl, form instead of warning into an inert -c compile
line. _lexed_build_flags and _unflag_tokens go through the shared
lex_build_flags so a future lexing fix cannot miss this path. The MMU
conflict message names dropping the variant knob when MMU_CUSTOM is
already set. An unreadable (not absent) header forces a cache miss
every run instead of pinning the stamp to a constant, and preprocessor
warnings persist beside the stamp and re-emit on cache hits. The drift
docstring states what the tests actually pin.
The bundled-dependency visibility warning also reads the
library.properties depends= key the shared parser returns raw, since
properties is the format bundled libraries actually ship. A bundled
manifest declaring an extraScript warns that it never runs (a new
Known-deviations entry). A version-less manifest dependency the config
separately requests as a top-level library is already in the build, so
the skipping warning no longer fires for it and cannot teach users to
ignore the real drop.
A top-level library the converter dropped always makes the firmware
wrong, so resolve_libraries raises naming the missing requests instead
of warning toward link errors, and a resolved component without its
node_key fails as a converter bug rather than silently substituting the
mismatched canonical name. includeDir and srcFilter join srcDir and
flags in raising a named error on malformed values, and dot_a_linkage
parses through the same strict table as libArchive so a typo warns and
keeps the archive default instead of flipping link semantics.
A non-dict manifest or build section raises an EsphomeError naming the
library instead of an AttributeError. ConvertedLibrary remembers the
request-side node key it resolved from, so the converter-drop warning
diffs requests against those keys; a bare name resolving to a canonical
owner__pkg is no longer falsely listed missing. A bundled library whose
manifest declares dependencies warns that the walk never runs for it (a
no-op on the ESP8266 core, not on every core this module serves).
functools.cache froze the ESPHOME_CCACHE_ENABLE/PATH decision for the
process lifetime, which a long-lived host like device-builder never
restarts, and forced a cache_clear fixture in the tests. The docstring
and test now pin the uncached delegation.
file["system"] normalized None and str but let an int or dict fall
through to the in test, where an int raises TypeError and a dict
becomes a key test; both now raise the same Unexpected-response error
as the other shape guards.
<= 2.6.2 instead of < 2.6.3: a 2.6.2 pre-release sorts above 2.6.2 and
belongs to the package-major-3 encoding, so the helper now describes
the same set as _format_framework_arduino_version and a 2.6.2-b1 pin
formats as it does on dev. The module never logged, so its _LOGGER and
logging import go.
cv.Invalid now carries path=[CONF_VERSION] so the rejection lands on
the framework version line the comment promised, matching the esp32
convention. framework_package_version raises for cores before 2.6.3
instead of encoding them wrongly for a caller that skipped the
PlatformIO path's era guard. get_build_env joins PATH from filtered
parts so an absent PATH cannot leave a trailing separator that the
shell reads as the current directory.
A raw MMU_* define alongside a PIO_FRAMEWORK_ARDUINO_MMU_* knob, or a
raw TCP_MSS/LWIP_* alongside the lwIP knobs, would win the compile line
while the linker script or prebuilt library keeps the knob's values;
both now raise like the no-knob case. _MMU_VARIANTS holds tuples and the
resolved config gets a copy, so nothing aliases the module table.
_lexed_build_flags lexes once and both consumers accept the tokens, so
a malformed entry warns once per build. The linker-script stamp covers
the header's size and mtime, an unreadable or non-UTF-8 cache
regenerates instead of aborting, plain-form linker flags warn that they
are not routed to the link line, and a moved rate-table anchor surfaces
as a named build error.
parse_enable_env carries the 1/true/yes/on and 0/false/no/off table for
both knobs, so IDF_CCACHE_ENABLE=off disables instead of reading as
truthy and suppressing the shared opt-out. The ccache module docstring
and the ESP-IDF _ccache_env docstring now describe the precedence this
PR actually ships, and the probe test duplicated by the helper move is
dropped from the PlatformIO toolchain tests.