@@ -120,34 +120,54 @@ def _analyze_project_dependencies(self) -> Set[str]:
120
120
"""Analyze project files to detect actually used components/libraries."""
121
121
used_components = set ()
122
122
123
+ print (f"DEBUG: Starting project analysis" )
124
+
123
125
try :
124
- # Analyze project source files
125
126
src_dir = self .env .subst ("$PROJECT_SRC_DIR" )
127
+ print (f"DEBUG: Scanning source directory: { src_dir } " )
128
+
126
129
if os .path .exists (src_dir ):
130
+ file_count = 0
127
131
for root , dirs , files in os .walk (src_dir ):
128
132
for file in files :
129
133
if file .endswith (('.cpp' , '.c' , '.h' , '.hpp' , '.ino' )):
134
+ file_count += 1
130
135
file_path = os .path .join (root , file )
131
- used_components .update (self ._extract_components_from_file (file_path ))
136
+ file_components = self ._extract_components_from_file (file_path )
137
+ if file_components :
138
+ print (f"DEBUG: File { file } detected components: { file_components } " )
139
+ used_components .update (file_components )
140
+
141
+ print (f"DEBUG: Scanned { file_count } source files" )
132
142
133
- # Analyze lib_deps for explicit dependencies (if available)
143
+ # Check lib_deps
134
144
lib_deps = self .env .GetProjectOption ("lib_deps" , [])
135
- if isinstance (lib_deps , str ):
136
- lib_deps = [lib_deps ]
137
-
138
- for dep in lib_deps :
139
- used_components .update (self ._extract_components_from_lib_dep (str (dep )))
145
+ if lib_deps :
146
+ print (f"DEBUG: Found lib_deps: { lib_deps } " )
147
+ if isinstance (lib_deps , str ):
148
+ lib_deps = [lib_deps ]
140
149
141
- except Exception :
142
- pass
150
+ for dep in lib_deps :
151
+ dep_components = self ._extract_components_from_lib_dep (str (dep ))
152
+ if dep_components :
153
+ print (f"DEBUG: lib_dep '{ dep } ' mapped to components: { dep_components } " )
154
+ used_components .update (dep_components )
155
+ else :
156
+ print (f"DEBUG: No lib_deps found" )
157
+
158
+ except Exception as e :
159
+ print (f"DEBUG: Exception in project analysis: { e } " )
160
+ import traceback
161
+ traceback .print_exc ()
143
162
163
+ print (f"DEBUG: Final detected components: { used_components } " )
144
164
return used_components
145
165
146
166
def _extract_components_from_file (self , file_path : str ) -> Set [str ]:
147
167
"""Extract component usage from a single file by analyzing includes and function calls."""
148
168
components = set ()
149
169
150
- # Component detection patterns - maps component names to search patterns
170
+ # Component detection patterns - maps component names to code patterns
151
171
component_patterns = {
152
172
'bt' : ['bluetooth' , 'ble' , 'nimble' , 'bt_' , 'esp_bt' , 'esp_ble' ],
153
173
'esp_wifi' : ['wifi' , 'esp_wifi' , 'tcpip_adapter' ],
@@ -163,14 +183,18 @@ def _extract_components_from_file(self, file_path: str) -> Set[str]:
163
183
'driver' : ['gpio_' , 'uart_' , 'spi_' , 'i2c_' , 'adc_' , 'dac_' ],
164
184
'esp_camera' : ['esp_camera' , 'camera.h' ],
165
185
'esp_now' : ['esp_now' , 'espnow' ],
166
- 'esp_smartconfig' : ['smartconfig' , 'esp_smartconfig' ]
186
+ 'esp_smartconfig' : ['smartconfig' , 'esp_smartconfig' ],
187
+ 'esp_eth' : ['esp_eth' , 'ethernet' ],
188
+ 'esp_websocket_client' : ['websocket' , 'esp_websocket' ],
189
+ 'cjson' : ['cjson' , 'json' ],
190
+ 'mbedtls' : ['mbedtls' , 'ssl' ],
191
+ 'openssl' : ['openssl' ]
167
192
}
168
193
169
194
try :
170
195
with open (file_path , 'r' , encoding = 'utf-8' , errors = 'ignore' ) as f :
171
196
content = f .read ().lower ()
172
197
173
- # Check each component pattern against file content
174
198
for component , patterns in component_patterns .items ():
175
199
if any (pattern in content for pattern in patterns ):
176
200
components .add (component )
@@ -181,7 +205,7 @@ def _extract_components_from_file(self, file_path: str) -> Set[str]:
181
205
return components
182
206
183
207
def _extract_components_from_lib_dep (self , lib_dep : str ) -> Set [str ]:
184
- """Extract components from lib_deps entry by mapping library names to components."""
208
+ """Extract components from lib_deps entry by mapping library names to ESP-IDF components."""
185
209
components = set ()
186
210
lib_dep_upper = lib_dep .upper ()
187
211
@@ -192,7 +216,10 @@ def _extract_components_from_lib_dep(self, lib_dep: str) -> Set[str]:
192
216
'esp_dsp' : ['DSP' , 'FFT' , 'JPEG' ],
193
217
'esp_http_client' : ['HTTP' , 'HTTPCLIENT' ],
194
218
'mqtt' : ['MQTT' , 'PUBSUB' ],
195
- 'esp_camera' : ['CAMERA' , 'ESP32CAM' ]
219
+ 'esp_camera' : ['CAMERA' , 'ESP32CAM' ],
220
+ 'esp_now' : ['ESPNOW' , 'ESP_NOW' ],
221
+ 'mdns' : ['MDNS' ],
222
+ 'esp_eth' : ['ETHERNET' ]
196
223
}
197
224
198
225
for component , keywords in lib_dep_mapping .items ():
@@ -203,7 +230,7 @@ def _extract_components_from_lib_dep(self, lib_dep: str) -> Set[str]:
203
230
204
231
def _is_component_used_in_project (self , lib_name : str ) -> bool :
205
232
"""Check if a component/library is actually used in the project."""
206
- # Cache project analysis results for performance
233
+ # Cache project analysis for performance
207
234
if not hasattr (self , '_project_components_cache' ):
208
235
self ._project_components_cache = self ._analyze_project_dependencies ()
209
236
@@ -406,23 +433,36 @@ def _remove_ignored_lib_includes(self) -> None:
406
433
build_py_path = join (self .arduino_libs_mcu , "pioarduino-build.py" )
407
434
408
435
if not os .path .exists (build_py_path ):
436
+ print (f"DEBUG: Build file not found: { build_py_path } " )
409
437
return
410
438
439
+ print (f"DEBUG: Starting lib_ignore processing" )
440
+ print (f"DEBUG: ignored_libs = { list (self .ignored_libs )} " )
441
+
442
+ # Force project analysis and show results
443
+ self ._project_components_cache = self ._analyze_project_dependencies ()
444
+ print (f"DEBUG: Detected project components: { list (self ._project_components_cache )} " )
445
+
411
446
try :
412
447
with open (build_py_path , 'r' ) as f :
413
448
content = f .read ()
414
449
415
450
original_content = content
416
451
total_removed = 0
417
452
418
- # Remove CPPPATH entries for each ignored library
453
+ # Check each library individually
419
454
for lib_name in self .ignored_libs :
420
- # Universal protection: Skip if component is actually used in project
421
- if self ._is_component_used_in_project (lib_name ):
422
- print (f"Skipping removal of library '{ lib_name } ' - detected as used in project" )
455
+ print (f"DEBUG: Processing lib_name = '{ lib_name } '" )
456
+
457
+ # Check if component is used
458
+ is_used = self ._is_component_used_in_project (lib_name )
459
+ print (f"DEBUG: Is '{ lib_name } ' used in project? { is_used } " )
460
+
461
+ if is_used :
462
+ print (f"DEBUG: SKIPPING '{ lib_name } ' - detected as used" )
423
463
continue
424
-
425
- # Multiple patterns to catch different include formats
464
+
465
+ # Check what would be removed
426
466
patterns = [
427
467
rf'.*join\([^,]*,\s*"include",\s*"{ re .escape (lib_name )} "[^)]*\),?\n' ,
428
468
rf'.*"include/{ re .escape (lib_name )} "[^,\n]*,?\n' ,
@@ -434,23 +474,41 @@ def _remove_ignored_lib_includes(self) -> None:
434
474
rf'\s*"[^"]*/{ re .escape (lib_name )} /[^"]*",?\n'
435
475
]
436
476
477
+ matches_found = []
437
478
for pattern in patterns :
438
479
matches = re .findall (pattern , content )
439
480
if matches :
481
+ matches_found .extend (matches )
482
+
483
+ if matches_found :
484
+ print (f"DEBUG: REMOVING '{ lib_name } ' - found { len (matches_found )} matches:" )
485
+ for match in matches_found :
486
+ print (f"DEBUG: - { match .strip ()} " )
487
+
488
+ for pattern in patterns :
440
489
content = re .sub (pattern , '' , content )
441
- total_removed += len (matches )
490
+ total_removed += len (re .findall (pattern , original_content ))
491
+ else :
492
+ print (f"DEBUG: No matches found for '{ lib_name } '" )
493
+
494
+ print (f"DEBUG: Total lines removed: { total_removed } " )
442
495
443
496
# Clean up empty lines and trailing commas
444
497
content = re .sub (r'\n\s*\n' , '\n ' , content )
445
498
content = re .sub (r',\s*\n\s*\]' , '\n ]' , content )
446
499
447
500
# Validate and write changes
448
501
if self ._validate_changes (original_content , content ) and content != original_content :
502
+ print (f"DEBUG: Content changed, writing new file" )
449
503
with open (build_py_path , 'w' ) as f :
450
504
f .write (content )
505
+ else :
506
+ print (f"DEBUG: No changes made to build file" )
451
507
452
- except Exception :
453
- pass
508
+ except Exception as e :
509
+ print (f"DEBUG: Exception occurred: { e } " )
510
+ import traceback
511
+ traceback .print_exc ()
454
512
455
513
def _validate_changes (self , original_content : str , new_content : str ) -> bool :
456
514
"""Validate that the changes are reasonable."""
0 commit comments