|
43 | 43 |
|
44 | 44 | IS_WINDOWS = sys.platform.startswith("win")
|
45 | 45 |
|
46 |
| -# Include path length threshold for path shortening, only valid and needed for Windows |
47 |
| -# Windows has a path length limit of ~260 characters per path, but the total command line |
48 |
| -# length is also limited to ~32000 characters |
49 |
| -INCLUDE_PATH_LENGTH_THRESHOLD = 31500 # Total character count threshold |
50 |
| - |
51 | 46 | python_deps = {
|
52 | 47 | "wheel": ">=0.35.1",
|
53 | 48 | "rich-click": ">=1.8.6",
|
@@ -90,6 +85,219 @@ def setup_logging():
|
90 | 85 | 'long_path_warning_shown': False
|
91 | 86 | }
|
92 | 87 |
|
| 88 | +def get_platform_default_threshold(mcu): |
| 89 | + """ |
| 90 | + Platform-specific bleeding edge default values for INCLUDE_PATH_LENGTH_THRESHOLD |
| 91 | + These values push the limits for maximum performance and minimal path shortening |
| 92 | + |
| 93 | + Args: |
| 94 | + mcu: MCU type (esp32, esp32s2, esp32s3, etc.) |
| 95 | + |
| 96 | + Returns: |
| 97 | + int: Platform-specific bleeding edge default threshold |
| 98 | + """ |
| 99 | + # Bleeding edge values - pushing Windows command line limits |
| 100 | + # Windows CMD has ~32768 character limit, we use aggressive values close to this |
| 101 | + platform_defaults = { |
| 102 | + "esp32": 45000, # Standard ESP32 |
| 103 | + "esp32s2": 43000, # ESP32-S2 |
| 104 | + "esp32s3": 48000, # ESP32-S3 |
| 105 | + "esp32c3": 41000, # ESP32-C3 |
| 106 | + "esp32c2": 38000, # ESP32-C2 |
| 107 | + "esp32c6": 44000, # ESP32-C6 |
| 108 | + "esp32h2": 40000, # ESP32-H2 |
| 109 | + "esp32p4": 50000, # ESP32-P4 |
| 110 | + } |
| 111 | + |
| 112 | + default_value = platform_defaults.get(mcu, 45000) # Aggressive fallback |
| 113 | + |
| 114 | + # Debug output only in verbose mode |
| 115 | + if logging.getLogger().isEnabledFor(logging.DEBUG): |
| 116 | + logging.debug(f"Bleeding edge platform default threshold for {mcu}: {default_value}") |
| 117 | + |
| 118 | + return default_value |
| 119 | + |
| 120 | +def validate_threshold(threshold, mcu): |
| 121 | + """ |
| 122 | + Validates threshold value with bleeding edge limits |
| 123 | + Uses aggressive boundaries for maximum performance |
| 124 | + |
| 125 | + Args: |
| 126 | + threshold: Threshold value to validate |
| 127 | + mcu: MCU type for context-specific validation |
| 128 | + |
| 129 | + Returns: |
| 130 | + int: Validated threshold value |
| 131 | + """ |
| 132 | + # Bleeding edge absolute limits - pushing boundaries |
| 133 | + min_threshold = 15000 # Minimum reasonable value for complex projects |
| 134 | + max_threshold = 65000 # Maximum aggressive value (beyond Windows CMD limit for testing) |
| 135 | + |
| 136 | + # MCU-specific bleeding edge adjustments - all values are aggressive |
| 137 | + mcu_adjustments = { |
| 138 | + "esp32c2": {"min": 30000, "max": 40000}, |
| 139 | + "esp32c3": {"min": 30000, "max": 45000}, |
| 140 | + "esp32": {"min": 30000, "max": 50000}, |
| 141 | + "esp32s2": {"min": 30000, "max": 50000}, |
| 142 | + "esp32s3": {"min": 30000, "max": 50000}, |
| 143 | + "esp32p4": {"min": 30000, "max": 55000}, |
| 144 | + "esp32c6": {"min": 30000, "max": 50000}, |
| 145 | + "esp32h2": {"min": 30000, "max": 40000}, |
| 146 | + } |
| 147 | + |
| 148 | + # Apply MCU-specific bleeding edge limits |
| 149 | + if mcu in mcu_adjustments: |
| 150 | + min_threshold = max(min_threshold, mcu_adjustments[mcu]["min"]) |
| 151 | + max_threshold = min(max_threshold, mcu_adjustments[mcu]["max"]) |
| 152 | + |
| 153 | + original_threshold = threshold |
| 154 | + |
| 155 | + if threshold < min_threshold: |
| 156 | + print(f"*** Warning: Include path threshold {threshold} too conservative for {mcu}, using bleeding edge minimum {min_threshold} ***") |
| 157 | + threshold = min_threshold |
| 158 | + elif threshold > max_threshold: |
| 159 | + print(f"*** Warning: Include path threshold {threshold} exceeds bleeding edge maximum for {mcu}, using {max_threshold} ***") |
| 160 | + threshold = max_threshold |
| 161 | + |
| 162 | + # Warning for conservative values (opposite of original - warn if too low) |
| 163 | + platform_default = get_platform_default_threshold(mcu) |
| 164 | + if threshold < platform_default * 0.7: # More than 30% below bleeding edge default |
| 165 | + print(f"*** Info: Include path threshold {threshold} is conservative compared to bleeding edge default {platform_default} for {mcu} ***") |
| 166 | + print(f"*** Consider using higher values for maximum performance ***") |
| 167 | + |
| 168 | + if original_threshold != threshold: |
| 169 | + logging.warning(f"Threshold adjusted from {original_threshold} to bleeding edge value {threshold} for {mcu}") |
| 170 | + |
| 171 | + return threshold |
| 172 | + |
| 173 | +def get_include_path_threshold(env, config, current_env_section): |
| 174 | + """ |
| 175 | + Determines Windows INCLUDE_PATH_LENGTH_THRESHOLD from various sources |
| 176 | + with priority order and bleeding edge validation |
| 177 | + |
| 178 | + Priority order: |
| 179 | + 1. Environment variable PLATFORMIO_INCLUDE_PATH_THRESHOLD |
| 180 | + 2. Environment-specific setting in platformio.ini |
| 181 | + 3. Global setting in [env] section |
| 182 | + 4. Setting in [platformio] section |
| 183 | + 5. MCU-specific bleeding edge default value |
| 184 | + |
| 185 | + Args: |
| 186 | + env: PlatformIO Environment |
| 187 | + config: Project Configuration |
| 188 | + current_env_section: Current environment section |
| 189 | + |
| 190 | + Returns: |
| 191 | + int: Validated bleeding edge threshold value |
| 192 | + """ |
| 193 | + mcu = env.BoardConfig().get("build.mcu", "esp32") |
| 194 | + default_threshold = get_platform_default_threshold(mcu) |
| 195 | + setting_name = "custom_include_path_length_threshold" |
| 196 | + |
| 197 | + try: |
| 198 | + # 1. Check environment variable (highest priority) |
| 199 | + env_var = os.environ.get("PLATFORMIO_INCLUDE_PATH_THRESHOLD") |
| 200 | + if env_var: |
| 201 | + try: |
| 202 | + threshold = int(env_var) |
| 203 | + threshold = validate_threshold(threshold, mcu) |
| 204 | + print(f"*** Using environment variable bleeding edge include path threshold: {threshold} (MCU: {mcu}) ***") |
| 205 | + return threshold |
| 206 | + except ValueError: |
| 207 | + print(f"*** Warning: Invalid environment variable PLATFORMIO_INCLUDE_PATH_THRESHOLD='{env_var}', ignoring ***") |
| 208 | + |
| 209 | + # 2. Check environment-specific setting |
| 210 | + if config.has_option(current_env_section, setting_name): |
| 211 | + threshold = config.getint(current_env_section, setting_name) |
| 212 | + threshold = validate_threshold(threshold, mcu) |
| 213 | + print(f"*** Using environment-specific bleeding edge include path threshold: {threshold} (MCU: {mcu}) ***") |
| 214 | + return threshold |
| 215 | + |
| 216 | + # 3. Check global setting in [env] section |
| 217 | + if config.has_option("env", setting_name): |
| 218 | + threshold = config.getint("env", setting_name) |
| 219 | + threshold = validate_threshold(threshold, mcu) |
| 220 | + print(f"*** Using global [env] bleeding edge include path threshold: {threshold} (MCU: {mcu}) ***") |
| 221 | + return threshold |
| 222 | + |
| 223 | + # 4. Check setting in [platformio] section |
| 224 | + if config.has_option("platformio", setting_name): |
| 225 | + threshold = config.getint("platformio", setting_name) |
| 226 | + threshold = validate_threshold(threshold, mcu) |
| 227 | + print(f"*** Using [platformio] section bleeding edge include path threshold: {threshold} (MCU: {mcu}) ***") |
| 228 | + return threshold |
| 229 | + |
| 230 | + # 5. Use MCU-specific bleeding edge default value |
| 231 | + threshold = validate_threshold(default_threshold, mcu) |
| 232 | + if env.get("VERBOSE"): |
| 233 | + print(f"*** Using platform-specific bleeding edge default include path threshold: {threshold} (MCU: {mcu}) ***") |
| 234 | + |
| 235 | + return threshold |
| 236 | + |
| 237 | + except (ValueError, TypeError) as e: |
| 238 | + print(f"*** Warning: Invalid include path threshold value, using bleeding edge platform default {default_threshold} for {mcu}: {e} ***") |
| 239 | + return validate_threshold(default_threshold, mcu) |
| 240 | + |
| 241 | +def get_threshold_info(env, config, current_env_section): |
| 242 | + """ |
| 243 | + Helper function for debug information about bleeding edge threshold configuration |
| 244 | + |
| 245 | + Args: |
| 246 | + env: PlatformIO Environment |
| 247 | + config: Project Configuration |
| 248 | + current_env_section: Current environment section |
| 249 | + |
| 250 | + Returns: |
| 251 | + dict: Information about threshold configuration |
| 252 | + """ |
| 253 | + mcu = env.BoardConfig().get("build.mcu", "esp32") |
| 254 | + setting_name = "custom_include_path_length_threshold" |
| 255 | + |
| 256 | + info = { |
| 257 | + "mcu": mcu, |
| 258 | + "platform_default": get_platform_default_threshold(mcu), |
| 259 | + "env_variable": os.environ.get("PLATFORMIO_INCLUDE_PATH_THRESHOLD"), |
| 260 | + "env_specific": None, |
| 261 | + "global_env": None, |
| 262 | + "platformio_section": None, |
| 263 | + "final_threshold": None, |
| 264 | + "source": "bleeding_edge_platform_default", |
| 265 | + "is_bleeding_edge": True |
| 266 | + } |
| 267 | + |
| 268 | + # Collect all possible sources |
| 269 | + if config.has_option(current_env_section, setting_name): |
| 270 | + try: |
| 271 | + info["env_specific"] = config.getint(current_env_section, setting_name) |
| 272 | + except ValueError: |
| 273 | + pass |
| 274 | + |
| 275 | + if config.has_option("env", setting_name): |
| 276 | + try: |
| 277 | + info["global_env"] = config.getint("env", setting_name) |
| 278 | + except ValueError: |
| 279 | + pass |
| 280 | + |
| 281 | + if config.has_option("platformio", setting_name): |
| 282 | + try: |
| 283 | + info["platformio_section"] = config.getint("platformio", setting_name) |
| 284 | + except ValueError: |
| 285 | + pass |
| 286 | + |
| 287 | + # Determine final threshold and source |
| 288 | + info["final_threshold"] = get_include_path_threshold(env, config, current_env_section) |
| 289 | + |
| 290 | + # Determine source |
| 291 | + if info["env_variable"]: |
| 292 | + info["source"] = "environment_variable" |
| 293 | + elif info["env_specific"] is not None: |
| 294 | + info["source"] = "env_specific" |
| 295 | + elif info["global_env"] is not None: |
| 296 | + info["source"] = "global_env" |
| 297 | + elif info["platformio_section"] is not None: |
| 298 | + info["source"] = "platformio_section" |
| 299 | + |
| 300 | + return info |
93 | 301 |
|
94 | 302 | # Cache class for frequently used paths
|
95 | 303 | class PathCache:
|
@@ -545,7 +753,7 @@ def debug_framework_paths(env, include_count, total_length):
|
545 | 753 | print(f"*** FRAMEWORK_SDK_DIR: {FRAMEWORK_SDK_DIR} ***")
|
546 | 754 | print(f"*** SDK exists: {exists(FRAMEWORK_SDK_DIR)} ***")
|
547 | 755 | print(f"*** Include count: {include_count} ***")
|
548 |
| - print(f"*** Total path length: {total_length} (threshold: {INCLUDE_PATH_LENGTH_THRESHOLD}) ***") |
| 756 | + print(f"*** Total path length: {total_length} ***") |
549 | 757 |
|
550 | 758 | includes = env.get("CPPPATH", [])
|
551 | 759 | framework_count = 0
|
@@ -619,31 +827,50 @@ def apply_include_shortening(env, node, includes, total_length):
|
619 | 827 | )
|
620 | 828 |
|
621 | 829 | def smart_include_length_shorten(env, node):
|
622 |
| - """Include path shortening based on total path length threshold""" |
| 830 | + """ |
| 831 | + Include path shortening based on bleeding edge configurable threshold with enhanced MCU support |
| 832 | + Uses aggressive thresholds for maximum performance |
| 833 | + """ |
623 | 834 | if IS_INTEGRATION_DUMP:
|
624 |
| - # Don't shorten include paths for IDE integrations |
625 | 835 | return node
|
626 | 836 |
|
627 | 837 | if not IS_WINDOWS:
|
628 | 838 | return env.Object(node)
|
629 | 839 |
|
630 |
| - # Check long path support once |
| 840 | + # Get dynamically configurable bleeding edge threshold |
| 841 | + include_path_threshold = get_include_path_threshold(env, config, current_env_section) |
| 842 | + |
631 | 843 | check_and_warn_long_path_support()
|
632 | 844 |
|
633 | 845 | includes = env.get("CPPPATH", [])
|
634 | 846 | include_count = len(includes)
|
635 | 847 | total_path_length = calculate_include_path_length(includes)
|
636 | 848 |
|
637 |
| - # Debug output in verbose mode |
638 |
| - debug_framework_paths(env, include_count, total_path_length) |
639 |
| - |
640 |
| - # Apply shortening only if total path length exceeds threshold |
641 |
| - # This is more accurate than just counting includes, as it considers |
642 |
| - # the actual command line length impact |
643 |
| - if total_path_length <= INCLUDE_PATH_LENGTH_THRESHOLD: |
644 |
| - return env.Object(node) # Normal compilation |
| 849 | + # Debug information in verbose mode |
| 850 | + if env.get("VERBOSE"): |
| 851 | + debug_framework_paths(env, include_count, total_path_length) |
| 852 | + |
| 853 | + # Extended debug information about bleeding edge threshold configuration |
| 854 | + threshold_info = get_threshold_info(env, config, current_env_section) |
| 855 | + print(f"*** Bleeding Edge Threshold Configuration Debug ***") |
| 856 | + print(f"*** MCU: {threshold_info['mcu']} ***") |
| 857 | + print(f"*** Bleeding Edge Platform Default: {threshold_info['platform_default']} ***") |
| 858 | + print(f"*** Final Bleeding Edge Threshold: {threshold_info['final_threshold']} ***") |
| 859 | + print(f"*** Source: {threshold_info['source']} ***") |
| 860 | + print(f"*** Performance Mode: Maximum Aggressive ***") |
| 861 | + if threshold_info['env_variable']: |
| 862 | + print(f"*** Env Variable: {threshold_info['env_variable']} ***") |
| 863 | + if threshold_info['env_specific']: |
| 864 | + print(f"*** Env Specific: {threshold_info['env_specific']} ***") |
| 865 | + if threshold_info['global_env']: |
| 866 | + print(f"*** Global Env: {threshold_info['global_env']} ***") |
| 867 | + if threshold_info['platformio_section']: |
| 868 | + print(f"*** PlatformIO Section: {threshold_info['platformio_section']} ***") |
| 869 | + |
| 870 | + # Use the configurable and validated bleeding edge threshold |
| 871 | + if total_path_length <= include_path_threshold: |
| 872 | + return env.Object(node) |
645 | 873 |
|
646 |
| - # Apply include path shortening |
647 | 874 | return apply_include_shortening(env, node, includes, total_path_length)
|
648 | 875 |
|
649 | 876 | def get_frameworks_in_current_env():
|
@@ -697,7 +924,7 @@ def get_frameworks_in_current_env():
|
697 | 924 | env.AddPostAction("checkprogsize", silent_action)
|
698 | 925 |
|
699 | 926 | if IS_WINDOWS:
|
700 |
| - # Smart include path optimization based on total path length |
| 927 | + # Smart include path optimization based on bleeding edge configurable threshold |
701 | 928 | env.AddBuildMiddleware(smart_include_length_shorten)
|
702 | 929 |
|
703 | 930 | build_script_path = join(FRAMEWORK_DIR, "tools", "pioarduino-build.py")
|
|
0 commit comments