@@ -116,113 +116,50 @@ def _get_lib_ignore_entries(self) -> List[str]:
116
116
except Exception :
117
117
return []
118
118
119
- def _analyze_project_dependencies (self ) -> Set [str ]:
120
- """Analyze project files to detect actually used components/libraries."""
121
- used_components = set ()
122
-
119
+ def _has_bt_ble_dependencies (self ) -> bool :
120
+ """Check if lib_deps contains any BT/BLE related dependencies."""
123
121
try :
124
- # Analyze project source files
125
- src_dir = self .env .subst ("$PROJECT_SRC_DIR" )
126
- if os .path .exists (src_dir ):
127
- for root , dirs , files in os .walk (src_dir ):
128
- for file in files :
129
- if file .endswith (('.cpp' , '.c' , '.h' , '.hpp' , '.ino' )):
130
- file_path = os .path .join (root , file )
131
- used_components .update (self ._extract_components_from_file (file_path ))
132
-
133
- # Analyze lib_deps for explicit dependencies (if present)
122
+ # Get lib_deps from current environment
134
123
lib_deps = self .env .GetProjectOption ("lib_deps" , [])
124
+
135
125
if isinstance (lib_deps , str ):
136
126
lib_deps = [lib_deps ]
127
+ elif lib_deps is None :
128
+ lib_deps = []
129
+
130
+ # Convert to string and check for BT/BLE keywords
131
+ lib_deps_str = ' ' .join (str (dep ) for dep in lib_deps ).upper ()
132
+
133
+ bt_ble_keywords = ['BLE' , 'BT' , 'NIMBLE' , 'BLUETOOTH' ]
134
+
135
+ for keyword in bt_ble_keywords :
136
+ if keyword in lib_deps_str :
137
+ return True
138
+
139
+ return False
137
140
138
- for dep in lib_deps :
139
- used_components .update (self ._extract_components_from_lib_dep (str (dep )))
140
-
141
- except Exception :
142
- pass
143
-
144
- return used_components
145
-
146
- def _extract_components_from_file (self , file_path : str ) -> Set [str ]:
147
- """Extract component usage from a single file by analyzing includes and function calls."""
148
- components = set ()
149
-
150
- # Component detection patterns - maps component names to code patterns
151
- component_patterns = {
152
- 'bt' : ['bluetooth' , 'ble' , 'nimble' , 'bt_' , 'esp_bt' , 'esp_ble' ],
153
- 'esp_wifi' : ['wifi' , 'esp_wifi' , 'tcpip_adapter' ],
154
- 'esp_dsp' : ['dsps_' , 'esp_dsp' , 'fft2r' , 'dsps_fft2r' ], # Enhanced DSP detection
155
- 'esp_http_client' : ['esp_http_client' , 'http_client' ],
156
- 'esp_https_ota' : ['esp_https_ota' , 'esp_ota' ],
157
- 'mdns' : ['mdns' , 'esp_mdns' ],
158
- 'mqtt' : ['mqtt' , 'esp_mqtt' ],
159
- 'spiffs' : ['spiffs' , 'esp_spiffs' ],
160
- 'fatfs' : ['fatfs' , 'ff.h' ],
161
- 'nvs_flash' : ['nvs' , 'nvs_flash' ],
162
- 'esp_timer' : ['esp_timer' , 'timer_' ],
163
- 'driver' : ['gpio_' , 'uart_' , 'spi_' , 'i2c_' , 'adc_' , 'dac_' ],
164
- 'esp_camera' : ['esp_camera' , 'camera.h' ],
165
- 'esp_now' : ['esp_now' , 'espnow' ],
166
- 'esp_smartconfig' : ['smartconfig' , 'esp_smartconfig' ],
167
- 'esp_eth' : ['esp_eth' , 'ethernet' ],
168
- 'esp_websocket_client' : ['websocket' , 'esp_websocket' ],
169
- 'cjson' : ['cjson' , 'json' ],
170
- 'mbedtls' : ['mbedtls' , 'ssl' ],
171
- 'openssl' : ['openssl' ]
172
- }
173
-
174
- try :
175
- with open (file_path , 'r' , encoding = 'utf-8' , errors = 'ignore' ) as f :
176
- content = f .read ().lower ()
177
-
178
- for component , patterns in component_patterns .items ():
179
- if any (pattern in content for pattern in patterns ):
180
- components .add (component )
181
-
182
141
except Exception :
183
- pass
184
-
185
- return components
186
-
187
- def _extract_components_from_lib_dep (self , lib_dep : str ) -> Set [str ]:
188
- """Extract components from lib_deps entry by mapping library names to ESP-IDF components."""
189
- components = set ()
190
- lib_dep_upper = lib_dep .upper ()
191
-
192
- # Map lib_deps entries to ESP-IDF components
193
- lib_dep_mapping = {
194
- 'bt' : ['BLE' , 'BT' , 'BLUETOOTH' , 'NIMBLE' ],
195
- 'esp_wifi' : ['WIFI' , 'ASYNCTCP' , 'ESPASYNCWEBSERVER' ],
196
- 'esp_dsp' : ['DSP' , 'FFT' , 'JPEG' ],
197
- 'esp_http_client' : ['HTTP' , 'HTTPCLIENT' ],
198
- 'mqtt' : ['MQTT' , 'PUBSUB' ],
199
- 'esp_camera' : ['CAMERA' , 'ESP32CAM' ],
200
- 'esp_now' : ['ESPNOW' , 'ESP_NOW' ],
201
- 'mdns' : ['MDNS' ],
202
- 'esp_eth' : ['ETHERNET' ]
203
- }
204
-
205
- for component , keywords in lib_dep_mapping .items ():
206
- if any (keyword in lib_dep_upper for keyword in keywords ):
207
- components .add (component )
208
-
209
- return components
142
+ return False
210
143
211
- def _is_component_used_in_project (self , lib_name : str ) -> bool :
212
- """Check if a component/library is actually used in the project."""
213
- # Cache project analysis for performance
214
- if not hasattr (self , '_project_components_cache' ):
215
- self ._project_components_cache = self ._analyze_project_dependencies ()
216
-
217
- lib_name_lower = lib_name .lower ()
218
-
219
- # Direct match
220
- if lib_name_lower in self ._project_components_cache :
221
- return True
222
-
223
- # Partial match for related components
224
- for used_component in self ._project_components_cache :
225
- if lib_name_lower in used_component or used_component in lib_name_lower :
144
+ def _is_bt_related_library (self , lib_name : str ) -> bool :
145
+ """Check if a library name is related to Bluetooth/BLE functionality."""
146
+ lib_name_upper = lib_name .upper ()
147
+
148
+ bt_related_names = [
149
+ 'BT' ,
150
+ 'BLE' ,
151
+ 'BLUETOOTH' ,
152
+ 'NIMBLE' ,
153
+ 'ESP32_BLE' ,
154
+ 'ESP32BLE' ,
155
+ 'BLUETOOTHSERIAL' ,
156
+ 'BLE_ARDUINO' ,
157
+ 'ESP_BLE' ,
158
+ 'ESP_BT'
159
+ ]
160
+
161
+ for bt_name in bt_related_names :
162
+ if bt_name in lib_name_upper :
226
163
return True
227
164
228
165
return False
@@ -415,6 +352,9 @@ def _remove_ignored_lib_includes(self) -> None:
415
352
if not os .path .exists (build_py_path ):
416
353
return
417
354
355
+ # Check if BT/BLE dependencies exist in lib_deps
356
+ bt_ble_protected = self ._has_bt_ble_dependencies ()
357
+
418
358
try :
419
359
with open (build_py_path , 'r' ) as f :
420
360
content = f .read ()
@@ -424,9 +364,14 @@ def _remove_ignored_lib_includes(self) -> None:
424
364
425
365
# Remove CPPPATH entries for each ignored library
426
366
for lib_name in self .ignored_libs :
427
- # Universal protection: Skip if component is actually used in project
428
- if self ._is_component_used_in_project (lib_name ):
429
- print (f"Skipping removal of library '{ lib_name } ' - detected as used in project" )
367
+ # Skip BT-related libraries if BT/BLE dependencies are present
368
+ if bt_ble_protected and self ._is_bt_related_library (lib_name ):
369
+ print (f"Skipping removal of BT-related library '{ lib_name } ' due to BT/BLE dependency in lib_deps" )
370
+ continue
371
+
372
+ # Hard protection for DSP components
373
+ if lib_name .lower () in ['dsp' , 'esp_dsp' , 'dsps' , 'fft2r' , 'dsps_fft2r' ]:
374
+ print (f"Hard-protected DSP component '{ lib_name } ' from removal" )
430
375
continue
431
376
432
377
# Multiple patterns to catch different include formats
0 commit comments