From 522395f93b6accbefb7388a75e216843dcbcb135 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Fri, 24 Apr 2026 12:50:23 -0500 Subject: [PATCH] [core] Match wake storage conditionals across platform TUs ESPHome's defines.h unconditionally #defines every feature flag for static analysis, so clang-tidy sees ESPHOME_THREAD_MULTI_ATOMICS even when building wake_esp8266.cpp / wake_rp2040.cpp / wake_generic.cpp. In that mode wake.h picks the std::atomic extern, and the plain-volatile definitions in those TUs trip a redefinition error. Guard each TU's g_wake_requested with the same ESPHOME_THREAD_MULTI_ATOMICS check wake.h uses. Real builds still pick volatile on every SINGLE platform. --- esphome/core/wake/wake_esp8266.cpp | 8 +++++++- esphome/core/wake/wake_generic.cpp | 12 ++++++++++-- esphome/core/wake/wake_rp2040.cpp | 8 +++++++- 3 files changed, 24 insertions(+), 4 deletions(-) diff --git a/esphome/core/wake/wake_esp8266.cpp b/esphome/core/wake/wake_esp8266.cpp index 9ced43c6df..4c12470148 100644 --- a/esphome/core/wake/wake_esp8266.cpp +++ b/esphome/core/wake/wake_esp8266.cpp @@ -8,9 +8,15 @@ namespace esphome { // === Wake-requested flag + main-loop woke flag storage === -// ESP8266 is always ESPHOME_THREAD_SINGLE. +// ESP8266 is always ESPHOME_THREAD_SINGLE in real builds, but defines.h (used +// for static analysis / IDE) can define ESPHOME_THREAD_MULTI_ATOMICS alongside +// USE_ESP8266, so the storage type here has to match wake.h's conditional. // NOLINTBEGIN(cppcoreguidelines-avoid-non-const-global-variables) +#ifdef ESPHOME_THREAD_MULTI_ATOMICS +std::atomic g_wake_requested{0}; +#else volatile uint8_t g_wake_requested = 0; +#endif volatile bool g_main_loop_woke = false; // NOLINTEND(cppcoreguidelines-avoid-non-const-global-variables) diff --git a/esphome/core/wake/wake_generic.cpp b/esphome/core/wake/wake_generic.cpp index 40044e4311..b90aa593b3 100644 --- a/esphome/core/wake/wake_generic.cpp +++ b/esphome/core/wake/wake_generic.cpp @@ -8,9 +8,17 @@ namespace esphome { // === Wake-requested flag storage === -// Fallback platforms (currently only Zephyr/NRF52) are ESPHOME_THREAD_SINGLE. -// NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables) +// Fallback platforms (currently only Zephyr/NRF52) are ESPHOME_THREAD_SINGLE in +// real builds, but defines.h (used for static analysis / IDE) can define +// ESPHOME_THREAD_MULTI_ATOMICS here too, so the storage type has to match +// wake.h's conditional. +// NOLINTBEGIN(cppcoreguidelines-avoid-non-const-global-variables) +#ifdef ESPHOME_THREAD_MULTI_ATOMICS +std::atomic g_wake_requested{0}; +#else volatile uint8_t g_wake_requested = 0; +#endif +// NOLINTEND(cppcoreguidelines-avoid-non-const-global-variables) } // namespace esphome diff --git a/esphome/core/wake/wake_rp2040.cpp b/esphome/core/wake/wake_rp2040.cpp index b18248dbd2..3fa47d4dcc 100644 --- a/esphome/core/wake/wake_rp2040.cpp +++ b/esphome/core/wake/wake_rp2040.cpp @@ -11,9 +11,15 @@ namespace esphome { // === Wake-requested flag + main-loop woke flag storage === -// RP2040 is always ESPHOME_THREAD_SINGLE. +// RP2040 is always ESPHOME_THREAD_SINGLE in real builds, but defines.h (used +// for static analysis / IDE) can define ESPHOME_THREAD_MULTI_ATOMICS alongside +// USE_RP2040, so the storage type here has to match wake.h's conditional. // NOLINTBEGIN(cppcoreguidelines-avoid-non-const-global-variables) +#ifdef ESPHOME_THREAD_MULTI_ATOMICS +std::atomic g_wake_requested{0}; +#else volatile uint8_t g_wake_requested = 0; +#endif volatile bool g_main_loop_woke = false; // NOLINTEND(cppcoreguidelines-avoid-non-const-global-variables)