Skip to content

enhance esp-idf-size #188

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 2 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 4 additions & 7 deletions builder/frameworks/espidf.py
Original file line number Diff line number Diff line change
Expand Up @@ -1799,13 +1799,10 @@ def get_python_exe():
"-DSDKCONFIG=" + SDKCONFIG_PATH,
]

if "CPPDEFINES" in env:
flatten_cppdefines = env.Flatten(env['CPPDEFINES'])
if "SHOW_METRICS" in flatten_cppdefines:
# This will add the linker flag for the map file
extra_cmake_args.append(
f'-DCMAKE_EXE_LINKER_FLAGS=-Wl,-Map={os.path.join(BUILD_DIR, env.subst("$PROGNAME") + ".map")}'
)
# This will add the linker flag for the map file
extra_cmake_args.append(
f'-DCMAKE_EXE_LINKER_FLAGS=-Wl,-Map={os.path.join(BUILD_DIR, env.subst("$PROGNAME") + ".map")}'
)

# Add any extra args from board config
extra_cmake_args += click.parser.split_arg_string(board.get("build.cmake_extra_args", ""))
Expand Down
91 changes: 77 additions & 14 deletions builder/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -360,28 +360,66 @@ def check_lib_archive_exists():


def firmware_metrics(target, source, env):
"""
Custom target to run esp-idf-size with support for command line parameters
Usage: pio run -t metrics -- [esp-idf-size arguments]
"""
if terminal_cp != "utf-8":
print("Firmware metrics can not be shown. Set the terminal codepage to \"utf-8\"")
return

map_file = os.path.join(env.subst("$BUILD_DIR"), env.subst("$PROGNAME") + ".map")
if not os.path.isfile(map_file):
# map file can be in project dir
map_file = os.path.join(get_project_dir(), env.subst("$PROGNAME") + ".map")

if os.path.isfile(map_file):
try:
import subprocess
python_exe = env.subst("$PYTHONEXE")
run_env = os.environ.copy()
run_env["PYTHONIOENCODING"] = "utf-8"
run_env["PYTHONUTF8"] = "1"
# Show output of esp_idf_size, but suppresses the command echo
subprocess.run([
python_exe, "-m", "esp_idf_size", "--ng", map_file
], env=run_env, check=False)
except Exception:
print("Warning: Failed to run firmware metrics. Is esp-idf-size installed?")
pass
if not os.path.isfile(map_file):
print(f"Error: Map file not found: {map_file}")
print("Make sure the project is built first with 'pio run'")
return

try:
import subprocess
import sys
import shlex

cmd = [env.subst("$PYTHONEXE"), "-m", "esp_idf_size", "--ng"]

# Parameters from platformio.ini
extra_args = env.GetProjectOption("custom_esp_idf_size_args", "")
if extra_args:
cmd.extend(shlex.split(extra_args))

# Command Line Parameter, after --
cli_args = []
if "--" in sys.argv:
dash_index = sys.argv.index("--")
if dash_index + 1 < len(sys.argv):
cli_args = sys.argv[dash_index + 1:]
cmd.extend(cli_args)

# Map-file as last argument
cmd.append(map_file)

# Debug-Info if wanted
if env.GetProjectOption("custom_esp_idf_size_verbose", False):
print(f"Running command: {' '.join(cmd)}")

# Call esp-idf-size
result = subprocess.run(cmd, check=False, capture_output=False)

if result.returncode != 0:
print(f"Warning: esp-idf-size exited with code {result.returncode}")

except ImportError:
print("Error: esp-idf-size module not found.")
print("Install with: pip install esp-idf-size")
except FileNotFoundError:
print("Error: Python executable not found.")
print("Check your Python installation.")
except Exception as e:
print(f"Error: Failed to run firmware metrics: {e}")
print("Make sure esp-idf-size is installed: pip install esp-idf-size")

#
# Target: Build executable and linkable firmware or FS image
Expand Down Expand Up @@ -618,6 +656,31 @@ def firmware_metrics(target, source, env):
"Erase Flash",
)

#
# Register Custom Target
#
env.AddCustomTarget(
name="metrics",
dependencies="$BUILD_DIR/${PROGNAME}.elf",
actions=firmware_metrics,
title="Firmware Size Metrics",
description="Analyze firmware size using esp-idf-size (supports CLI args after --)",
always_build=True
)

#
# Additional Target without Build-Dependency when already compiled
#
env.AddCustomTarget(
name="metrics-only",
dependencies=None,
actions=firmware_metrics,
title="Firmware Size Metrics (No Build)",
description="Analyze firmware size without building first",
always_build=True
)


#
# Override memory inspection behavior
#
Expand Down