Arduino core 3.3.5

This commit is contained in:
Jason2866
2025-12-19 16:03:25 +01:00
parent db09865583
commit 879780c5a9
22 changed files with 610 additions and 72 deletions
+4
View File
@@ -1,6 +1,10 @@
dependencies:
# Required IDF version
idf: ">=5.1"
espressif/cmake_utilities:
version: "0.*"
rules:
- if: "target == esp32c2"
espressif/fb_gfx:
version: "master"
path: components/fb_gfx
+79 -9
View File
@@ -73,8 +73,9 @@ def get_platform_default_threshold(mcu):
"esp32s2": 32000, # ESP32-S2
"esp32s3": 32766, # ESP32-S3
"esp32c3": 32000, # ESP32-C3
"esp32c2": 32000, # ESP32-C2
"esp32c2": 31600, # ESP32-C2
"esp32c6": 31600, # ESP32-C6
"esp32c61": 31600, # ESP32-C61
"esp32h2": 32000, # ESP32-H2
"esp32p4": 32000, # ESP32-P4
}
@@ -110,6 +111,7 @@ def validate_threshold(threshold, mcu):
"esp32s3": {"min": 30000, "max": 32767},
"esp32p4": {"min": 30000, "max": 32767},
"esp32c6": {"min": 30000, "max": 32767},
"esp32c61": {"min": 30000, "max": 32767},
"esp32h2": {"min": 30000, "max": 32767},
}
@@ -236,7 +238,7 @@ def get_threshold_info(env, config, current_env_section):
Returns:
dict: Information about threshold configuration
"""
mcu = env.BoardConfig().get("build.mcu", "esp32")
mcu = env.BoardConfig().get("build.mcu", "esp32").lower()
setting_name = "custom_include_path_length_threshold"
info = {
@@ -285,9 +287,10 @@ def get_threshold_info(env, config, current_env_section):
# Cache class for frequently used paths
class PathCache:
def __init__(self, platform, mcu):
def __init__(self, platform, mcu, chip_variant):
self.platform = platform
self.mcu = mcu
self.chip_variant = chip_variant
self._framework_dir = None
self._framework_lib_dir = None
self._sdk_dir = None
@@ -310,7 +313,7 @@ class PathCache:
def sdk_dir(self):
if self._sdk_dir is None:
self._sdk_dir = fs.to_unix_path(
str(Path(self.framework_lib_dir) / self.mcu / "include")
str(Path(self.framework_lib_dir) / self.chip_variant / "include")
)
return self._sdk_dir
@@ -520,9 +523,11 @@ board = env.BoardConfig()
# Cached values
mcu = board.get("build.mcu", "esp32")
chip_variant = env.BoardConfig().get("build.chip_variant", "").lower()
chip_variant = chip_variant if chip_variant else mcu
pioenv = env["PIOENV"]
project_dir = env.subst("$PROJECT_DIR")
path_cache = PathCache(platform, mcu)
path_cache = PathCache(platform, mcu, chip_variant)
current_env_section = f"env:{pioenv}"
# Board configuration
@@ -532,9 +537,7 @@ flag_custom_sdkconfig = False
flag_custom_component_remove = False
flag_custom_component_add = False
flag_lib_ignore = False
if mcu == "esp32c2":
flag_custom_sdkconfig = True
flag_lto = False
# pio lib_ignore check
if config.has_option(current_env_section, "lib_ignore"):
@@ -598,6 +601,10 @@ if flag_custom_sdkconfig:
if has_unicore_flags():
build_unflags += " -ustart_app_other_cores"
# Check for enabling LTO for Arduino HybridCompile part by unflagging -fno-lto
if '-fno-lto' in build_unflags:
flag_lto = True
new_build_unflags = build_unflags.split()
env.Replace(BUILD_UNFLAGS=new_build_unflags)
@@ -916,13 +923,76 @@ if ("arduino" in pioframework and "espidf" not in pioframework and
from component_manager import ComponentManager
component_manager = ComponentManager(env)
component_manager.handle_component_settings()
# Handle LTO flags if flag_lto is set
if flag_lto:
# First remove existing -fno-lto flags, then add LTO flags
component_manager.remove_no_lto_flags()
component_manager.add_lto_flags()
silent_action = env.Action(component_manager.restore_pioarduino_build_py)
# silence scons command output
silent_action.strfunction = lambda target, source, env: ''
env.AddPostAction("checkprogsize", silent_action)
if IS_WINDOWS:
env.AddBuildMiddleware(smart_include_length_shorten)
# Integrate smart_include_length_shorten with existing middlewares
existing_middlewares = list(env.get("__PIO_BUILD_MIDDLEWARES", []))
if existing_middlewares:
# Wrap user middlewares to work together with smart_include_length_shorten
def integrated_middleware(env, node):
# Create a custom env.Object wrapper that intercepts calls
original_object = env.Object
result_holder = {"result": None, "called": False}
def custom_object_wrapper(_node, **kwargs):
# User middleware called env.Object - capture it
result_holder["called"] = True
result_holder["kwargs"] = kwargs
# Don't actually compile yet, just return a marker
return None
# Temporarily replace env.Object
env.Object = custom_object_wrapper
# Call user middleware - it will call our wrapper
for middleware_func, _ in existing_middlewares:
middleware_func(env, node)
# Restore original env.Object
env.Object = original_object
# Now compile with smart_include_length_shorten
if result_holder["called"] and result_holder.get("kwargs"):
# User middleware wants custom flags - merge them
user_kwargs = result_holder["kwargs"]
# Temporarily apply user's custom flags to env
old_values = {}
for key, value in user_kwargs.items():
if key in env:
old_values[key] = env[key]
env[key] = value
# Compile with smart_include_length_shorten
result = smart_include_length_shorten(env, node)
# Restore original env values
for key, value in old_values.items():
env[key] = value
return result
else:
# No custom flags, just use smart_include_length_shorten
return smart_include_length_shorten(env, node)
# Replace all middlewares with the integrated one
env["__PIO_BUILD_MIDDLEWARES"] = []
env.AddBuildMiddleware(integrated_middleware)
else:
# No user middlewares, just add smart_include_length_shorten
env.AddBuildMiddleware(smart_include_length_shorten)
build_script_path = str(Path(FRAMEWORK_DIR) / "tools" / "pioarduino-build.py")
SConscript(build_script_path)
+109 -1
View File
@@ -45,6 +45,8 @@ class ComponentManagerConfig:
self.board = env.BoardConfig()
# Extract MCU type from board configuration, defaulting to esp32
self.mcu = self.board.get("build.mcu", "esp32").lower()
chip_variant = self.board.get("build.chip_variant", "").lower()
self.chip_variant = chip_variant if chip_variant else self.mcu
# Get project source directory path
self.project_src_dir = env.subst("$PROJECT_SRC_DIR")
@@ -74,7 +76,7 @@ class ComponentManagerConfig:
"""
if self._arduino_libs_mcu is None:
ald = self.platform.get_package_dir("framework-arduinoespressif32-libs")
self._arduino_libs_mcu = str(Path(ald) / self.mcu) if ald else ""
self._arduino_libs_mcu = str(Path(ald) / self.chip_variant) if ald else ""
return self._arduino_libs_mcu
@@ -1271,3 +1273,109 @@ class ComponentManager:
session, useful for build reporting and debugging.
"""
self.logger.print_changes_summary()
def remove_no_lto_flags(self) -> bool:
"""
Remove all -fno-lto flags from pioarduino-build.py.
Removes all occurrences of -fno-lto from CCFLAGS, CFLAGS, CXXFLAGS,
and LINKFLAGS in the Arduino build script.
Returns:
bool: True if successful, False otherwise
"""
build_py_path = str(Path(self.config.arduino_libs_mcu) / "pioarduino-build.py")
if not os.path.exists(build_py_path):
print(f"Warning: pioarduino-build.py not found at {build_py_path}")
return False
try:
with open(build_py_path, 'r', encoding='utf-8') as f:
content = f.read()
# Remove all -fno-lto flags
modified_content = re.sub(r'["\']?-fno-lto["\']?,?\s*', '', content)
# Clean up any resulting empty strings or double commas
modified_content = re.sub(r',\s*,', ',', modified_content)
modified_content = re.sub(r'\[\s*,', '[', modified_content)
modified_content = re.sub(r',\s*\]', ']', modified_content)
with open(build_py_path, 'w', encoding='utf-8') as f:
f.write(modified_content)
return True
except (IOError, OSError) as e:
print(f"Error removing -fno-lto flags: {e}")
return False
def add_lto_flags(self) -> bool:
"""
Add LTO flags to pioarduino-build.py.
Adds -flto=auto to CCFLAGS, CFLAGS, CXXFLAGS and -flto to LINKFLAGS
in the Arduino build script. Flags are inserted right after the opening bracket.
Returns:
bool: True if successful, False otherwise
"""
build_py_path = str(Path(self.config.arduino_libs_mcu) / "pioarduino-build.py")
if not os.path.exists(build_py_path):
print(f"Warning: pioarduino-build.py not found at {build_py_path}")
return False
try:
with open(build_py_path, 'r', encoding='utf-8') as f:
content = f.read()
modified = False
# Add -flto=auto to CCFLAGS right after the opening bracket
if 'CCFLAGS=[' in content:
ccflags_start = content.find('CCFLAGS=[')
ccflags_section_start = ccflags_start + len('CCFLAGS=[')
content = (content[:ccflags_section_start] +
'\n "-flto=auto",' +
content[ccflags_section_start:])
modified = True
# Add -flto=auto to CFLAGS right after the opening bracket
if 'CFLAGS=[' in content:
cflags_start = content.find('CFLAGS=[')
cflags_section_start = cflags_start + len('CFLAGS=[')
content = (content[:cflags_section_start] +
'\n "-flto=auto",' +
content[cflags_section_start:])
modified = True
# Add -flto=auto to CXXFLAGS right after the opening bracket
if 'CXXFLAGS=[' in content:
cxxflags_start = content.find('CXXFLAGS=[')
cxxflags_section_start = cxxflags_start + len('CXXFLAGS=[')
content = (content[:cxxflags_section_start] +
'\n "-flto=auto",' +
content[cxxflags_section_start:])
modified = True
# Add -flto to LINKFLAGS right after the opening bracket
if 'LINKFLAGS=[' in content:
linkflags_start = content.find('LINKFLAGS=[')
linkflags_section_start = linkflags_start + len('LINKFLAGS=[')
content = (content[:linkflags_section_start] +
'\n "-flto",' +
content[linkflags_section_start:])
modified = True
if modified:
with open(build_py_path, 'w', encoding='utf-8') as f:
f.write(content)
print("*** Added LTO flags for Arduino compile ***")
return True
except (IOError, OSError) as e:
print(f"Error adding LTO flags: {e}")
return False
+60 -30
View File
@@ -76,10 +76,14 @@ os.environ["IDF_COMPONENT_OVERWRITE_MANAGED_COMPONENTS"] = "1"
config = env.GetProjectConfig()
board = env.BoardConfig()
pio_orig_frwrk = env.GetProjectOption("framework")
mcu = board.get("build.mcu", "esp32")
chip_variant = board.get("build.chip_variant", "").lower()
chip_variant = chip_variant if chip_variant else mcu
flash_speed = board.get("build.f_flash", "40000000L")
flash_frequency = str(flash_speed.replace("000000L", ""))
flash_mode = board.get("build.flash_mode", "dio")
boot_mode = board.get("build.boot", None)
idf_variant = mcu.lower()
flag_custom_sdkonfig = False
flag_custom_component_add = False
@@ -178,17 +182,29 @@ if "arduino" in env.subst("$PIOFRAMEWORK"):
ARDUINO_FRMWRK_LIB_DIR_PATH = arduino_lib_dir.resolve()
ARDUINO_FRMWRK_LIB_DIR = str(ARDUINO_FRMWRK_LIB_DIR_PATH)
if mcu == "esp32c2":
ARDUINO_FRMWRK_C2_LIB_DIR = str(ARDUINO_FRMWRK_LIB_DIR_PATH / mcu)
if mcu == "esp32c2" and "espidf" not in pio_orig_frwrk:
ARDUINO_FRMWRK_C2_LIB_DIR = str(ARDUINO_FRMWRK_LIB_DIR_PATH / chip_variant)
if not os.path.exists(ARDUINO_FRMWRK_C2_LIB_DIR):
_arduino_c2_dir = platform.get_package_dir("framework-arduino-c2-skeleton-lib")
if not _arduino_c2_dir:
sys.stderr.write("Error: Missing framework-arduino-c2-skeleton-lib package\n")
env.Exit(1)
arduino_c2_dir = Path(_arduino_c2_dir)
ARDUINO_C2_DIR = str(arduino_c2_dir / mcu)
ARDUINO_C2_DIR = str(arduino_c2_dir / chip_variant)
shutil.copytree(ARDUINO_C2_DIR, ARDUINO_FRMWRK_C2_LIB_DIR, dirs_exist_ok=True)
arduino_libs_mcu = str(ARDUINO_FRMWRK_LIB_DIR_PATH / mcu)
if mcu == "esp32c61" and "espidf" not in pio_orig_frwrk:
ARDUINO_FRMWRK_C61_LIB_DIR = str(ARDUINO_FRMWRK_LIB_DIR_PATH / chip_variant)
if not os.path.exists(ARDUINO_FRMWRK_C61_LIB_DIR):
_arduino_c61_dir = platform.get_package_dir("framework-arduino-c61-skeleton-lib")
if not _arduino_c61_dir:
sys.stderr.write("Error: Missing framework-arduino-c61-skeleton-lib package\n")
env.Exit(1)
arduino_c61_dir = Path(_arduino_c61_dir)
ARDUINO_C61_DIR = str(arduino_c61_dir / chip_variant)
shutil.copytree(ARDUINO_C61_DIR, ARDUINO_FRMWRK_C61_LIB_DIR, dirs_exist_ok=True)
arduino_libs_mcu = str(ARDUINO_FRMWRK_LIB_DIR_PATH / chip_variant)
BUILD_DIR = env.subst("$BUILD_DIR")
PROJECT_DIR = env.subst("$PROJECT_DIR")
@@ -218,6 +234,10 @@ if config.has_option("env:"+env["PIOENV"], "custom_sdkconfig"):
if "espidf.custom_sdkconfig" in board:
flag_custom_sdkonfig = True
# Disable HybridCompile for espidf and arduino, espidf projects
# HybridCompile is always "framework = arduino" !
if "espidf" in pio_orig_frwrk:
flag_custom_sdkonfig = False
# Check for board-specific configurations that require sdkconfig generation
def has_board_specific_config():
@@ -336,11 +356,18 @@ def HandleArduinoIDFsettings(env):
flash_memory_type, psram_memory_type = parts
else:
flash_memory_type = memory_type
# Check for additional flash configuration indicators
boot_mode = board.get("build", {}).get("boot", None)
flash_mode = board.get("build", {}).get("flash_mode", None)
# Add flash mode to sdkconfig
if flash_mode:
flash_mode_lower = flash_mode.lower()
board_config_flags.append(f"CONFIG_ESPTOOLPY_FLASHMODE_{flash_mode.upper()}=y")
# Disable other flash mode options
flash_modes = ["qio", "qout", "dio", "dout"]
for mode in flash_modes:
if mode != flash_mode_lower:
board_config_flags.append(f"# CONFIG_ESPTOOLPY_FLASHMODE_{mode.upper()} is not set")
# Override flash_memory_type if boot mode indicates OPI
if boot_mode == "opi" or flash_mode in ["dout", "opi"]:
if not flash_memory_type or flash_memory_type.lower() != "opi":
@@ -2577,24 +2604,24 @@ if os.path.isdir(ulp_dir) and os.listdir(ulp_dir) and mcu not in ("esp32c2", "es
if ("arduino" in env.subst("$PIOFRAMEWORK")) and ("espidf" not in env.subst("$PIOFRAMEWORK")):
def idf_lib_copy(source, target, env):
def _replace_move(src, dst):
def _replace_copy(src, dst):
dst_p = Path(dst)
dst_p.parent.mkdir(parents=True, exist_ok=True)
try:
os.remove(dst)
except FileNotFoundError:
shutil.copy2(src, dst)
except (OSError, IOError):
# Gracefully handle missing source files (e.g., PSRAM libs in non-PSRAM builds)
# This is expected when copying variant-specific libraries
pass
try:
os.replace(src, dst)
except OSError:
shutil.move(src, dst)
except Exception as e:
print(f"Warning: Failed to copy {src} to {dst}: {e}")
env_build = str(Path(env["PROJECT_BUILD_DIR"]) / env["PIOENV"])
sdkconfig_h_path = str(Path(env_build) / "config" / "sdkconfig.h")
arduino_libs = str(Path(ARDUINO_FRMWRK_LIB_DIR))
lib_src = str(Path(env_build) / "esp-idf")
lib_dst = str(Path(arduino_libs) / mcu / "lib")
ld_dst = str(Path(arduino_libs) / mcu / "ld")
mem_var = str(Path(arduino_libs) / mcu / board.get("build.arduino.memory_type", (board.get("build.flash_mode", "dio") + "_qspi")))
lib_dst = str(Path(arduino_libs) / chip_variant / "lib")
ld_dst = str(Path(arduino_libs) / chip_variant / "ld")
mem_var = str(Path(arduino_libs) / chip_variant / board.get("build.arduino.memory_type", (board.get("build.flash_mode", "dio") + "_qspi")))
# Ensure destinations exist
for d in (lib_dst, ld_dst, mem_var, str(Path(mem_var) / "include")):
Path(d).mkdir(parents=True, exist_ok=True)
@@ -2606,22 +2633,25 @@ if ("arduino" in env.subst("$PIOFRAMEWORK")) and ("espidf" not in env.subst("$PI
if file.strip().endswith(".a"):
shutil.copyfile(file, str(Path(lib_dst) / file.split(os.path.sep)[-1]))
_replace_move(str(Path(lib_dst) / "libspi_flash.a"), str(Path(mem_var) / "libspi_flash.a"))
_replace_move(str(Path(env_build) / "memory.ld"), str(Path(ld_dst) / "memory.ld"))
_replace_copy(str(Path(lib_dst) / "libspi_flash.a"), str(Path(mem_var) / "libspi_flash.a"))
_replace_copy(str(Path(env_build) / "memory.ld"), str(Path(ld_dst) / "memory.ld"))
if mcu == "esp32s3":
_replace_move(str(Path(lib_dst) / "libesp_psram.a"), str(Path(mem_var) / "libesp_psram.a"))
_replace_move(str(Path(lib_dst) / "libesp_system.a"), str(Path(mem_var) / "libesp_system.a"))
_replace_move(str(Path(lib_dst) / "libfreertos.a"), str(Path(mem_var) / "libfreertos.a"))
_replace_move(str(Path(lib_dst) / "libbootloader_support.a"), str(Path(mem_var) / "libbootloader_support.a"))
_replace_move(str(Path(lib_dst) / "libesp_hw_support.a"), str(Path(mem_var) / "libesp_hw_support.a"))
_replace_move(str(Path(lib_dst) / "libesp_lcd.a"), str(Path(mem_var) / "libesp_lcd.a"))
_replace_copy(str(Path(lib_dst) / "libesp_psram.a"), str(Path(mem_var) / "libesp_psram.a"))
_replace_copy(str(Path(lib_dst) / "libesp_system.a"), str(Path(mem_var) / "libesp_system.a"))
_replace_copy(str(Path(lib_dst) / "libfreertos.a"), str(Path(mem_var) / "libfreertos.a"))
_replace_copy(str(Path(lib_dst) / "libbootloader_support.a"), str(Path(mem_var) / "libbootloader_support.a"))
_replace_copy(str(Path(lib_dst) / "libesp_hw_support.a"), str(Path(mem_var) / "libesp_hw_support.a"))
_replace_copy(str(Path(lib_dst) / "libesp_lcd.a"), str(Path(mem_var) / "libesp_lcd.a"))
shutil.copyfile(sdkconfig_h_path, str(Path(mem_var) / "include" / "sdkconfig.h"))
if not bool(os.path.isfile(str(Path(arduino_libs) / mcu / "sdkconfig.orig"))):
shutil.move(str(Path(arduino_libs) / mcu / "sdkconfig"), str(Path(arduino_libs) / mcu / "sdkconfig.orig"))
shutil.copyfile(str(Path(env.subst("$PROJECT_DIR")) / ("sdkconfig." + env["PIOENV"])), str(Path(arduino_libs) / mcu / "sdkconfig"))
if not bool(os.path.isfile(str(Path(arduino_libs) / chip_variant / "sdkconfig.orig"))):
shutil.move(str(Path(arduino_libs) / chip_variant / "sdkconfig"), str(Path(arduino_libs) / chip_variant / "sdkconfig.orig"))
shutil.copyfile(str(Path(env.subst("$PROJECT_DIR")) / ("sdkconfig." + env["PIOENV"])), str(Path(arduino_libs) / chip_variant / "sdkconfig"))
shutil.copyfile(str(Path(env.subst("$PROJECT_DIR")) / ("sdkconfig." + env["PIOENV"])), str(Path(arduino_libs) / "sdkconfig"))
try:
# clean env build folder to avoid issues with following Arduino build
shutil.rmtree(env_build)
Path(env_build).mkdir(parents=True, exist_ok=True)
os.remove(str(Path(env.subst("$PROJECT_DIR")) / "dependencies.lock"))
os.remove(str(Path(env.subst("$PROJECT_DIR")) / "CMakeLists.txt"))
except FileNotFoundError:
+1 -1
View File
@@ -38,7 +38,7 @@ if sys.version_info < (3, 10):
github_actions = bool(os.getenv("GITHUB_ACTIONS"))
PLATFORMIO_URL_VERSION_RE = re.compile(
r'/v?(\d+\.\d+\.\d+(?:[.-]\w+)?(?:\.\d+)?)(?:\.(?:zip|tar\.gz|tar\.bz2))?$',
r'/v?(\d+\.\d+\.\d+(?:[.-](?:alpha|beta|rc|dev|post|pre)\d*)?(?:\.\d+)?)(?:\.(?:zip|tar\.gz|tar\.bz2))?$',
re.IGNORECASE,
)