diff --git a/esphome/components/esp32/__init__.py b/esphome/components/esp32/__init__.py index a8a5abab25..201c69a8c0 100644 --- a/esphome/components/esp32/__init__.py +++ b/esphome/components/esp32/__init__.py @@ -1083,11 +1083,7 @@ def _resolve_toolchain(value: ConfigType) -> ConfigType: # CORE.toolchain instead of re-resolving it from the config dict. if CORE.toolchain is None: CORE.toolchain = value.get(CONF_TOOLCHAIN, Toolchain.ESP_IDF) - if CORE.toolchain not in (Toolchain.PLATFORMIO, Toolchain.ESP_IDF): - raise cv.Invalid( - f"Unsupported toolchain '{CORE.toolchain.value}' for ESP32. " - "Supported toolchains are 'platformio' and 'esp-idf'." - ) + cv.check_supported_toolchain("ESP32", (Toolchain.PLATFORMIO, Toolchain.ESP_IDF)) return value diff --git a/esphome/components/host/__init__.py b/esphome/components/host/__init__.py index 6f0fcb9d52..1717870238 100644 --- a/esphome/components/host/__init__.py +++ b/esphome/components/host/__init__.py @@ -36,8 +36,8 @@ CONFIG_SCHEMA = cv.All( cv.Optional(CONF_MAC_ADDRESS, default="98:35:69:ab:f6:79"): cv.mac_address, } ), - set_core_data, cv.require_platformio_toolchain("host"), + set_core_data, ) diff --git a/esphome/components/nrf52/__init__.py b/esphome/components/nrf52/__init__.py index 2328d444f7..fe0c1a12de 100644 --- a/esphome/components/nrf52/__init__.py +++ b/esphome/components/nrf52/__init__.py @@ -128,11 +128,7 @@ def set_core_data(config: ConfigType) -> ConfigType: def _resolve_toolchain(config: ConfigType) -> ConfigType: if CORE.toolchain is None: CORE.toolchain = config.get(CONF_TOOLCHAIN, Toolchain.SDK_NRF) - if CORE.toolchain not in (Toolchain.PLATFORMIO, Toolchain.SDK_NRF): - raise cv.Invalid( - f"Unsupported toolchain '{CORE.toolchain.value}' for nRF52. " - "Supported toolchains are 'platformio' and 'sdk-nrf'." - ) + cv.check_supported_toolchain("nRF52", (Toolchain.PLATFORMIO, Toolchain.SDK_NRF)) return config diff --git a/esphome/components/rp2/__init__.py b/esphome/components/rp2/__init__.py index 14806b26ce..dae7df26c3 100644 --- a/esphome/components/rp2/__init__.py +++ b/esphome/components/rp2/__init__.py @@ -312,8 +312,8 @@ CONFIG_SCHEMA = cv.All( ), cv.has_at_least_one_key(CONF_BOARD, CONF_VARIANT), _detect_variant, - set_core_data, cv.require_platformio_toolchain("RP2"), + set_core_data, ) diff --git a/esphome/config_validation.py b/esphome/config_validation.py index c3ee760761..009b844986 100644 --- a/esphome/config_validation.py +++ b/esphome/config_validation.py @@ -75,6 +75,7 @@ from esphome.const import ( TYPE_GIT, TYPE_LOCAL, Framework, + Toolchain, __version__ as ESPHOME_VERSION, ) from esphome.core import ( @@ -2532,6 +2533,21 @@ def platformio_version_constraint(value): return constraints +def check_supported_toolchain(platform_name: str, supported: tuple) -> None: + """Raise when the resolved ``CORE.toolchain`` is not in ``supported``. + + One message shape for every platform, so a ``--toolchain`` a platform + cannot serve always fails by name instead of silently building with a + different backend. + """ + if CORE.toolchain not in supported: + names = ", ".join(f"'{tc.value}'" for tc in supported) + raise Invalid( + f"Unsupported toolchain '{CORE.toolchain.value}' for " + f"{platform_name}. Supported: {names}." + ) + + def require_platformio_toolchain(platform_name: str): """Reject a CLI-selected toolchain other than PlatformIO. @@ -2540,15 +2556,9 @@ def require_platformio_toolchain(platform_name: str): """ def validator(config): - from esphome.const import Toolchain - if CORE.toolchain is None: CORE.toolchain = Toolchain.PLATFORMIO - if CORE.toolchain != Toolchain.PLATFORMIO: - raise Invalid( - f"Unsupported toolchain '{CORE.toolchain.value}' for " - f"{platform_name}. The only supported toolchain is 'platformio'." - ) + check_supported_toolchain(platform_name, (Toolchain.PLATFORMIO,)) return config return validator diff --git a/esphome/core/config.py b/esphome/core/config.py index be577cccbb..9fef173b48 100644 --- a/esphome/core/config.py +++ b/esphome/core/config.py @@ -557,9 +557,9 @@ def _add_library_str(lib: str) -> None: @coroutine_with_priority(CoroPriority.FINAL) async def _add_platformio_options(pio_options: dict[str, str | list[str]]) -> None: - if CORE.using_toolchain_esp_idf or ( - CORE.using_toolchain_arduino and CORE.is_esp8266 - ): + # Every platform's toolchain validation rejects values it cannot serve, + # so using_toolchain_arduino by itself implies the native ESP8266 build. + if CORE.using_toolchain_esp_idf or CORE.using_toolchain_arduino: # The native builds don't read platformio.ini; honor the options # with a native equivalent and warn about the rest, which would # otherwise be silently ignored.