The build.ninja python variable goes through strip_win_long_path_prefix
like every other emitted binary path (the NSIS launcher's extended
prefix cannot be spawned by cmd.exe). Compile rules are named by the
shared source kinds directly, retiring the identity translation table
and its drift test. write_project takes the caller's resolved ccache,
get_flash_ld_path reads the InstalledPaths the ninja file linked
against instead of re-resolving the version, the board backstop checks
the one table it indexes with an honest comment, and cc/cxx/ar paths go
through the shared toolchain_tool accessor (gaining the Windows
suffix).
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.
Published configs override it to reserve a filesystem region or correct
a board's assumed flash size; the routed value replaces the BOARDS
default, and a path is rejected since the name resolves via -L.
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.
write_project rejects a board missing from either table, so a new test
asserts the two stay exactly equal (the subset check is how d1_wroom_02
went missing). The hardcoded --flash_freq 40 carries the audit note:
all 45 supported boards ship 40 MHz, and a platform bump adding one
that does not must revisit it.
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).