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
Section titled “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
Section titled “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
Section titled “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
Section titled “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
Section titled “Migration Guide”External Components: Add cg.add_library() Calls
Section titled “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__.pyimport esphome.codegen as cgfrom 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.hThe None version parameter tells ESPHome to use the version bundled with the Arduino framework.
Users: Add Libraries in YAML
Section titled “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 lambdasLibraries Already Enabled by Built-in Components
Section titled “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
Section titled “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
Section titled “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 explicitlySupporting Multiple ESPHome Versions
Section titled “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
Section titled “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 directoryfatal error: Preferences.h: No such file or directoryfatal error: Wire.h: No such file or directoryThe fix is to add the corresponding cg.add_library() call in your Python code.
Timeline
Section titled “Timeline”- ESPHome 2026.2.0 (February 2026): Arduino libraries disabled by default
- No deprecation period — behavior changed directly
Finding Code That Needs Updates
Section titled “Finding Code That Needs Updates”# Find Arduino library includes in your C++ codegrep -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 librariesgrep -rn 'add_library' your_component/Questions?
Section titled “Questions?”If you have questions about migrating your external component, please ask in:
- ESPHome Discord - #devs channel
- ESPHome GitHub Discussions
Related Documentation
Section titled “Related Documentation”Copyright © 2026 ESPHome - A project from the Open Home Foundation
Comments
Feel free to leave a comment here to discuss this post with 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.