diff --git a/esphome/components/api/__init__.py b/esphome/components/api/__init__.py index 53ad0fe5d7..a10bfd3418 100644 --- a/esphome/components/api/__init__.py +++ b/esphome/components/api/__init__.py @@ -14,7 +14,7 @@ from esphome.components.noise import ( # noqa: F401 encryption_schema, validate_encryption_key, ) -from esphome.config_helpers import get_logger_level +from esphome.config_helpers import filter_source_files_from_defines, get_logger_level import esphome.config_validation as cv from esphome.const import ( CONF_ACTION, @@ -835,11 +835,20 @@ async def api_connected_to_code( return var +# user_services.cpp is only needed when user defined actions exist; the +# frame helpers are fully #ifdef'd on the protocol defines set in to_code +# (both are set when encryption is configured without a key). +_define_filter = filter_source_files_from_defines( + { + "user_services.cpp": "USE_API_USER_DEFINED_ACTIONS", + "api_frame_helper_noise.cpp": "USE_API_NOISE", + "api_frame_helper_plaintext.cpp": "USE_API_PLAINTEXT", + } +) + + def FILTER_SOURCE_FILES() -> list[str]: - """Filter out api_pb2_dump.cpp when proto message dumping is not enabled, - user_services.cpp when no services are defined, and protocol-specific - implementations based on encryption configuration.""" - files_to_filter: list[str] = [] + files_to_filter = _define_filter() # api_pb2_dump.cpp is only needed when HAS_PROTO_MESSAGE_DUMP is defined # This is a particularly large file that still needs to be opened and read @@ -850,21 +859,4 @@ def FILTER_SOURCE_FILES() -> list[str]: if get_logger_level() != "VERY_VERBOSE": files_to_filter.append("api_pb2_dump.cpp") - # user_services.cpp is only needed when services are defined - config = CORE.config.get(DOMAIN, {}) - if config and not config.get(CONF_ACTIONS) and not config[CONF_CUSTOM_SERVICES]: - files_to_filter.append("user_services.cpp") - - # Filter protocol-specific implementations based on encryption configuration - encryption_config = config.get(CONF_ENCRYPTION) if config else None - - # If encryption is not configured at all, we only need plaintext - if encryption_config is None: - files_to_filter.append("api_frame_helper_noise.cpp") - # If encryption is configured with a key, we only need noise - elif encryption_config.get(CONF_KEY): - files_to_filter.append("api_frame_helper_plaintext.cpp") - # If encryption is configured but no key is provided, we need both - # (this allows a plaintext client to provide a noise key) - return files_to_filter diff --git a/esphome/components/ethernet/__init__.py b/esphome/components/ethernet/__init__.py index cd5904f501..a44a609d3c 100644 --- a/esphome/components/ethernet/__init__.py +++ b/esphome/components/ethernet/__init__.py @@ -10,7 +10,10 @@ from esphome.components.network import ( get_priority_interfaces_from_full_config, ip_address_literal, ) -from esphome.config_helpers import filter_source_files_from_platform +from esphome.config_helpers import ( + filter_source_files_from_defines, + filter_source_files_from_platform, +) import esphome.config_validation as cv from esphome.const import ( CONF_ADDRESS, @@ -821,8 +824,15 @@ _platform_filter = filter_source_files_from_platform( ) +# The custom W5500 SPI driver is fully #ifdef'd on USE_ESP32 and +# USE_ETHERNET_W5500 (the platform filter map above handles non-ESP32). +_define_filter = filter_source_files_from_defines( + {"w5500_custom_spi.cpp": "USE_ETHERNET_W5500"} +) + + def _filter_source_files() -> list[str]: - excluded = _platform_filter() + excluded = _platform_filter() + _define_filter() eth_data = CORE.data.get(KEY_ETHERNET, {}) eth_type = eth_data.get(ETHERNET_TYPE_KEY) # Only compile the custom JL1101 driver when JL1101 is configured @@ -836,12 +846,8 @@ def _filter_source_files() -> list[str]: # to avoid shadowing. Native IDF builds always need the custom driver. if cv.Version(5, 4, 2) <= idf_version() < cv.Version(6, 0, 0): excluded.append("esp_eth_phy_jl1101.c") - # The custom W5500 SPI driver is fully #ifdef'd on USE_ESP32 and - # USE_ETHERNET_W5500 (the platform filter map above handles non-ESP32); - # skip it entirely for the other ethernet types. - if eth_type != "W5500": - excluded.append("w5500_custom_spi.cpp") - return excluded + # The platform and define filters can both name the same file + return list(dict.fromkeys(excluded)) FILTER_SOURCE_FILES = _filter_source_files diff --git a/esphome/components/socket/__init__.py b/esphome/components/socket/__init__.py index cd002d9eb0..895fc8d03a 100644 --- a/esphome/components/socket/__init__.py +++ b/esphome/components/socket/__init__.py @@ -4,6 +4,7 @@ from enum import StrEnum import logging import esphome.codegen as cg +from esphome.config_helpers import filter_source_files_from_defines import esphome.config_validation as cv from esphome.core import CORE @@ -181,16 +182,12 @@ async def to_code(config): cg.add_build_flag("-DUSE_LWIP_FAST_SELECT") -def FILTER_SOURCE_FILES() -> list[str]: - """Return list of socket implementation files that aren't selected by the user.""" - impl = CORE.config["socket"][CONF_IMPLEMENTATION] - - # Build list of files to exclude based on selected implementation - excluded = [] - if impl != IMPLEMENTATION_LWIP_TCP: - excluded.append("lwip_raw_tcp_impl.cpp") - if impl != IMPLEMENTATION_BSD_SOCKETS: - excluded.append("bsd_sockets_impl.cpp") - if impl != IMPLEMENTATION_LWIP_SOCKETS: - excluded.append("lwip_sockets_impl.cpp") - return excluded +# Each implementation file is fully #ifdef'd on the define set in to_code +# for the selected implementation. +FILTER_SOURCE_FILES = filter_source_files_from_defines( + { + "lwip_raw_tcp_impl.cpp": "USE_SOCKET_IMPL_LWIP_TCP", + "bsd_sockets_impl.cpp": "USE_SOCKET_IMPL_BSD_SOCKETS", + "lwip_sockets_impl.cpp": "USE_SOCKET_IMPL_LWIP_SOCKETS", + } +)