32
32
# column of the table is really D/IRAM.
33
33
import os
34
34
import re
35
+ import shutil
35
36
import sys
36
37
import subprocess
37
38
from dataclasses import dataclass
47
48
)
48
49
49
50
51
+ def rmtree (path ):
52
+ try :
53
+ shutil .rmtree (path )
54
+ except FileNotFoundError :
55
+ pass
56
+
57
+
50
58
@dataclass
51
59
class BuildSizes :
52
60
idf_ver : str
@@ -99,7 +107,7 @@ def __lt__(self, other):
99
107
100
108
def build_dir (self ):
101
109
if self .variant :
102
- return f"build-{ self .board } _ { self .variant } "
110
+ return f"build-{ self .board } - { self .variant } "
103
111
else :
104
112
return f"build-{ self .board } "
105
113
@@ -124,12 +132,23 @@ def run_make(self, target):
124
132
def make_size (self ):
125
133
try :
126
134
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
130
151
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 )
133
152
self .bin_size = re .search (RE_BIN , size_out ).group (1 )
134
153
except subprocess .CalledProcessError :
135
154
self .bin_size = "build failed"
@@ -139,13 +158,26 @@ def main(do_clean):
139
158
if "IDF_PATH" not in os .environ :
140
159
raise RuntimeError ("IDF_PATH must be set" )
141
160
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
+
142
171
sizes = []
143
172
for idf_ver in IDF_VERS :
144
173
switch_ver (idf_ver )
174
+ rmtree ("managed_components" )
145
175
for board , variant in BUILDS :
146
176
print (f"Building '{ board } '/'{ variant } '..." , file = sys .stderr )
147
177
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 ())
149
181
result .make_size ()
150
182
result .print_summary ()
151
183
sizes .append (result )
0 commit comments