ESP32 Arduino Selective Compilation: Libraries Disabled by Default
ESP32 Arduino builds now disable all Arduino libraries by default. ESPHome uses ESP-IDF APIs directly for WiFi, networking, and BLE, so most Arduino libraries were compiled and linked but never called. External components that use Arduino libraries must explicitly enable them via cg.add_library().
This is a breaking change for external components in ESPHome 2026.2.0 and later.
Background
PR #13623: Reduce Arduino build size by 44% and build time by 36%
Previously, the entire Arduino framework with all its libraries was compiled and linked into every ESP32 Arduino build, even though ESPHome uses ESP-IDF APIs directly for most functionality. This wasted significant flash, RAM, and compile time.
This PR enables CONFIG_ARDUINO_SELECTIVE_COMPILATION and disables all Arduino libraries by default. It also stubs out unused IDF managed components that Arduino's idf_component.yml would otherwise pull in.
Results
| Metric | Before | After | Savings |
|---|---|---|---|
| Flash | 1,053,543 bytes (57.4%) | 588,647 bytes (32.1%) | 464,896 bytes (44% reduction) |
| Static RAM | 39,124 bytes (11.9%) | 19,700 bytes (6.0%) | 19,424 bytes (50% reduction) |
| Build time | 56.5 sec | 36.3 sec | 36% faster |
What's Changing
All Arduino libraries are now disabled by default on ESP32 Arduino builds. The full list of disabled libraries includes: WiFi, Network, BLE, SPI, Wire, Preferences, HTTPClient, ESPmDNS, Ethernet, FS, SD, Update, WebServer, and many more.
ESPHome's built-in components already call cg.add_library() for any Arduino libraries they need, so they are automatically re-enabled. External components that use Arduino libraries must do the same.
The mechanism is automatic — when you call cg.add_library("WiFi", None), ESPHome:
- Enables the
WiFiArduino library for compilation - Enables any Arduino library dependencies (e.g.,
WiFidepends onNetwork) - Un-stubs any IDF managed components that the library requires
Who This Affects
External components that:
- Use Arduino library APIs (e.g.,
WiFi.h,Wire.h,SPI.h,Preferences.h) in C++ code without callingcg.add_library()in their Pythonto_code() - Rely on Arduino libraries being implicitly available
Users who:
- Call Arduino library APIs directly in lambdas (e.g.,
WiFi.localIP(),Preferences)
Standard YAML configurations are not affected — ESPHome's built-in components automatically enable the libraries they need.
Migration Guide
External Components: Add cg.add_library() Calls
If your external component uses Arduino library APIs, add the corresponding cg.add_library() call in your to_code():
# In your component's __init__.py
import esphome.codegen as cg
from esphome.core import CORE
async def to_code(config):
# Enable the Arduino libraries your C++ code uses directly
if CORE.is_esp32 and CORE.using_arduino:
cg.add_library("Preferences", None) # For Preferences.h
cg.add_library("FS", None) # For FS.h
The None version parameter tells ESPHome to use the version bundled with the Arduino framework.
Users: Add Libraries in YAML
If you call Arduino library APIs directly in lambdas:
esphome:
libraries:
- WiFi # For WiFi.h APIs in lambdas
- Preferences # For Preferences.h APIs in lambdas
Libraries Already Enabled by Built-in Components
Many Arduino libraries are already enabled by ESPHome's built-in components. If your external component lists any of these in its DEPENDENCIES, the library is already available — you do not need to add it again:
| Library | Enabled by ESPHome Component |
|---|---|
WiFi |
wifi |
Wire |
i2c |
SPI |
spi |
HTTPClient |
http_request |
DNSServer |
captive_portal |
NetworkClientSecure |
i2s_audio (media_player) |
Libraries You May Need to Add
These libraries are not enabled by any commonly-used built-in component. If your external component uses them directly, you must add cg.add_library():
| Library | Header | Use Case |
|---|---|---|
Preferences |
Preferences.h |
NVS key-value storage |
BLE |
BLE*.h |
Bluetooth Low Energy (Arduino API) |
BluetoothSerial |
BluetoothSerial.h |
Classic Bluetooth serial |
FS |
FS.h |
Filesystem base class |
SD / SD_MMC |
SD.h / SD_MMC.h |
SD card access |
When You Still Need to Add Already-Enabled Libraries
If your external component uses an Arduino library API without depending on the corresponding ESPHome component, you must add the library yourself. For example, if your component includes WiFi.h directly but does not list wifi in DEPENDENCIES:
DEPENDENCIES = [] # No wifi dependency
async def to_code(config):
if CORE.is_esp32 and CORE.using_arduino:
cg.add_library("WiFi", None) # Must add explicitly
Supporting Multiple ESPHome Versions
The cg.add_library() call is safe on all ESPHome versions — it's a no-op for libraries that are already enabled. No version check is needed:
async def to_code(config):
# Safe on all versions - just always add it
if CORE.is_esp32 and CORE.using_arduino:
cg.add_library("WiFi", None)
On ESPHome < 2026.2.0, the library was already compiled by default, so the add_library call simply registers it in PlatformIO (which it was already). On ESPHome >= 2026.2.0, the call enables the library for selective compilation.
Compilation Errors
If your component uses a disabled Arduino library without enabling it, you'll see errors like:
fatal error: WiFi.h: No such file or directory
fatal error: Preferences.h: No such file or directory
fatal error: Wire.h: No such file or directory
The fix is to add the corresponding cg.add_library() call in your Python code.
Timeline
- ESPHome 2026.2.0 (February 2026): Arduino libraries disabled by default
- No deprecation period — behavior changed directly
Finding Code That Needs Updates
# Find Arduino library includes in your C++ code
grep -rn '#include.*<WiFi\.h>' your_component/
grep -rn '#include.*<Wire\.h>' your_component/
grep -rn '#include.*<SPI\.h>' your_component/
grep -rn '#include.*<Preferences\.h>' your_component/
grep -rn '#include.*<HTTPClient\.h>' your_component/
grep -rn '#include.*<BLE' your_component/
# Check if your Python code already adds these libraries
grep -rn 'add_library' your_component/
Questions?
If you have questions about migrating your external component, please ask in:
- ESPHome Discord - #devs channel
- ESPHome GitHub Discussions
Related Documentation
Comments
Feel free to leave a comment here to discuss this post wth others. You can ask questions, share your experience, or suggest improvements. If you have a question about a specific feature or issue, please consider using the ESPHome Discord. Stick to English and follow ESPHome's code of conduct. These comments exist on a discussion on GitHub, so you can also comment there directly if you prefer.