3232# column of the table is really D/IRAM.
3333import os
3434import re
35+ import shutil
3536import sys
3637import subprocess
3738from dataclasses import dataclass
4748)
4849
4950
51+ def rmtree (path ):
52+ try :
53+ shutil .rmtree (path )
54+ except FileNotFoundError :
55+ pass
56+
57+
5058@dataclass
5159class BuildSizes :
5260 idf_ver : str
@@ -99,7 +107,7 @@ def __lt__(self, other):
99107
100108 def build_dir (self ):
101109 if self .variant :
102- return f"build-{ self .board } _ { self .variant } "
110+ return f"build-{ self .board } - { self .variant } "
103111 else :
104112 return f"build-{ self .board } "
105113
@@ -124,12 +132,23 @@ def run_make(self, target):
124132 def make_size (self ):
125133 try :
126134 size_out = self .run_make ("size" )
127- # "Used static DRAM:" or "Used stat D/IRAM:"
128- RE_DRAM = r"Used stat(?:ic)? D.*: *(\d+) bytes"
129- RE_IRAM = r"Used static IRAM: *(\d+) bytes"
135+ try :
136+ # pre IDF v5.4 size output
137+ # "Used static DRAM:" or "Used stat D/IRAM:"
138+ RE_DRAM = r"Used stat(?:ic)? D.*: *(\d+) bytes"
139+ RE_IRAM = r"Used static IRAM: *(\d+) bytes"
140+ self .dram_size = re .search (RE_DRAM , size_out ).group (1 )
141+ self .iram_size = re .search (RE_IRAM , size_out ).group (1 )
142+ except AttributeError :
143+ # IDF v5.4 size output is much nicer formatted
144+ # Note the pipes in these expressions are not the ASCII/RE |
145+ RE_DRAM = r"│ *DI?RAM *│ *(\d+)"
146+ RE_IRAM = r"│ *IRAM *│ *(\d+)"
147+ self .dram_size = re .search (RE_DRAM , size_out ).group (1 )
148+ self .iram_size = re .search (RE_IRAM , size_out ).group (1 )
149+
150+ # This line is the same on before/after versions
130151 RE_BIN = r"Total image size: *(\d+) bytes"
131- self .dram_size = re .search (RE_DRAM , size_out ).group (1 )
132- self .iram_size = re .search (RE_IRAM , size_out ).group (1 )
133152 self .bin_size = re .search (RE_BIN , size_out ).group (1 )
134153 except subprocess .CalledProcessError :
135154 self .bin_size = "build failed"
@@ -139,13 +158,26 @@ def main(do_clean):
139158 if "IDF_PATH" not in os .environ :
140159 raise RuntimeError ("IDF_PATH must be set" )
141160
161+ if not os .path .exists ("Makefile" ):
162+ raise RuntimeError (
163+ "This script must be run from the ports/esp32 directory, i.e. as ./tools/metrics_esp32.py"
164+ )
165+
166+ if "IDF_PYTHON_ENV_PATH" in os .environ :
167+ raise RuntimeError (
168+ "Run this script without any existing ESP-IDF environment active/exported."
169+ )
170+
142171 sizes = []
143172 for idf_ver in IDF_VERS :
144173 switch_ver (idf_ver )
174+ rmtree ("managed_components" )
145175 for board , variant in BUILDS :
146176 print (f"Building '{ board } '/'{ variant } '..." , file = sys .stderr )
147177 result = BuildSizes (idf_ver , board , variant )
148- result .run_make ("clean" )
178+ # Rather than running the 'clean' target, delete the build directory to avoid
179+ # environment version mismatches, etc.
180+ rmtree (result .build_dir ())
149181 result .make_size ()
150182 result .print_summary ()
151183 sizes .append (result )
0 commit comments