Skip to content

Commit c19d1a0

Browse files
authored
Update arduino.py
1 parent c287ddb commit c19d1a0

File tree

1 file changed

+99
-84
lines changed

1 file changed

+99
-84
lines changed

builder/frameworks/arduino.py

Lines changed: 99 additions & 84 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
import shutil
3131
import hashlib
3232
import logging
33+
import threading
3334
from contextlib import suppress
3435
from os.path import join, exists, isabs, splitdrive, commonpath, relpath
3536
from pathlib import Path
@@ -81,7 +82,8 @@ def setup_logging():
8182
"CONFIG_FREERTOS_UNICORE=y"
8283
}
8384

84-
# Global flags to prevent message spam
85+
# Thread-safe global flags to prevent message spam
86+
_PATH_SHORTENING_LOCK = threading.Lock()
8587
_PATH_SHORTENING_MESSAGES = {
8688
'shortening_applied': False,
8789
'no_framework_paths_warning': False,
@@ -95,6 +97,7 @@ def __init__(self, platform, mcu):
9597
self.platform = platform
9698
self.mcu = mcu
9799
self._framework_dir = None
100+
self._framework_lib_dir = None
98101
self._sdk_dir = None
99102

100103
@property
@@ -104,7 +107,7 @@ def framework_dir(self):
104107
return self._framework_dir
105108

106109
@property
107-
def framework_dir(self):
110+
def framework_lib_dir(self):
108111
if self._framework_lib_dir is None:
109112
self._framework_lib_dir = self.platform.get_package_dir("framework-arduinoespressif32-libs")
110113
return self._framework_lib_dir
@@ -119,32 +122,33 @@ def sdk_dir(self):
119122

120123
def check_and_warn_long_path_support():
121124
"""Checks Windows long path support and issues warning if disabled"""
122-
if not IS_WINDOWS or _PATH_SHORTENING_MESSAGES['long_path_warning_shown']:
123-
return
124-
125-
try:
126-
import winreg
127-
key = winreg.OpenKey(
128-
winreg.HKEY_LOCAL_MACHINE,
129-
r"SYSTEM\CurrentControlSet\Control\FileSystem"
130-
)
131-
value, _ = winreg.QueryValueEx(key, "LongPathsEnabled")
132-
winreg.CloseKey(key)
125+
with _PATH_SHORTENING_LOCK: # Thread-safe access
126+
if not IS_WINDOWS or _PATH_SHORTENING_MESSAGES['long_path_warning_shown']:
127+
return
128+
129+
try:
130+
import winreg
131+
key = winreg.OpenKey(
132+
winreg.HKEY_LOCAL_MACHINE,
133+
r"SYSTEM\CurrentControlSet\Control\FileSystem"
134+
)
135+
value, _ = winreg.QueryValueEx(key, "LongPathsEnabled")
136+
winreg.CloseKey(key)
137+
138+
if value != 1:
139+
print("*** WARNING: Windows Long Path Support is disabled ***")
140+
print("*** Enable it for better performance: ***")
141+
print("*** 1. Run as Administrator: gpedit.msc ***")
142+
print("*** 2. Navigate to: Computer Configuration > Administrative Templates > System > Filesystem ***")
143+
print("*** 3. Enable 'Enable Win32 long paths' ***")
144+
print("*** OR run PowerShell as Admin: ***")
145+
print("*** New-ItemProperty -Path 'HKLM:\\SYSTEM\\CurrentControlSet\\Control\\FileSystem' -Name 'LongPathsEnabled' -Value 1 -PropertyType DWORD -Force ***")
146+
print("*** Restart required after enabling ***")
147+
except Exception:
148+
print("*** WARNING: Could not check Long Path Support status ***")
149+
print("*** Consider enabling Windows Long Path Support for better performance ***")
133150

134-
if value != 1:
135-
print("*** WARNING: Windows Long Path Support is disabled ***")
136-
print("*** Enable it for better performance: ***")
137-
print("*** 1. Run as Administrator: gpedit.msc ***")
138-
print("*** 2. Navigate to: Computer Configuration > Administrative Templates > System > Filesystem ***")
139-
print("*** 3. Enable 'Enable Win32 long paths' ***")
140-
print("*** OR run PowerShell as Admin: ***")
141-
print("*** New-ItemProperty -Path 'HKLM:\\SYSTEM\\CurrentControlSet\\Control\\FileSystem' -Name 'LongPathsEnabled' -Value 1 -PropertyType DWORD -Force ***")
142-
print("*** Restart required after enabling ***")
143-
except Exception:
144-
print("*** WARNING: Could not check Long Path Support status ***")
145-
print("*** Consider enabling Windows Long Path Support for better performance ***")
146-
147-
_PATH_SHORTENING_MESSAGES['long_path_warning_shown'] = True
151+
_PATH_SHORTENING_MESSAGES['long_path_warning_shown'] = True
148152

149153
# Secure deletion functions
150154
def safe_delete_file(file_path: Union[str, Path],
@@ -204,34 +208,37 @@ def safe_delete_directory(dir_path: Union[str, Path]) -> bool:
204208

205209
def validate_platformio_path(path: Union[str, Path]) -> bool:
206210
"""
207-
Special validation for PlatformIO package paths
211+
Enhanced validation for PlatformIO package paths
208212
"""
209-
path = Path(path).resolve()
210-
path_str = str(path)
211-
212-
# Must be within .platformio directory structure
213-
if ".platformio" not in path_str:
214-
return False
215-
216-
# Must be a packages directory
217-
if "packages" not in path_str:
218-
return False
213+
try:
214+
path = Path(path).resolve()
215+
path_str = str(path)
219216

220-
# Must be framework-related
221-
framework_indicators = [
222-
"framework-arduinoespressif32",
223-
".platformio/packages",
224-
"packages/framework-arduinoespressif32",
225-
"packages/framework-arduinoespressif32-libs",
226-
"packages/framework-arduino-c2-skeleton-lib"
227-
]
228-
229-
if not any(indicator in path_str for indicator in framework_indicators):
217+
# Must be within .platformio directory structure
218+
if ".platformio" not in path_str:
219+
return False
220+
221+
# Must be a packages directory
222+
if "packages" not in path_str:
223+
return False
224+
225+
# Must be framework-related
226+
framework_indicators = [
227+
"framework-arduinoespressif32",
228+
"framework-arduinoespressif32-libs",
229+
"framework-arduino-c2-skeleton-lib"
230+
]
231+
232+
if not any(indicator in path_str for indicator in framework_indicators):
233+
return False
234+
235+
# Must not be a critical system path
236+
critical_paths = ["/usr", "/bin", "/sbin", "/etc", "/boot", "C:\\Windows", "C:\\Program Files"]
237+
return not any(critical in path_str for critical in critical_paths)
238+
239+
except Exception as e:
240+
logging.error(f"Path validation error: {e}")
230241
return False
231-
232-
# Must not be a critical system path
233-
critical_paths = ["/usr", "/bin", "/sbin", "/etc", "/boot"]
234-
return not any(critical in path_str for critical in critical_paths)
235242

236243
def validate_deletion_path(path: Union[str, Path],
237244
allowed_patterns: List[str]) -> bool:
@@ -281,43 +288,42 @@ def validate_deletion_path(path: Union[str, Path],
281288
return is_allowed
282289

283290
def safe_framework_cleanup():
284-
"""Secure cleanup of Arduino Framework"""
291+
"""Secure cleanup of Arduino Framework with enhanced error handling"""
292+
success = True
285293

286-
# Secure deletion of framework directories
294+
# Framework directory cleanup
287295
if exists(FRAMEWORK_DIR):
288296
logging.info(f"Attempting to validate framework path: {FRAMEWORK_DIR}")
289297

290-
# Use specialized PlatformIO path validation
291298
if validate_platformio_path(FRAMEWORK_DIR):
292-
#print("*** Secure framework cleanup ***")
293299
logging.info(f"Framework path validated successfully: {FRAMEWORK_DIR}")
294300

295301
if safe_delete_directory(FRAMEWORK_DIR):
296302
print("Framework successfully removed")
297303
else:
298304
print("Error removing framework")
299-
return False
305+
success = False
300306
else:
301307
logging.error(f"PlatformIO path validation failed: {FRAMEWORK_DIR}")
302-
return False
303-
308+
success = False
309+
310+
# Framework libs directory cleanup
311+
if exists(FRAMEWORK_LIB_DIR):
304312
logging.info(f"Attempting to validate framework lib path: {FRAMEWORK_LIB_DIR}")
305313

306-
# Use specialized PlatformIO path validation
307314
if validate_platformio_path(FRAMEWORK_LIB_DIR):
308-
#print("*** Secure framework cleanup ***")
309315
logging.info(f"Framework lib path validated successfully: {FRAMEWORK_LIB_DIR}")
310316

311317
if safe_delete_directory(FRAMEWORK_LIB_DIR):
312318
print("Framework libs successfully removed")
313-
return True
314319
else:
315-
print("Error removing framework")
316-
return False
320+
print("Error removing framework libs")
321+
success = False
317322
else:
318323
logging.error(f"PlatformIO path validation failed: {FRAMEWORK_LIB_DIR}")
319-
return False
320-
return True
324+
success = False
325+
326+
return success
321327

322328
def safe_remove_sdkconfig_files():
323329
"""Secure removal of SDKConfig files"""
@@ -499,9 +505,17 @@ def is_framework_subfolder(potential_subfolder):
499505
return False
500506
return commonpath([FRAMEWORK_SDK_DIR]) == commonpath([FRAMEWORK_SDK_DIR, potential_subfolder])
501507

508+
# Performance optimization with caching
502509
def calculate_include_path_length(includes):
503-
"""Calculate total character count of all include paths"""
504-
return sum(len(str(inc)) for inc in includes)
510+
"""Calculate total character count of all include paths with caching"""
511+
if not hasattr(calculate_include_path_length, '_cache'):
512+
calculate_include_path_length._cache = {}
513+
514+
cache_key = tuple(includes)
515+
if cache_key not in calculate_include_path_length._cache:
516+
calculate_include_path_length._cache[cache_key] = sum(len(str(inc)) for inc in includes)
517+
518+
return calculate_include_path_length._cache[cache_key]
505519

506520
def analyze_path_distribution(includes):
507521
"""Analyze the distribution of include path lengths for optimization insights"""
@@ -581,20 +595,21 @@ def apply_include_shortening(env, node, includes, total_length):
581595
else:
582596
generic_includes.append(inc)
583597

584-
# Show result message only once
585-
if not _PATH_SHORTENING_MESSAGES['shortening_applied']:
586-
if shortened_includes:
587-
new_total_length = original_length - saved_chars + len(f"-iprefix{FRAMEWORK_SDK_DIR}")
588-
print(f"*** Applied include path shortening for {len(shortened_includes)} framework paths ***")
589-
print(f"*** Path length reduced from {original_length} to ~{new_total_length} characters ***")
590-
print(f"*** Estimated savings: {saved_chars} characters ***")
591-
else:
592-
if not _PATH_SHORTENING_MESSAGES['no_framework_paths_warning']:
593-
print("*** Warning: Path length high but no framework paths found for shortening ***")
594-
print("*** This may indicate an architecture-specific issue ***")
595-
print("*** Run with -v (verbose) for detailed path analysis ***")
596-
_PATH_SHORTENING_MESSAGES['no_framework_paths_warning'] = True
597-
_PATH_SHORTENING_MESSAGES['shortening_applied'] = True
598+
# Show result message only once with thread safety
599+
with _PATH_SHORTENING_LOCK:
600+
if not _PATH_SHORTENING_MESSAGES['shortening_applied']:
601+
if shortened_includes:
602+
new_total_length = original_length - saved_chars + len(f"-iprefix{FRAMEWORK_SDK_DIR}")
603+
print(f"*** Applied include path shortening for {len(shortened_includes)} framework paths ***")
604+
print(f"*** Path length reduced from {original_length} to ~{new_total_length} characters ***")
605+
print(f"*** Estimated savings: {saved_chars} characters ***")
606+
else:
607+
if not _PATH_SHORTENING_MESSAGES['no_framework_paths_warning']:
608+
print("*** Warning: Path length high but no framework paths found for shortening ***")
609+
print("*** This may indicate an architecture-specific issue ***")
610+
print("*** Run with -v (verbose) for detailed path analysis ***")
611+
_PATH_SHORTENING_MESSAGES['no_framework_paths_warning'] = True
612+
_PATH_SHORTENING_MESSAGES['shortening_applied'] = True
598613

599614
common_flags = ["-iprefix", FRAMEWORK_SDK_DIR] + shortened_includes
600615

@@ -645,14 +660,14 @@ def get_frameworks_in_current_env():
645660
# Arduino as component is set, switch off Hybrid compile
646661
flag_custom_sdkconfig = False
647662

648-
# Framework reinstallation if required - IMPROVED WITH SECURE DELETION
663+
# Framework reinstallation if required - Enhanced with secure deletion and error handling
649664
if check_reinstall_frwrk():
650665
# Secure removal of SDKConfig files
651666
safe_remove_sdkconfig_files()
652667

653668
print("*** Reinstall Arduino framework ***")
654669

655-
# Secure framework cleanup
670+
# Secure framework cleanup with enhanced error handling
656671
if safe_framework_cleanup():
657672
arduino_frmwrk_url = str(platform.get_package_spec("framework-arduinoespressif32")).split("uri=", 1)[1][:-1]
658673
arduino_frmwrk_lib_url = str(platform.get_package_spec("framework-arduinoespressif32-libs")).split("uri=",1)[1][:-1]

0 commit comments

Comments
 (0)