Commit Graph

602 Commits

Author SHA1 Message Date
J. Nick Koston 8096b95910 Merge remote-tracking branch 'upstream/skip_external_files_update_logs' into integration 2026-04-26 04:51:47 -05:00
J. Nick Koston 3438ff817a Address review: drop redundant comments and rely on existing CORE.reset() between tests 2026-04-26 04:49:04 -05:00
J. Nick Koston 4654f427ca Merge remote-tracking branch 'upstream/skip_external_files_update_logs' into integration 2026-04-26 04:44:42 -05:00
J. Nick Koston 5150a32224 [external_files] Unify skip_external_update via CORE flag for git as well 2026-04-26 04:43:53 -05:00
J. Nick Koston 26ba4850e4 [external_files] Skip remote freshness checks during esphome logs
Avoid per-file HTTP HEAD requests during config validation when running
esphome logs against a previously-cached project. The skip_external_update
flag was already plumbed for git operations, but external_files.download_content
ignored it. Thread it through CORE so audio_file, micro_wake_word,
speaker/media_player, image, font, and bme68x_bsec2 reuse cached files
without per-URL network round-trips when the file already exists locally.
2026-04-26 04:37:35 -05:00
J. Nick Koston a8d767cc5c Merge remote-tracking branch 'upstream/dev' into integration 2026-04-26 04:16:55 -05:00
J. Nick Koston 9028cc8c3e Merge remote-tracking branch 'origin/git_shallow_fetch' into integration 2026-04-26 04:13:13 -05:00
Darafei Praliaskouski 68625a1b76 [core] Isolate generated build metadata (#16007)
Co-authored-by: J. Nick Koston <nick@koston.org>
Co-authored-by: J. Nick Koston <nick@home-assistant.io>
2026-04-26 09:11:09 +00:00
J. Nick Koston e907e71101 [git] Address PR review feedback
- Add `--` terminator before submodule paths (both clone and refresh
  paths) so a path beginning with `-` cannot be parsed as a git option.
- Reword the refresh-fetch comment: this fetch also runs when ref is
  None, in which case it pulls the remote default branch.
2026-04-26 04:08:43 -05:00
J. Nick Koston b3a57d1395 [git] Make ref fetches and submodule updates shallow
Fixes esphome/esphome#11550

When clone_or_update is called with a ref or submodules, the initial
clone uses --depth=1 but the subsequent git fetch and git submodule
update commands run deep, pulling the full history on every refresh.
This causes excess network traffic and disk usage for external_components,
packages, and dashboard imports.

Add --depth=1 to all four call sites (initial fetch, initial submodule
init, refresh fetch, refresh submodule update). Shallow fetches still
advance the local clone to the current remote tip when it moves, so the
refresh path keeps working as before.
2026-04-26 03:57:35 -05:00
J. Nick Koston f797090f1d Merge remote-tracking branch 'origin/output-power-scaling-optional' into integration 2026-04-25 12:42:52 -05:00
Javier Peletier b5ccd55f4e [packages] Fix premature substitution of vars in remote package files (#15997)
Co-authored-by: J. Nick Koston <nick+github@koston.org>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2026-04-25 17:06:58 +00:00
J. Nick Koston 835b9a55a0 Merge remote-tracking branch 'upstream/dev' into integration 2026-04-23 14:53:33 -05:00
Paulus Schoutsen 9b45b046a8 [core] Allow finding all devices as target that match mac suffix (#13135) 2026-04-23 08:43:32 -05:00
J. Nick Koston bb3ad6e431 Merge remote-tracking branch 'upstream/dev' into integration 2026-04-22 22:32:06 -05:00
Jesse Hills e1d629f0d2 [time] Handle Windows EINVAL when validating POSIX TZ strings (#15934) 2026-04-23 14:35:13 +12:00
J. Nick Koston d9cb0a8f2d Merge remote-tracking branch 'upstream/dev' into integration 2026-04-22 05:41:38 +02:00
Javier Peletier 9cebce1b6e [substitutions] Improve error messages with include stack trace (#15874)
Co-authored-by: J. Nick Koston <nick@home-assistant.io>
2026-04-22 03:19:01 +02:00
J. Nick Koston 574bdc9a00 Merge remote-tracking branch 'origin/decouple_scheduler_loop_cadence' into integration 2026-04-20 12:06:28 +02:00
Javier Peletier aad1318b4a [packages] Improve error messages with include stack and fix missing path propagation (#15844)
Co-authored-by: pre-commit-ci-lite[bot] <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com>
Co-authored-by: J. Nick Koston <nick@home-assistant.io>
Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com>
2026-04-19 21:09:14 +00:00
J. Nick Koston 7a23a339e9 [substitutions] Fix substitutions: !include file.yaml regression (#15850) 2026-04-20 09:00:31 +12:00
J. Nick Koston 0d43973380 Merge remote-tracking branch 'upstream/fix/substitutions-include-15848' into integration 2026-04-19 02:52:38 -05:00
J. Nick Koston 78853260a5 [substitutions] Lock in shape check and document single-shot resolve
- Add unit tests asserting cv.Invalid when `substitutions: !include list.yaml`
  resolves to a non-mapping, covering both do_substitution_pass and
  do_packages_pass.
- Note in resolve_substitutions_block that the resolve is single-shot and
  chained top-level includes are not supported (matches _walk_packages for
  `packages: !include`).
2026-04-19 02:50:20 -05:00
J. Nick Koston e67b65b669 [substitutions] [packages] Address review feedback
- Seed `resolve_include` context with `command_line_substitutions` so
  `substitutions: !include ${var}.yaml` can reference CLI-provided vars
  in the include filename (parallels the `packages: !include` path).
- Validate shape of resolved substitutions in `do_packages_pass` and raise
  `cv.Invalid` under `CONF_SUBSTITUTIONS` instead of letting `UserDict()`
  fail with a low-level exception on a non-mapping.
- Fixture 17 exercises the CLI-templated include filename.
2026-04-19 02:42:03 -05:00
J. Nick Koston ba8e729443 [substitutions] [packages] Fix substitutions: !include file.yaml regression
Resolve a deferred IncludeFile before validating the substitutions shape in
do_substitution_pass, and before wrapping it in UserDict in do_packages_pass.

Fixes esphome/esphome#15848
2026-04-19 02:25:00 -05:00
J. Nick Koston fa2a75acd0 Merge remote-tracking branch 'origin/core-chunked-setup' into integration 2026-04-17 17:46:08 -05:00
J. Nick Koston 00f08ba6ed [core] Drop per-component begin/end labels from generated main.cpp
The labels were there to help humans scanning the generated main.cpp
find component boundaries, but they were:

- Unreliable: CORE.flush_tasks can interleave coroutines on each
  await, so a component's later statements can land in another
  component's begin/end block.
- Load-bearing for a pile of complexity: a tuple return from
  _wrap_in_iifes, a has_iife flag, a comment-only detector to
  suppress trailing end-markers for comment-only components, and
  a brittle `"[]()" in line` check that could false-positive on
  YAML dumps containing lambda syntax.
- Not actually needed — generated main.cpp is a build artifact
  rarely read by anyone, and cg.LineComment("name:") already puts
  the component name at the start of its block.

ComponentMarker stays as a pure chunking sentinel — it tells
cpp_main_section where component boundaries are (for grouping) but
produces no C++ output. _wrap_in_iifes returns a plain list again.
Added a regression test for the now-defused case of a comment
containing "[]()" that was previously flagged by review.
2026-04-17 15:19:48 -05:00
J. Nick Koston f82401a504 [core] Address Copilot review: robust brace depth, accurate docstrings
- Count { and } characters per line instead of matching whole-line
  tokens. Current codegen only emits scope braces as standalone lines
  (from cg.with_local_variable()), but the defensive change is robust
  against future codegen emitting inline control flow like
  `if (cond) {` or `} else {` on one line.
- Add a regression test covering those inline-brace patterns.
- Fix stale docstrings on ComponentMarker and cpp_main_section that
  still claimed "stack frame released on return" and described the
  IIFEs as "noinline". The IIFEs have no noinline attribute and rely
  on scope-based lifetime shortening rather than guaranteed frames.
2026-04-17 15:06:42 -05:00
J. Nick Koston 178f23a7aa [core] Use begin/end marker pairs around each component's IIFE
Rename the bracket markers from "// === X ===" (same on both sides)
to "// === begin X ===" and "// === end X ===" so the generated
main.cpp reads unambiguously when scanning by component. Comment-only
components still get a single "begin X" marker since they have no
IIFE to close.
2026-04-17 15:06:42 -05:00
J. Nick Koston 864d31aa65 [core] Put ComponentMarker outside the IIFE as a visual bracket
The marker comment was being emitted as the first line *inside* each
IIFE:

  []() {
    // === logger ===
    // logger:
    //   ...
    ...
  }();

That works but buries the component label inside the lambda body, so
scanning generated main.cpp to find "where does component X's setup
live" is harder than it needs to be. Emit the marker before and after
the IIFE instead:

  // === logger ===
  []() {
    // logger:
    //   ...
    ...
  }();
  // === logger ===

Comment-only components (e.g. sha256, async_tcp, empty platforms like
binary_sensor:) don't grow a useless trailing duplicate marker —
when there's no IIFE to bracket, the marker is emitted once.
2026-04-17 15:06:42 -05:00
J. Nick Koston 936694af2c [core] Don't emit IIFE for comment-only chunks
Some components (sha256, async_tcp, network, empty text_sensor:, etc.)
emit only a ComponentMarker plus config-dump comments and no actual
C++ statements. Wrapping those in a `[]() { ... }();` IIFE is pure
clutter in the generated main.cpp — the IIFE has no body.

When _wrap_in_iifes sees a chunk whose lines are all // comments,
emit them verbatim instead of wrapping. Peak stack and flash are
unchanged on apollo and neargaragedoor since GCC was already
eliding the empty IIFEs; this just makes the generated code read
cleanly to humans.
2026-04-17 15:06:42 -05:00
J. Nick Koston 6a7c9af870 [core] Drop noinline from IIFE chunks and rename helper
Additional measurements showed GCC's -Os inliner re-inlines most IIFE
chunks back into setup() by choice, and the structural scoping alone
captures nearly all of the peak-stack benefit on esp32 without the
flash cost of forcing all chunks to stay as real functions.

Apollo (esp32-s3, -Os) with vs without noinline:
  peak setup stack     176 B (noinline)  vs  304 B (scope-only)
  flash delta         +388 B (noinline)  vs   -504 B (scope-only)
  chunks kept          86               vs    20

Issue #15796 is an LVGL-setup class of bug that has only surfaced on
esp32 after years in the field; the extra guarantee that noinline
provides is not worth the flash cost in practice. Also rename the
helper from _wrap_in_noinline_iifes to _wrap_in_iifes to match.
2026-04-17 15:06:42 -05:00
J. Nick Koston 29dcf9fc51 [core] Use __attribute__((noinline)) on IIFE lambdas to honor attribute
The C++ standard-attribute spelling [[gnu::noinline]] placed between a
lambda's parameter list and body binds to the return type, not the
call operator. GCC 14 silently ignores it and emits -Wattributes
warnings at every chunk site. Switch to GCC's __attribute__((...))
syntax which binds to operator() as intended.

Measured impact on apollo-r-pro-1-eth (esp32-s3, -Os) vs the broken
[[gnu::noinline]] version: setup() frame 160 B -> 32 B, peak stack
304 B -> 176 B (another -42%). Flash grows by 888 B because all 86
chunks now stay as separate functions instead of GCC inlining the
small ones (which it was free to do when the attribute was ignored).

Net vs baseline -Os: peak stack 1264 B -> 176 B (-86%); flash
+388 B (<0.05% of a typical esp32 partition).
2026-04-17 15:06:42 -05:00
J. Nick Koston 6b67224286 [core] Chunk setup() into per-component noinline IIFEs
Generated setup() is a single monolithic function whose stack frame
scales super-linearly with config size. On a 5,943-line apollo build
the frame reached 1,264 B at -Os; extrapolation onto larger configs
(e.g. the 16k-line LVGL config in #15796) plausibly overflows the
8 KB loop task stack before safe_mode can increment its boot counter.

Emit a ComponentMarker sentinel at the start of each component's
to_code output, then have cpp_main_section wrap each component's
block (and sub-splits of up to 50 statements within each block) in a
noinline IIFE lambda. Each lambda's ENTRY frame is released on
return, bounding peak stack to setup() frame + max chunk frame.

Measured on apollo-r-pro-1-eth (esp32-s3, -Os):

  setup() frame        1264 B  ->  160 B
  max chunk frame      n/a     ->  144 B
  peak setup stack     1264 B  ->  304 B  (-76%)
  total flash      792,471 B   ->  791,995 B  (-476 B)

The brace-depth guard in _wrap_in_noinline_iifes ensures we never
split between the RawStatement("{") / RawStatement("}") pair emitted
by cg.with_local_variable() (currently only wifi), so scoped locals
stay intact.
2026-04-17 15:06:41 -05:00
J. Nick Koston 162bd415ce Merge remote-tracking branch 'upstream/fix-delay-action-mutable-lambda' into integration 2026-04-17 08:36:08 -05:00
J. Nick Koston 523c6f2376 [core] coerce set_interval(0) / update_interval: 0ms to 1ms (#15799) 2026-04-17 02:45:50 -10:00
J. Nick Koston c6ad23fbc0 [bundle] Force-resolve nested IncludeFile during file discovery (#15762) 2026-04-16 08:45:33 -10:00
J. Nick Koston fa1391ac54 Merge branch 'light-force-inline-set-flag' into integration 2026-04-13 17:27:22 -10:00
J. Nick Koston edb16a27d3 [esphome] Skip missing extra flash images in upload_using_esptool (#15723)
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
2026-04-13 16:58:48 -10:00
J. Nick Koston ddf5ab6d1c Merge remote-tracking branch 'upstream/esptool-skip-missing-flash-images' into integration 2026-04-13 13:51:03 -10:00
J. Nick Koston 5f76b78cfa [esphome] Skip missing extra flash images in upload_using_esptool
PlatformIO's idedata may list flash images that do not exist on disk
(e.g. a tasmota tinyuf2.bin referenced by the adafruit_qtpy_esp32s3_n4r2
board). Previously the CLI passed every entry straight to esptool, which
aborted the entire flash with "No such file or directory". The dashboard
path is unaffected because it flashes the pre-merged firmware.factory.bin
produced by the post-build step, which already tolerates missing inputs.

Filter non-existent extra_flash_images with a warning so a stale or
incorrect platform-declared image no longer breaks esphome run.

Fixes https://github.com/esphome/esphome/issues/15634
2026-04-13 13:37:29 -10:00
J. Nick Koston 48a611b625 Merge remote-tracking branch 'upstream/captive-portal-ota-resume-brick' into integration 2026-04-13 13:21:31 -10:00
Jonathan Swoboda 5d0cfc31fa [core] Move FILTER_PLATFORMIO_LINES into platformio_runner (#15707) 2026-04-13 14:18:44 -04:00
J. Nick Koston 5d864c3491 Merge branch 'app-loop-optimize-speed' into integration 2026-04-12 20:31:23 -10:00
J. Nick Koston 3e9f464a2c Fix clang-tidy and test for optimize(O2) attribute 2026-04-12 20:21:11 -10:00
J. Nick Koston 40c2ac2f8f Merge remote-tracking branch 'upstream/dev' into integration 2026-04-12 13:08:40 -10:00
Javier Peletier daa68a2a60 [packages] fix support packages: !include mypackages.yaml (#15677) 2026-04-13 09:48:30 +12:00
J. Nick Koston 09e544125a Merge remote-tracking branch 'upstream/dev' into integration 2026-04-12 10:07:28 -10:00
Jonathan Swoboda 2f684bf4f3 [esp32] Bump platform to 55.03.38, Arduino to 3.3.8, ESP-IDF to 5.5.4 (#15666) 2026-04-12 10:07:04 -10:00
J. Nick Koston a72609e640 [yaml] Resolve top-level IncludeFile in load_yaml (#15557) 2026-04-08 08:39:14 -04:00