mirror of
https://github.com/esphome/esphome.git
synced 2025-10-27 13:13:50 +00:00
167 lines
6.0 KiB
Plaintext
167 lines
6.0 KiB
Plaintext
import os
|
|
import re
|
|
|
|
# pylint: disable=E0602
|
|
Import("env") # noqa
|
|
|
|
|
|
# Memory sizes for testing mode (allow larger builds for CI component grouping)
|
|
TESTING_IRAM_SIZE = "0x200000" # 2MB
|
|
TESTING_DRAM_SIZE = "0x200000" # 2MB
|
|
TESTING_FLASH_SIZE = "0x2000000" # 32MB
|
|
|
|
|
|
def patch_segment_size(content, segment_name, new_size, label):
|
|
"""Patch a memory segment's length in linker script.
|
|
|
|
Args:
|
|
content: Linker script content
|
|
segment_name: Name of the segment (e.g., 'iram1_0_seg')
|
|
new_size: New size as hex string (e.g., '0x200000')
|
|
label: Human-readable label for logging (e.g., 'IRAM')
|
|
|
|
Returns:
|
|
Tuple of (patched_content, was_patched)
|
|
"""
|
|
# Match: segment_name : org = 0x..., len = 0x...
|
|
pattern = rf"({segment_name}\s*:\s*org\s*=\s*0x[0-9a-fA-F]+\s*,\s*len\s*=\s*)0x[0-9a-fA-F]+"
|
|
new_content = re.sub(pattern, rf"\g<1>{new_size}", content)
|
|
return new_content, new_content != content
|
|
|
|
|
|
def apply_memory_patches(content):
|
|
"""Apply IRAM, DRAM, and Flash patches to linker script content.
|
|
|
|
Args:
|
|
content: Linker script content as string
|
|
|
|
Returns:
|
|
Patched content as string
|
|
"""
|
|
patches_applied = []
|
|
|
|
# Patch IRAM (for larger code in IRAM)
|
|
content, patched = patch_segment_size(content, "iram1_0_seg", TESTING_IRAM_SIZE, "IRAM")
|
|
if patched:
|
|
patches_applied.append("IRAM")
|
|
|
|
# Patch DRAM (for larger BSS/data sections)
|
|
content, patched = patch_segment_size(content, "dram0_0_seg", TESTING_DRAM_SIZE, "DRAM")
|
|
if patched:
|
|
patches_applied.append("DRAM")
|
|
|
|
# Patch Flash (for larger code sections)
|
|
content, patched = patch_segment_size(content, "irom0_0_seg", TESTING_FLASH_SIZE, "Flash")
|
|
if patched:
|
|
patches_applied.append("Flash")
|
|
|
|
if patches_applied:
|
|
iram_mb = int(TESTING_IRAM_SIZE, 16) // (1024 * 1024)
|
|
dram_mb = int(TESTING_DRAM_SIZE, 16) // (1024 * 1024)
|
|
flash_mb = int(TESTING_FLASH_SIZE, 16) // (1024 * 1024)
|
|
print(f" Patched memory segments: {', '.join(patches_applied)} (IRAM/DRAM: {iram_mb}MB, Flash: {flash_mb}MB)")
|
|
|
|
return content
|
|
|
|
|
|
def patch_linker_script_file(filepath, description):
|
|
"""Patch a linker script file in the build directory with enlarged memory segments.
|
|
|
|
This function modifies linker scripts in the build directory only (never SDK files).
|
|
It patches IRAM, DRAM, and Flash segments to allow larger builds in testing mode.
|
|
|
|
Args:
|
|
filepath: Path to the linker script file in the build directory
|
|
description: Human-readable description for logging
|
|
|
|
Returns:
|
|
True if the file was patched, False if already patched or not found
|
|
"""
|
|
if not os.path.exists(filepath):
|
|
print(f"ESPHome: {description} not found at {filepath}")
|
|
return False
|
|
|
|
print(f"ESPHome: Patching {description}...")
|
|
with open(filepath, "r") as f:
|
|
content = f.read()
|
|
|
|
patched_content = apply_memory_patches(content)
|
|
|
|
if patched_content != content:
|
|
with open(filepath, "w") as f:
|
|
f.write(patched_content)
|
|
print(f"ESPHome: Successfully patched {description}")
|
|
return True
|
|
else:
|
|
print(f"ESPHome: {description} already patched or no changes needed")
|
|
return False
|
|
|
|
|
|
def patch_local_linker_script(source, target, env):
|
|
"""Patch the local.eagle.app.v6.common.ld in build directory.
|
|
|
|
This patches the preprocessed linker script that PlatformIO creates in the build
|
|
directory, enlarging IRAM, DRAM, and Flash segments for testing mode.
|
|
|
|
Args:
|
|
source: SCons source nodes
|
|
target: SCons target nodes
|
|
env: SCons environment
|
|
"""
|
|
# Check if we're in testing mode
|
|
build_flags = env.get("BUILD_FLAGS", [])
|
|
testing_mode = any("-DESPHOME_TESTING_MODE" in flag for flag in build_flags)
|
|
|
|
if not testing_mode:
|
|
return
|
|
|
|
# Patch the local linker script if it exists
|
|
build_dir = env.subst("$BUILD_DIR")
|
|
ld_dir = os.path.join(build_dir, "ld")
|
|
if os.path.exists(ld_dir):
|
|
local_ld = os.path.join(ld_dir, "local.eagle.app.v6.common.ld")
|
|
if os.path.exists(local_ld):
|
|
patch_linker_script_file(local_ld, "local.eagle.app.v6.common.ld")
|
|
|
|
|
|
# Check if we're in testing mode
|
|
build_flags = env.get("BUILD_FLAGS", [])
|
|
testing_mode = any("-DESPHOME_TESTING_MODE" in flag for flag in build_flags)
|
|
|
|
if testing_mode:
|
|
# Create a custom linker script in the build directory with patched memory limits
|
|
# This allows larger IRAM/DRAM/Flash for CI component grouping tests
|
|
build_dir = env.subst("$BUILD_DIR")
|
|
ldscript = env.GetProjectOption("board_build.ldscript", "")
|
|
assert ldscript, "No linker script configured in board_build.ldscript"
|
|
|
|
framework_dir = env.PioPlatform().get_package_dir("framework-arduinoespressif8266")
|
|
assert framework_dir is not None, "Could not find framework-arduinoespressif8266 package"
|
|
|
|
# Read the original SDK linker script (read-only, SDK is never modified)
|
|
sdk_ld = os.path.join(framework_dir, "tools", "sdk", "ld", ldscript)
|
|
# Create a custom version in the build directory (isolated, temporary)
|
|
custom_ld = os.path.join(build_dir, f"testing_{ldscript}")
|
|
|
|
if os.path.exists(sdk_ld) and not os.path.exists(custom_ld):
|
|
# Read the SDK linker script
|
|
with open(sdk_ld, "r") as f:
|
|
content = f.read()
|
|
|
|
# Apply memory patches (IRAM: 2MB, DRAM: 2MB, Flash: 32MB)
|
|
patched_content = apply_memory_patches(content)
|
|
|
|
# Write the patched linker script to the build directory
|
|
with open(custom_ld, "w") as f:
|
|
f.write(patched_content)
|
|
|
|
print(f"ESPHome: Created custom linker script: {custom_ld}")
|
|
|
|
# Tell the linker to use our custom script from the build directory
|
|
assert os.path.exists(custom_ld), f"Custom linker script not found: {custom_ld}"
|
|
env.Replace(LDSCRIPT_PATH=custom_ld)
|
|
print(f"ESPHome: Using custom linker script with patched memory limits")
|
|
|
|
# Also patch local.eagle.app.v6.common.ld after PlatformIO creates it
|
|
env.AddPreAction("$BUILD_DIR/${PROGNAME}.elf", patch_local_linker_script)
|