Skip to content

Commit 5d39582

Browse files
authored
try again deep analyse
1 parent 5db706c commit 5d39582

File tree

1 file changed

+103
-48
lines changed

1 file changed

+103
-48
lines changed

builder/frameworks/component_manager.py

Lines changed: 103 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -116,50 +116,113 @@ def _get_lib_ignore_entries(self) -> List[str]:
116116
except Exception:
117117
return []
118118

119-
def _has_bt_ble_dependencies(self) -> bool:
120-
"""Check if lib_deps contains any BT/BLE related dependencies."""
119+
def _analyze_project_dependencies(self) -> Set[str]:
120+
"""Analyze project files to detect actually used components/libraries."""
121+
used_components = set()
122+
121123
try:
122-
# Get lib_deps from current environment
123-
lib_deps = self.env.GetProjectOption("lib_deps", [])
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))
124132

133+
# Analyze lib_deps for explicit dependencies (if present)
134+
lib_deps = self.env.GetProjectOption("lib_deps", [])
125135
if isinstance(lib_deps, str):
126136
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
140137

138+
for dep in lib_deps:
139+
used_components.update(self._extract_components_from_lib_dep(str(dep)))
140+
141141
except Exception:
142-
return False
142+
pass
143+
144+
return used_components
143145

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:
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+
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
210+
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:
163226
return True
164227

165228
return False
@@ -352,9 +415,6 @@ def _remove_ignored_lib_includes(self) -> None:
352415
if not os.path.exists(build_py_path):
353416
return
354417

355-
# Check if BT/BLE dependencies exist in lib_deps
356-
bt_ble_protected = self._has_bt_ble_dependencies()
357-
358418
try:
359419
with open(build_py_path, 'r') as f:
360420
content = f.read()
@@ -364,14 +424,9 @@ def _remove_ignored_lib_includes(self) -> None:
364424

365425
# Remove CPPPATH entries for each ignored library
366426
for lib_name in self.ignored_libs:
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")
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")
375430
continue
376431

377432
# Multiple patterns to catch different include formats

0 commit comments

Comments
 (0)