From e0f2822b30630537c9aadd62fe10d41519fd2d72 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Sun, 10 Aug 2025 18:40:04 +0200 Subject: [PATCH 01/26] Update main.py --- builder/main.py | 309 ++---------------------------------------------- 1 file changed, 8 insertions(+), 301 deletions(-) diff --git a/builder/main.py b/builder/main.py index 197634114..a9d4a8e36 100644 --- a/builder/main.py +++ b/builder/main.py @@ -13,11 +13,8 @@ # limitations under the License. import locale -import json import os import re -import site -import semantic_version import shlex import subprocess import sys @@ -33,34 +30,9 @@ ) from platformio.project.helpers import get_project_dir -from platformio.package.version import pepver_to_semver from platformio.util import get_serial_ports from platformio.compat import IS_WINDOWS - -# Check Python version requirement -if sys.version_info < (3, 10): - sys.stderr.write( - f"Error: Python 3.10 or higher is required. " - f"Current version: {sys.version_info.major}.{sys.version_info.minor}.{sys.version_info.micro}\n" - f"Please update your Python installation.\n" - ) - sys.exit(1) - -# Python dependencies required for the build process -python_deps = { - "uv": ">=0.1.0", - "platformio": "https://github.com/pioarduino/platformio-core/archive/refs/tags/v6.1.18.zip", - "pyyaml": ">=6.0.2", - "rich-click": ">=1.8.6", - "zopfli": ">=0.2.2", - "intelhex": ">=2.3.0", - "rich": ">=14.0.0", - "cryptography": ">=45.0.3", - "ecdsa": ">=0.19.1", - "bitstring": ">=4.3.1", - "reedsolo": ">=1.5.3,<1.8", - "esp-idf-size": ">=1.6.1" -} +from penv_setup import setup_python_environment # Initialize environment and configuration env = DefaultEnvironment() @@ -70,270 +42,8 @@ FRAMEWORK_DIR = platform.get_package_dir("framework-arduinoespressif32") platformio_dir = projectconfig.get("platformio", "core_dir") -# Global Python executable path, replaced later with venv python path -PYTHON_EXE = env.subst("$PYTHONEXE") -penv_dir = os.path.join(platformio_dir, "penv") - - -def get_executable_path(executable_name): - """ - Get the path to an executable based on the penv_dir. - """ - exe_suffix = ".exe" if IS_WINDOWS else "" - scripts_dir = "Scripts" if IS_WINDOWS else "bin" - - return os.path.join(penv_dir, scripts_dir, f"{executable_name}{exe_suffix}") - - -def setup_pipenv_in_package(): - """ - Checks if 'penv' folder exists in platformio dir and creates virtual environment if not. - """ - if not os.path.exists(penv_dir): - env.Execute( - env.VerboseAction( - '"$PYTHONEXE" -m venv --clear "%s"' % penv_dir, - "Creating pioarduino Python virtual environment: %s" % penv_dir, - ) - ) - assert os.path.isfile( - get_executable_path("pip") - ), "Error: Failed to create a proper virtual environment. Missing the `pip` binary!" - - -# Setup virtual environment if needed -setup_pipenv_in_package() - -# Set Python Scons Var to env Python -penv_python = get_executable_path("python") -env.Replace(PYTHONEXE=penv_python) -PYTHON_EXE = penv_python - -# check for python binary, exit with error when not found -assert os.path.isfile(PYTHON_EXE), f"Python executable not found: {PYTHON_EXE}" - - -def setup_python_paths(): - """Setup Python module search paths using the penv_dir.""" - # Add penv_dir to module search path - site.addsitedir(penv_dir) - - # Add site-packages directory - python_ver = f"python{sys.version_info.major}.{sys.version_info.minor}" - site_packages = ( - os.path.join(penv_dir, "Lib", "site-packages") if IS_WINDOWS - else os.path.join(penv_dir, "lib", python_ver, "site-packages") - ) - - if os.path.isdir(site_packages): - site.addsitedir(site_packages) - - -setup_python_paths() - -# Set executable paths from tools -esptool_binary_path = get_executable_path("esptool") -uv_executable = get_executable_path("uv") - - -def get_packages_to_install(deps, installed_packages): - """ - Generator for Python packages that need to be installed. - - Args: - deps (dict): Dictionary of package names and version specifications - installed_packages (dict): Dictionary of currently installed packages - - Yields: - str: Package name that needs to be installed - """ - for package, spec in deps.items(): - if package not in installed_packages: - yield package - elif package == "platformio": - # Enforce the version from the direct URL if it looks like one. - # If version can't be parsed, fall back to accepting any installed version. - m = re.search(r'/v?(\d+\.\d+\.\d+(?:\.\d+)?)(?:\.(?:zip|tar\.gz|tar\.bz2))?$', spec) - if m: - expected_ver = semantic_version.Version(m.group(1)) - if installed_packages.get(package) != expected_ver: - # Reinstall to align with the pinned URL version - yield package - else: - continue - else: - version_spec = semantic_version.Spec(spec) - if not version_spec.match(installed_packages[package]): - yield package - - -def install_python_deps(): - """ - Ensure uv package manager is available and install required Python dependencies. - - Returns: - bool: True if successful, False otherwise - """ - try: - result = subprocess.run( - [uv_executable, "--version"], - capture_output=True, - text=True, - timeout=3 - ) - uv_available = result.returncode == 0 - except (FileNotFoundError, subprocess.TimeoutExpired): - uv_available = False - - if not uv_available: - try: - result = subprocess.run( - [PYTHON_EXE, "-m", "pip", "install", "uv>=0.1.0", "-q", "-q", "-q"], - capture_output=True, - text=True, - timeout=30 # 30 second timeout - ) - if result.returncode != 0: - if result.stderr: - print(f"Error output: {result.stderr.strip()}") - return False - - except subprocess.TimeoutExpired: - print("Error: uv installation timed out") - return False - except FileNotFoundError: - print("Error: Python executable not found") - return False - except Exception as e: - print(f"Error installing uv package manager: {e}") - return False - - - def _get_installed_uv_packages(): - """ - Get list of installed packages in virtual env 'penv' using uv. - - Returns: - dict: Dictionary of installed packages with versions - """ - result = {} - try: - cmd = [uv_executable, "pip", "list", f"--python={PYTHON_EXE}", "--format=json"] - result_obj = subprocess.run( - cmd, - capture_output=True, - text=True, - encoding='utf-8', - timeout=30 # 30 second timeout - ) - - if result_obj.returncode == 0: - content = result_obj.stdout.strip() - if content: - packages = json.loads(content) - for p in packages: - result[p["name"]] = pepver_to_semver(p["version"]) - else: - print(f"Warning: uv pip list failed with exit code {result_obj.returncode}") - if result_obj.stderr: - print(f"Error output: {result_obj.stderr.strip()}") - - except subprocess.TimeoutExpired: - print("Warning: uv pip list command timed out") - except (json.JSONDecodeError, KeyError) as e: - print(f"Warning: Could not parse package list: {e}") - except FileNotFoundError: - print("Warning: uv command not found") - except Exception as e: - print(f"Warning! Couldn't extract the list of installed Python packages: {e}") - - return result - - installed_packages = _get_installed_uv_packages() - packages_to_install = list(get_packages_to_install(python_deps, installed_packages)) - - if packages_to_install: - packages_list = [] - for p in packages_to_install: - spec = python_deps[p] - if spec.startswith(('http://', 'https://', 'git+', 'file://')): - packages_list.append(spec) - else: - packages_list.append(f"{p}{spec}") - - cmd = [ - uv_executable, "pip", "install", - f"--python={PYTHON_EXE}", - "--quiet", "--upgrade" - ] + packages_list - - try: - result = subprocess.run( - cmd, - capture_output=True, - text=True, - timeout=30 # 30 second timeout for package installation - ) - - if result.returncode != 0: - print(f"Error: Failed to install Python dependencies (exit code: {result.returncode})") - if result.stderr: - print(f"Error output: {result.stderr.strip()}") - return False - - except subprocess.TimeoutExpired: - print("Error: Python dependencies installation timed out") - return False - except FileNotFoundError: - print("Error: uv command not found") - return False - except Exception as e: - print(f"Error installing Python dependencies: {e}") - return False - - return True - - -def install_esptool(): - """ - Install esptool from package folder "tool-esptoolpy" using uv package manager. - - Raises: - SystemExit: If esptool installation fails - """ - try: - subprocess.check_call( - [PYTHON_EXE, "-c", "import esptool"], - stdout=subprocess.DEVNULL, - stderr=subprocess.DEVNULL - ) - return - except (subprocess.CalledProcessError, FileNotFoundError): - pass - - esptool_repo_path = env.subst(platform.get_package_dir("tool-esptoolpy") or "") - if not esptool_repo_path or not os.path.isdir(esptool_repo_path): - print("Error: esptool package directory not found") - sys.exit(1) - - try: - subprocess.check_call([ - uv_executable, "pip", "install", "--quiet", - f"--python={PYTHON_EXE}", - "-e", esptool_repo_path - ]) - - return - - except subprocess.CalledProcessError as e: - print(f"Error: Failed to install esptool: {e}") - sys.exit(1) - - -# Install espressif32 Python dependencies -install_python_deps() -# Install esptool after dependencies -install_esptool() +# Setup Python virtual environment and get executable paths +PYTHON_EXE, esptool_binary_path = setup_python_environment(env, platform, platformio_dir) def BeforeUpload(target, source, env): @@ -708,7 +418,7 @@ def switch_off_ldf(): filesystem = board.get("build.filesystem", "littlefs") # Set toolchain architecture for RISC-V based ESP32 variants -if mcu in ("esp32c2", "esp32c3", "esp32c5", "esp32c6", "esp32h2", "esp32p4"): +if mcu not in ("esp32", "esp32s2", "esp32s3"): toolchain_arch = "riscv32-esp" # Initialize integration extra data if not present @@ -736,13 +446,10 @@ def switch_off_ldf(): GDB=join( platform.get_package_dir( "tool-riscv32-esp-elf-gdb" - if mcu in ( - "esp32c2", - "esp32c3", - "esp32c5", - "esp32c6", - "esp32h2", - "esp32p4", + if mcu not in ( + "esp32", + "esp32s2", + "esp32s3", ) else "tool-xtensa-esp-elf-gdb" ) From 9e4d64a8a15293b9535ca607cf3be7dcd0fb255a Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Sun, 10 Aug 2025 18:40:59 +0200 Subject: [PATCH 02/26] Create penv_setup.py --- builder/penv_setup.py | 344 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 344 insertions(+) create mode 100644 builder/penv_setup.py diff --git a/builder/penv_setup.py b/builder/penv_setup.py new file mode 100644 index 000000000..a8786a9c6 --- /dev/null +++ b/builder/penv_setup.py @@ -0,0 +1,344 @@ +# Copyright 2014-present PlatformIO +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import json +import os +import re +import site +import semantic_version +import subprocess +import sys + +from platformio.package.version import pepver_to_semver +from platformio.compat import IS_WINDOWS + +# Python dependencies required for the build process +python_deps = { + "uv": ">=0.1.0", + "platformio": "https://github.com/pioarduino/platformio-core/archive/refs/tags/v6.1.18.zip", + "pyyaml": ">=6.0.2", + "rich-click": ">=1.8.6", + "zopfli": ">=0.2.2", + "intelhex": ">=2.3.0", + "rich": ">=14.0.0", + "cryptography": ">=45.0.3", + "ecdsa": ">=0.19.1", + "bitstring": ">=4.3.1", + "reedsolo": ">=1.5.3,<1.8", + "esp-idf-size": ">=1.6.1" +} + + +def get_executable_path(penv_dir, executable_name): + """ + Get the path to an executable based on the penv_dir. + """ + exe_suffix = ".exe" if IS_WINDOWS else "" + scripts_dir = "Scripts" if IS_WINDOWS else "bin" + + return os.path.join(penv_dir, scripts_dir, f"{executable_name}{exe_suffix}") + + +def setup_pipenv_in_package(env, penv_dir): + """ + Checks if 'penv' folder exists in platformio dir and creates virtual environment if not. + """ + if not os.path.exists(penv_dir): + env.Execute( + env.VerboseAction( + '"$PYTHONEXE" -m venv --clear "%s"' % penv_dir, + "Creating pioarduino Python virtual environment: %s" % penv_dir, + ) + ) + assert os.path.isfile( + get_executable_path(penv_dir, "pip") + ), "Error: Failed to create a proper virtual environment. Missing the `pip` binary!" + + +def setup_python_paths(penv_dir): + """Setup Python module search paths using the penv_dir.""" + # Add penv_dir to module search path + site.addsitedir(penv_dir) + + # Add site-packages directory + python_ver = f"python{sys.version_info.major}.{sys.version_info.minor}" + site_packages = ( + os.path.join(penv_dir, "Lib", "site-packages") if IS_WINDOWS + else os.path.join(penv_dir, "lib", python_ver, "site-packages") + ) + + if os.path.isdir(site_packages): + site.addsitedir(site_packages) + + +def get_packages_to_install(deps, installed_packages): + """ + Generator for Python packages that need to be installed. + Compares package names case-insensitively. + + Args: + deps (dict): Dictionary of package names and version specifications + installed_packages (dict): Dictionary of currently installed packages (keys should be lowercase) + + Yields: + str: Package name that needs to be installed + """ + for package, spec in deps.items(): + name = package.lower() + if name not in installed_packages: + yield package + elif name == "platformio": + # Enforce the version from the direct URL if it looks like one. + # If version can't be parsed, fall back to accepting any installed version. + m = re.search(r'/v?(\d+\.\d+\.\d+(?:\.\d+)?)(?:\.(?:zip|tar\.gz|tar\.bz2))?$', spec) + if m: + expected_ver = pepver_to_semver(m.group(1)) + if installed_packages.get(name) != expected_ver: + # Reinstall to align with the pinned URL version + yield package + else: + continue + else: + version_spec = semantic_version.SimpleSpec(spec) + if not version_spec.match(installed_packages[name]): + yield package + + +def install_python_deps(python_exe, uv_executable): + """ + Ensure uv package manager is available and install required Python dependencies. + + Returns: + bool: True if successful, False otherwise + """ + try: + result = subprocess.run( + [uv_executable, "--version"], + capture_output=True, + text=True, + timeout=3 + ) + uv_available = result.returncode == 0 + except (FileNotFoundError, subprocess.TimeoutExpired): + uv_available = False + + if not uv_available: + try: + result = subprocess.run( + [python_exe, "-m", "pip", "install", "uv>=0.1.0", "-q", "-q", "-q"], + capture_output=True, + text=True, + timeout=30 # 30 second timeout + ) + if result.returncode != 0: + if result.stderr: + print(f"Error output: {result.stderr.strip()}") + return False + + except subprocess.TimeoutExpired: + print("Error: uv installation timed out") + return False + except FileNotFoundError: + print("Error: Python executable not found") + return False + except Exception as e: + print(f"Error installing uv package manager: {e}") + return False + + + def _get_installed_uv_packages(): + """ + Get list of installed packages in virtual env 'penv' using uv. + + Returns: + dict: Dictionary of installed packages with versions + """ + result = {} + try: + cmd = [uv_executable, "pip", "list", f"--python={python_exe}", "--format=json"] + result_obj = subprocess.run( + cmd, + capture_output=True, + text=True, + encoding='utf-8', + timeout=30 # 30 second timeout + ) + + if result_obj.returncode == 0: + content = result_obj.stdout.strip() + if content: + packages = json.loads(content) + for p in packages: + result[p["name"].lower()] = pepver_to_semver(p["version"]) + else: + print(f"Warning: uv pip list failed with exit code {result_obj.returncode}") + if result_obj.stderr: + print(f"Error output: {result_obj.stderr.strip()}") + + except subprocess.TimeoutExpired: + print("Warning: uv pip list command timed out") + except (json.JSONDecodeError, KeyError) as e: + print(f"Warning: Could not parse package list: {e}") + except FileNotFoundError: + print("Warning: uv command not found") + except Exception as e: + print(f"Warning! Couldn't extract the list of installed Python packages: {e}") + + return result + + installed_packages = _get_installed_uv_packages() + packages_to_install = list(get_packages_to_install(python_deps, installed_packages)) + + if packages_to_install: + packages_list = [] + for p in packages_to_install: + spec = python_deps[p] + if spec.startswith(('http://', 'https://', 'git+', 'file://')): + packages_list.append(spec) + else: + packages_list.append(f"{p}{spec}") + + cmd = [ + uv_executable, "pip", "install", + f"--python={python_exe}", + "--quiet", "--upgrade" + ] + packages_list + + try: + result = subprocess.run( + cmd, + capture_output=True, + text=True, + timeout=30 # 30 second timeout for package installation + ) + + if result.returncode != 0: + print(f"Error: Failed to install Python dependencies (exit code: {result.returncode})") + if result.stderr: + print(f"Error output: {result.stderr.strip()}") + return False + + except subprocess.TimeoutExpired: + print("Error: Python dependencies installation timed out") + return False + except FileNotFoundError: + print("Error: uv command not found") + return False + except Exception as e: + print(f"Error installing Python dependencies: {e}") + return False + + return True + + +def install_esptool(env, platform, python_exe, uv_executable): + """ + Install esptool from package folder "tool-esptoolpy" using uv package manager. + Ensures esptool is installed from the specific tool-esptoolpy package directory. + + Args: + env: SCons environment object + platform: PlatformIO platform object + python_exe (str): Path to Python executable in virtual environment + uv_executable (str): Path to uv executable + + Raises: + SystemExit: If esptool installation fails or package directory not found + """ + esptool_repo_path = env.subst(platform.get_package_dir("tool-esptoolpy") or "") + if not esptool_repo_path or not os.path.isdir(esptool_repo_path): + sys.exit(1) + + # Check if esptool is already installed from the correct path + try: + result = subprocess.run( + [python_exe, "-c", + "import esptool; " + "import os; " + f"expected_path = os.path.normpath(r'{esptool_repo_path}'); " + "actual_path = os.path.normpath(os.path.dirname(esptool.__file__)); " + "print('MATCH' if expected_path in actual_path else 'MISMATCH')"], + capture_output=True, + text=True, + timeout=5 + ) + + if result.returncode == 0 and "MATCH" in result.stdout: + return + + except (subprocess.CalledProcessError, subprocess.TimeoutExpired, FileNotFoundError): + pass + + try: + subprocess.check_call([ + uv_executable, "pip", "install", "--quiet", "--force-reinstall", + f"--python={python_exe}", + "-e", esptool_repo_path + ]) + + except subprocess.CalledProcessError: + sys.exit(1) + + +def setup_python_environment(env, platform, platformio_dir): + """ + Main function to setup the Python virtual environment and dependencies. + + Args: + env: SCons environment object + platform: PlatformIO platform object + platformio_dir (str): Path to PlatformIO core directory + + Returns: + tuple[str, str]: (Path to penv Python executable, Path to esptool script) + + Raises: + SystemExit: If Python version < 3.10 or dependency installation fails + """ + # Check Python version requirement + if sys.version_info < (3, 10): + sys.stderr.write( + f"Error: Python 3.10 or higher is required. " + f"Current version: {sys.version_info.major}.{sys.version_info.minor}.{sys.version_info.micro}\n" + f"Please update your Python installation.\n" + ) + sys.exit(1) + + penv_dir = os.path.join(platformio_dir, "penv") + + # Setup virtual environment if needed + setup_pipenv_in_package(env, penv_dir) + + # Set Python Scons Var to env Python + penv_python = get_executable_path(penv_dir, "python") + env.Replace(PYTHONEXE=penv_python) + + # check for python binary, exit with error when not found + assert os.path.isfile(penv_python), f"Python executable not found: {penv_python}" + + # Setup Python module search paths + setup_python_paths(penv_dir) + + # Set executable paths from tools + esptool_binary_path = get_executable_path(penv_dir, "esptool") + uv_executable = get_executable_path(penv_dir, "uv") + + # Install espressif32 Python dependencies + if not install_python_deps(penv_python, uv_executable): + sys.stderr.write("Error: Failed to install Python dependencies into penv\n") + sys.exit(1) + # Install esptool after dependencies + install_esptool(env, platform, penv_python, uv_executable) + + return penv_python, esptool_binary_path From 72d9bb65c88cb3862975f2ce9956c2f92836eb95 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Sun, 10 Aug 2025 18:41:49 +0200 Subject: [PATCH 03/26] Update _embed_files.py --- builder/frameworks/_embed_files.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/builder/frameworks/_embed_files.py b/builder/frameworks/_embed_files.py index b114fbcee..a2de784b7 100644 --- a/builder/frameworks/_embed_files.py +++ b/builder/frameworks/_embed_files.py @@ -110,14 +110,14 @@ def transform_to_asm(target, source, env): " ".join( [ "riscv32-esp-elf-objcopy" - if mcu in ("esp32c2","esp32c3","esp32c5","esp32c6","esp32h2","esp32p4") + if mcu not in ("esp32","esp32s2","esp32s3") else "xtensa-%s-elf-objcopy" % mcu, "--input-target", "binary", "--output-target", - "elf32-littleriscv" if mcu in ("esp32c2","esp32c3","esp32c5","esp32c6","esp32h2","esp32p4") else "elf32-xtensa-le", + "elf32-littleriscv" if mcu not in ("esp32","esp32s2","esp32s3") else "elf32-xtensa-le", "--binary-architecture", - "riscv" if mcu in ("esp32c2","esp32c3","esp32c5","esp32c6","esp32h2","esp32p4") else "xtensa", + "riscv" if mcu not in ("esp32","esp32s2","esp32s3") else "xtensa", "--rename-section", ".data=.rodata.embedded", "$SOURCE", From 82b291d173114cf2bdbe118cb267fc4b749d7f4c Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Sun, 10 Aug 2025 18:42:38 +0200 Subject: [PATCH 04/26] Update ulp.py --- builder/frameworks/ulp.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/builder/frameworks/ulp.py b/builder/frameworks/ulp.py index 22a591cfb..d284a5e03 100644 --- a/builder/frameworks/ulp.py +++ b/builder/frameworks/ulp.py @@ -37,7 +37,7 @@ def prepare_ulp_env_vars(env): toolchain_path = platform.get_package_dir( "toolchain-xtensa-esp-elf" - if idf_variant not in ("esp32c5","esp32c6", "esp32p4") + if idf_variant in ("esp32","esp32s2","esp32s3") else "toolchain-riscv32-esp" ) From 487b0a5e4bad7e1b5d43a5f065fda9700115043a Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Sun, 10 Aug 2025 19:04:51 +0200 Subject: [PATCH 05/26] enhance regex for detection of more version variants --- builder/penv_setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/builder/penv_setup.py b/builder/penv_setup.py index a8786a9c6..6153849df 100644 --- a/builder/penv_setup.py +++ b/builder/penv_setup.py @@ -101,7 +101,7 @@ def get_packages_to_install(deps, installed_packages): elif name == "platformio": # Enforce the version from the direct URL if it looks like one. # If version can't be parsed, fall back to accepting any installed version. - m = re.search(r'/v?(\d+\.\d+\.\d+(?:\.\d+)?)(?:\.(?:zip|tar\.gz|tar\.bz2))?$', spec) + m = re.search(r'/v?(\d+\.\d+\.\d+(?:[.-]\w+)?(?:\.\d+)?)(?:\.(?:zip|tar\.gz|tar\.bz2))?$', spec) if m: expected_ver = pepver_to_semver(m.group(1)) if installed_packages.get(name) != expected_ver: From 104bab8a8dc0353eb3f6a9f747d586814039906f Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Sun, 10 Aug 2025 20:31:24 +0200 Subject: [PATCH 06/26] Update penv_setup.py --- builder/penv_setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/builder/penv_setup.py b/builder/penv_setup.py index 6153849df..c09d6781a 100644 --- a/builder/penv_setup.py +++ b/builder/penv_setup.py @@ -274,7 +274,7 @@ def install_esptool(env, platform, python_exe, uv_executable): timeout=5 ) - if result.returncode == 0 and "MATCH" in result.stdout: + if result.returncode == 0 and result.stdout.strip() == "MATCH": return except (subprocess.CalledProcessError, subprocess.TimeoutExpired, FileNotFoundError): From 1d2b07abc8f60f153e59f200deb1fbd29b7c5693 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Sun, 10 Aug 2025 20:32:15 +0200 Subject: [PATCH 07/26] Update main.py --- builder/main.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/builder/main.py b/builder/main.py index a9d4a8e36..1c96e710d 100644 --- a/builder/main.py +++ b/builder/main.py @@ -772,7 +772,7 @@ def firmware_metrics(target, source, env): "detect", "$FS_START", ], - UPLOADCMD='"$UPLOADER" $UPLOADERFLAGS $SOURCE', + UPLOADCMD='$UPLOADER $UPLOADERFLAGS $SOURCE', ) upload_actions = [ From 9e391f590b78de951841533b4109ba46a3161133 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Sun, 10 Aug 2025 20:37:04 +0200 Subject: [PATCH 08/26] no duplicate append of cmd --- builder/main.py | 1 - 1 file changed, 1 deletion(-) diff --git a/builder/main.py b/builder/main.py index 1c96e710d..48465f411 100644 --- a/builder/main.py +++ b/builder/main.py @@ -599,7 +599,6 @@ def firmware_metrics(target, source, env): dash_index = sys.argv.index("--") if dash_index + 1 < len(sys.argv): cli_args = sys.argv[dash_index + 1:] - cmd.extend(cli_args) # Add CLI arguments before the map file if cli_args: From d4c8d2aa8a1e72a4e96efcf1481d3bee86f04a1b Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Sun, 10 Aug 2025 20:47:09 +0200 Subject: [PATCH 09/26] Update penv_setup.py --- builder/penv_setup.py | 1 + 1 file changed, 1 insertion(+) diff --git a/builder/penv_setup.py b/builder/penv_setup.py index c09d6781a..1bda45abd 100644 --- a/builder/penv_setup.py +++ b/builder/penv_setup.py @@ -270,6 +270,7 @@ def install_esptool(env, platform, python_exe, uv_executable): "actual_path = os.path.normpath(os.path.dirname(esptool.__file__)); " "print('MATCH' if expected_path in actual_path else 'MISMATCH')"], capture_output=True, + check=True, text=True, timeout=5 ) From be3388b7f21f46dd603baa77a5535b45102b6f00 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Sun, 10 Aug 2025 20:57:26 +0200 Subject: [PATCH 10/26] avoid possible issues with Windows --- builder/penv_setup.py | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/builder/penv_setup.py b/builder/penv_setup.py index 1bda45abd..4b43906a5 100644 --- a/builder/penv_setup.py +++ b/builder/penv_setup.py @@ -263,12 +263,17 @@ def install_esptool(env, platform, python_exe, uv_executable): # Check if esptool is already installed from the correct path try: result = subprocess.run( - [python_exe, "-c", - "import esptool; " - "import os; " - f"expected_path = os.path.normpath(r'{esptool_repo_path}'); " - "actual_path = os.path.normpath(os.path.dirname(esptool.__file__)); " - "print('MATCH' if expected_path in actual_path else 'MISMATCH')"], + [ + python_exe, + "-c", + ( + "import esptool, os, sys; " + "expected_path = os.path.normcase(os.path.realpath(sys.argv[1])); " + "actual_path = os.path.normcase(os.path.realpath(os.path.dirname(esptool.__file__))); " + "print('MATCH' if actual_path.startswith(expected_path) else 'MISMATCH')" + ), + esptool_repo_path, + ], capture_output=True, check=True, text=True, From e4816606710c0ead52b4bcba4042f10b24922789 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Sun, 10 Aug 2025 21:22:11 +0200 Subject: [PATCH 11/26] remove the impossible error for subprocess --- builder/main.py | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/builder/main.py b/builder/main.py index 48465f411..426fc5601 100644 --- a/builder/main.py +++ b/builder/main.py @@ -616,10 +616,7 @@ def firmware_metrics(target, source, env): if result.returncode != 0: print(f"Warning: esp-idf-size exited with code {result.returncode}") - - except ImportError: - print("Error: esp-idf-size module not found.") - print("Install with: pip install esp-idf-size") + except FileNotFoundError: print("Error: Python executable not found.") print("Check your Python installation.") From 20eac8fd5a8e0576875bb975e9b312cf4a681da5 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Sun, 10 Aug 2025 21:30:22 +0200 Subject: [PATCH 12/26] add error message for esptool --- builder/penv_setup.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/builder/penv_setup.py b/builder/penv_setup.py index 4b43906a5..2b82a7153 100644 --- a/builder/penv_setup.py +++ b/builder/penv_setup.py @@ -258,6 +258,9 @@ def install_esptool(env, platform, python_exe, uv_executable): """ esptool_repo_path = env.subst(platform.get_package_dir("tool-esptoolpy") or "") if not esptool_repo_path or not os.path.isdir(esptool_repo_path): + sys.stderr.write( + f"Error: 'tool-esptoolpy' package directory not found: {esptool_repo_path!r}\n" + ) sys.exit(1) # Check if esptool is already installed from the correct path @@ -293,7 +296,10 @@ def install_esptool(env, platform, python_exe, uv_executable): "-e", esptool_repo_path ]) - except subprocess.CalledProcessError: + except subprocess.CalledProcessError as e: + sys.stderr.write( + f"Error: Failed to install esptool from {esptool_repo_path} (exit {e.returncode})\n" + ) sys.exit(1) From 55be1519c2114713b50313c0d2dbec67c4f6b67f Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Sun, 10 Aug 2025 21:40:03 +0200 Subject: [PATCH 13/26] move regex as constant to top --- builder/penv_setup.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/builder/penv_setup.py b/builder/penv_setup.py index 2b82a7153..58c294e16 100644 --- a/builder/penv_setup.py +++ b/builder/penv_setup.py @@ -23,6 +23,11 @@ from platformio.package.version import pepver_to_semver from platformio.compat import IS_WINDOWS +PLATFORMIO_URL_VERSION_RE = re.compile( + r'/v?(\d+\.\d+\.\d+(?:[.-]\w+)?(?:\.\d+)?)(?:\.(?:zip|tar\.gz|tar\.bz2))?$', + re.IGNORECASE, +) + # Python dependencies required for the build process python_deps = { "uv": ">=0.1.0", @@ -101,7 +106,7 @@ def get_packages_to_install(deps, installed_packages): elif name == "platformio": # Enforce the version from the direct URL if it looks like one. # If version can't be parsed, fall back to accepting any installed version. - m = re.search(r'/v?(\d+\.\d+\.\d+(?:[.-]\w+)?(?:\.\d+)?)(?:\.(?:zip|tar\.gz|tar\.bz2))?$', spec) + m = PLATFORMIO_URL_VERSION_RE.search(spec) if m: expected_ver = pepver_to_semver(m.group(1)) if installed_packages.get(name) != expected_ver: From f1370e7060383dbe9a066fd4954c2b8148f2b241 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Sun, 10 Aug 2025 21:56:33 +0200 Subject: [PATCH 14/26] Update penv_setup.py --- builder/penv_setup.py | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/builder/penv_setup.py b/builder/penv_setup.py index 58c294e16..12e180ed6 100644 --- a/builder/penv_setup.py +++ b/builder/penv_setup.py @@ -55,7 +55,7 @@ def get_executable_path(penv_dir, executable_name): return os.path.join(penv_dir, scripts_dir, f"{executable_name}{exe_suffix}") -def setup_pipenv_in_package(env, penv_dir): +def setup_env_in_package(env, penv_dir): """ Checks if 'penv' folder exists in platformio dir and creates virtual environment if not. """ @@ -335,7 +335,7 @@ def setup_python_environment(env, platform, platformio_dir): penv_dir = os.path.join(platformio_dir, "penv") # Setup virtual environment if needed - setup_pipenv_in_package(env, penv_dir) + setup_env_in_package(env, penv_dir) # Set Python Scons Var to env Python penv_python = get_executable_path(penv_dir, "python") @@ -347,15 +347,17 @@ def setup_python_environment(env, platform, platformio_dir): # Setup Python module search paths setup_python_paths(penv_dir) - # Set executable paths from tools - esptool_binary_path = get_executable_path(penv_dir, "esptool") + # Set executable path from tool uv uv_executable = get_executable_path(penv_dir, "uv") # Install espressif32 Python dependencies if not install_python_deps(penv_python, uv_executable): sys.stderr.write("Error: Failed to install Python dependencies into penv\n") sys.exit(1) + # Install esptool after dependencies install_esptool(env, platform, penv_python, uv_executable) - + # Set executable path from tool esptool + esptool_binary_path = get_executable_path(penv_dir, "esptool") + return penv_python, esptool_binary_path From aaaccf6e713059e9726569a10170f2d9749070e0 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Sun, 10 Aug 2025 22:00:36 +0200 Subject: [PATCH 15/26] simplify if --- builder/penv_setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/builder/penv_setup.py b/builder/penv_setup.py index 12e180ed6..faa772a4d 100644 --- a/builder/penv_setup.py +++ b/builder/penv_setup.py @@ -288,7 +288,7 @@ def install_esptool(env, platform, python_exe, uv_executable): timeout=5 ) - if result.returncode == 0 and result.stdout.strip() == "MATCH": + if result.stdout.strip() == "MATCH": return except (subprocess.CalledProcessError, subprocess.TimeoutExpired, FileNotFoundError): From 38eb7a458b97863b7aaf15ad75a27551fc643660 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Sun, 10 Aug 2025 23:47:27 +0200 Subject: [PATCH 16/26] Update main.py --- builder/main.py | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/builder/main.py b/builder/main.py index 426fc5601..f3903decd 100644 --- a/builder/main.py +++ b/builder/main.py @@ -414,11 +414,12 @@ def switch_off_ldf(): # Initialize board configuration and MCU settings board = env.BoardConfig() mcu = board.get("build.mcu", "esp32") +is_xtensa = mcu in ("esp32","esp32s2","esp32s3") toolchain_arch = "xtensa-%s" % mcu filesystem = board.get("build.filesystem", "littlefs") # Set toolchain architecture for RISC-V based ESP32 variants -if mcu not in ("esp32", "esp32s2", "esp32s3"): +if not is_xtensa: toolchain_arch = "riscv32-esp" # Initialize integration extra data if not present @@ -426,7 +427,7 @@ def switch_off_ldf(): env["INTEGRATION_EXTRA_DATA"] = {} # Take care of possible whitespaces in path -objcopy_value = ( +uploader_path = ( f'"{esptool_binary_path}"' if ' ' in esptool_binary_path else esptool_binary_path @@ -446,18 +447,14 @@ def switch_off_ldf(): GDB=join( platform.get_package_dir( "tool-riscv32-esp-elf-gdb" - if mcu not in ( - "esp32", - "esp32s2", - "esp32s3", - ) + if not is_xtensa else "tool-xtensa-esp-elf-gdb" ) or "", "bin", "%s-elf-gdb" % toolchain_arch, ), - OBJCOPY=objcopy_value, + OBJCOPY=uploader_path, RANLIB="%s-elf-gcc-ranlib" % toolchain_arch, SIZETOOL="%s-elf-size" % toolchain_arch, ARFLAGS=["rc"], @@ -467,7 +464,7 @@ def switch_off_ldf(): SIZECHECKCMD="$SIZETOOL -A -d $SOURCES", SIZEPRINTCMD="$SIZETOOL -B -d $SOURCES", ERASEFLAGS=["--chip", mcu, "--port", '"$UPLOAD_PORT"'], - ERASECMD='"$OBJCOPY" $ERASEFLAGS erase-flash', + ERASECMD='$OBJCOPY $ERASEFLAGS erase-flash', # mkspiffs package contains two different binaries for IDF and Arduino MKFSTOOL="mk%s" % filesystem + ( @@ -719,7 +716,7 @@ def firmware_metrics(target, source, env): # Configure upload protocol: esptool elif upload_protocol == "esptool": env.Replace( - UPLOADER=objcopy_value, + UPLOADER=uploader_path, UPLOADERFLAGS=[ "--chip", mcu, @@ -794,7 +791,7 @@ def firmware_metrics(target, source, env): "-Q", "-D", ], - UPLOADCMD='"$UPLOADER" $UPLOADERFLAGS "$SOURCE"', + UPLOADCMD='$UPLOADER $UPLOADERFLAGS "$SOURCE"', ) # Configure upload protocol: Debug tools (OpenOCD) From 10de438378cfd15bed58505e6bdc731e910fad90 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Sun, 10 Aug 2025 23:48:24 +0200 Subject: [PATCH 17/26] Update penv_setup.py --- builder/penv_setup.py | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/builder/penv_setup.py b/builder/penv_setup.py index faa772a4d..568220d9a 100644 --- a/builder/penv_setup.py +++ b/builder/penv_setup.py @@ -55,7 +55,7 @@ def get_executable_path(penv_dir, executable_name): return os.path.join(penv_dir, scripts_dir, f"{executable_name}{exe_suffix}") -def setup_env_in_package(env, penv_dir): +def setup_pipenv_in_package(env, penv_dir): """ Checks if 'penv' folder exists in platformio dir and creates virtual environment if not. """ @@ -335,7 +335,7 @@ def setup_python_environment(env, platform, platformio_dir): penv_dir = os.path.join(platformio_dir, "penv") # Setup virtual environment if needed - setup_env_in_package(env, penv_dir) + setup_pipenv_in_package(env, penv_dir) # Set Python Scons Var to env Python penv_python = get_executable_path(penv_dir, "python") @@ -347,17 +347,15 @@ def setup_python_environment(env, platform, platformio_dir): # Setup Python module search paths setup_python_paths(penv_dir) - # Set executable path from tool uv + # Set executable paths from tools + esptool_binary_path = get_executable_path(penv_dir, "esptool") uv_executable = get_executable_path(penv_dir, "uv") # Install espressif32 Python dependencies if not install_python_deps(penv_python, uv_executable): sys.stderr.write("Error: Failed to install Python dependencies into penv\n") sys.exit(1) - # Install esptool after dependencies install_esptool(env, platform, penv_python, uv_executable) - # Set executable path from tool esptool - esptool_binary_path = get_executable_path(penv_dir, "esptool") - + return penv_python, esptool_binary_path From bab33a8aeb53e31319d76a70b8d2fa99246d722c Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Sun, 10 Aug 2025 23:49:43 +0200 Subject: [PATCH 18/26] Update _embed_files.py --- builder/frameworks/_embed_files.py | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/builder/frameworks/_embed_files.py b/builder/frameworks/_embed_files.py index a2de784b7..92c0d4bb2 100644 --- a/builder/frameworks/_embed_files.py +++ b/builder/frameworks/_embed_files.py @@ -21,6 +21,8 @@ Import("env") board = env.BoardConfig() +mcu = board.get("build.mcu", "esp32") +is_xtensa = mcu in ("esp32","esp32s2","esp32s3") # # Embedded files helpers @@ -101,8 +103,7 @@ def transform_to_asm(target, source, env): files = [join("$BUILD_DIR", s.name + ".S") for s in source] return files, source - -mcu = board.get("build.mcu", "esp32") + env.Append( BUILDERS=dict( TxtToBin=Builder( @@ -110,14 +111,14 @@ def transform_to_asm(target, source, env): " ".join( [ "riscv32-esp-elf-objcopy" - if mcu not in ("esp32","esp32s2","esp32s3") + if not is_xtensa else "xtensa-%s-elf-objcopy" % mcu, "--input-target", "binary", "--output-target", - "elf32-littleriscv" if mcu not in ("esp32","esp32s2","esp32s3") else "elf32-xtensa-le", + "elf32-littleriscv" if not is_xtensa else "elf32-xtensa-le", "--binary-architecture", - "riscv" if mcu not in ("esp32","esp32s2","esp32s3") else "xtensa", + "riscv" if not is_xtensa else "xtensa", "--rename-section", ".data=.rodata.embedded", "$SOURCE", From 5d203d2e9d5172c64c4ee193597eac584b063cf6 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Mon, 11 Aug 2025 00:17:23 +0200 Subject: [PATCH 19/26] changes + fix in ULP --- builder/frameworks/ulp.py | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/builder/frameworks/ulp.py b/builder/frameworks/ulp.py index d284a5e03..5619a0185 100644 --- a/builder/frameworks/ulp.py +++ b/builder/frameworks/ulp.py @@ -31,13 +31,14 @@ BUILD_DIR, "esp-idf", project_config["name"].replace("__idf_", ""), "ulp_main" ) +is_xtensa = idf_variant in ("esp32", "esp32s2", "esp32s3") def prepare_ulp_env_vars(env): ulp_env.PrependENVPath("IDF_PATH", FRAMEWORK_DIR) toolchain_path = platform.get_package_dir( "toolchain-xtensa-esp-elf" - if idf_variant in ("esp32","esp32s2","esp32s3") + if is_xtensa else "toolchain-riscv32-esp" ) @@ -47,12 +48,13 @@ def prepare_ulp_env_vars(env): else "" ) + python_dir = os.path.dirname(ulp_env.subst("$PYTHONEXE")) or "" additional_packages = [ toolchain_path, toolchain_path_ulp, platform.get_package_dir("tool-ninja"), os.path.join(platform.get_package_dir("tool-cmake"), "bin"), - os.path.dirname(where_is_program("python")), + python_dir, ] for package in additional_packages: @@ -85,7 +87,7 @@ def _generate_ulp_configuration_action(env, target, source): riscv_ulp_enabled = sdk_config.get("ULP_COPROC_TYPE_RISCV", False) lp_core_ulp_enabled = sdk_config.get("ULP_COPROC_TYPE_LP_CORE", False) - if lp_core_ulp_enabled == False: + if not lp_core_ulp_enabled: ulp_toolchain = "toolchain-%sulp%s.cmake"% ( "" if riscv_ulp_enabled else idf_variant + "-", "-riscv" if riscv_ulp_enabled else "", @@ -93,9 +95,9 @@ def _generate_ulp_configuration_action(env, target, source): else: ulp_toolchain = "toolchain-lp-core-riscv.cmake" - comp_includes = ";".join(get_component_includes(target_config)) - plain_includes = ";".join(app_includes["plain_includes"]) - comp_includes = comp_includes + plain_includes + comp_includes_list = get_component_includes(target_config) + plain_includes_list = app_includes["plain_includes"] + comp_includes = ";".join(comp_includes_list + plain_includes_list) cmd = ( os.path.join(platform.get_package_dir("tool-cmake"), "bin", "cmake"), From f25793704241b83a397142452cb2853699b582f2 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Mon, 11 Aug 2025 00:22:45 +0200 Subject: [PATCH 20/26] Update _embed_files.py --- builder/frameworks/_embed_files.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/builder/frameworks/_embed_files.py b/builder/frameworks/_embed_files.py index 92c0d4bb2..4e2ba2329 100644 --- a/builder/frameworks/_embed_files.py +++ b/builder/frameworks/_embed_files.py @@ -22,7 +22,7 @@ board = env.BoardConfig() mcu = board.get("build.mcu", "esp32") -is_xtensa = mcu in ("esp32","esp32s2","esp32s3") +is_xtensa = mcu in ("esp32", "esp32s2", "esp32s3") # # Embedded files helpers @@ -112,7 +112,7 @@ def transform_to_asm(target, source, env): [ "riscv32-esp-elf-objcopy" if not is_xtensa - else "xtensa-%s-elf-objcopy" % mcu, + else f"xtensa-{mcu}-elf-objcopy", "--input-target", "binary", "--output-target", From 89a60464a1756fb75790da652719b4a730d658f4 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Mon, 11 Aug 2025 00:26:08 +0200 Subject: [PATCH 21/26] Update main.py --- builder/main.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/builder/main.py b/builder/main.py index f3903decd..fffe7a28f 100644 --- a/builder/main.py +++ b/builder/main.py @@ -414,7 +414,7 @@ def switch_off_ldf(): # Initialize board configuration and MCU settings board = env.BoardConfig() mcu = board.get("build.mcu", "esp32") -is_xtensa = mcu in ("esp32","esp32s2","esp32s3") +is_xtensa = mcu in ("esp32", "esp32s2", "esp32s3") toolchain_arch = "xtensa-%s" % mcu filesystem = board.get("build.filesystem", "littlefs") From a0f25f41f4388f1985b3dd33b363f2dfc53cbd84 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Mon, 11 Aug 2025 00:49:02 +0200 Subject: [PATCH 22/26] Update ulp.py --- builder/frameworks/ulp.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/builder/frameworks/ulp.py b/builder/frameworks/ulp.py index 5619a0185..b1d394541 100644 --- a/builder/frameworks/ulp.py +++ b/builder/frameworks/ulp.py @@ -45,7 +45,7 @@ def prepare_ulp_env_vars(env): toolchain_path_ulp = platform.get_package_dir( "toolchain-esp32ulp" if sdk_config.get("ULP_COPROC_TYPE_FSM", False) - else "" + else None ) python_dir = os.path.dirname(ulp_env.subst("$PYTHONEXE")) or "" From 58c2256d7af3b4f01e4e107275af9bf73a838855 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Mon, 11 Aug 2025 01:03:27 +0200 Subject: [PATCH 23/26] Update ulp.py --- builder/frameworks/ulp.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/builder/frameworks/ulp.py b/builder/frameworks/ulp.py index b1d394541..46c3dc976 100644 --- a/builder/frameworks/ulp.py +++ b/builder/frameworks/ulp.py @@ -58,7 +58,8 @@ def prepare_ulp_env_vars(env): ] for package in additional_packages: - ulp_env.PrependENVPath("PATH", package) + if package: + ulp_env.PrependENVPath("PATH", package) def collect_ulp_sources(): From a6550b85d6b63934c2748071b6315b963c50a524 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Mon, 11 Aug 2025 09:55:08 +0200 Subject: [PATCH 24/26] Update ulp.py --- builder/frameworks/ulp.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/builder/frameworks/ulp.py b/builder/frameworks/ulp.py index 46c3dc976..c3b225507 100644 --- a/builder/frameworks/ulp.py +++ b/builder/frameworks/ulp.py @@ -58,7 +58,7 @@ def prepare_ulp_env_vars(env): ] for package in additional_packages: - if package: + if package and os.path.isdir(package): ulp_env.PrependENVPath("PATH", package) From 73f7b8ee0c1a4d693791dc768a1c3d3d468fdc76 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Mon, 11 Aug 2025 10:56:40 +0200 Subject: [PATCH 25/26] Update ulp.py --- builder/frameworks/ulp.py | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/builder/frameworks/ulp.py b/builder/frameworks/ulp.py index c3b225507..c07fc3d3f 100644 --- a/builder/frameworks/ulp.py +++ b/builder/frameworks/ulp.py @@ -96,10 +96,6 @@ def _generate_ulp_configuration_action(env, target, source): else: ulp_toolchain = "toolchain-lp-core-riscv.cmake" - comp_includes_list = get_component_includes(target_config) - plain_includes_list = app_includes["plain_includes"] - comp_includes = ";".join(comp_includes_list + plain_includes_list) - cmd = ( os.path.join(platform.get_package_dir("tool-cmake"), "bin", "cmake"), "-DCMAKE_EXPORT_COMPILE_COMMANDS=ON", @@ -115,7 +111,7 @@ def _generate_ulp_configuration_action(env, target, source): "-DULP_S_SOURCES=%s" % ";".join([fs.to_unix_path(s.get_abspath()) for s in source]), "-DULP_APP_NAME=ulp_main", "-DCOMPONENT_DIR=" + os.path.join(ulp_env.subst("$PROJECT_DIR"), "ulp"), - "-DCOMPONENT_INCLUDES=" + comp_includes, + "-DCOMPONENT_INCLUDES=%s" % ";".join(get_component_includes(target_config)), "-DIDF_TARGET=%s" % idf_variant, "-DIDF_PATH=" + fs.to_unix_path(FRAMEWORK_DIR), "-DSDKCONFIG_HEADER=" + os.path.join(BUILD_DIR, "config", "sdkconfig.h"), From 6d03d991154dd394f68d43471b40341469a6e221 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Mon, 11 Aug 2025 11:01:43 +0200 Subject: [PATCH 26/26] Update ulp.py --- builder/frameworks/ulp.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/builder/frameworks/ulp.py b/builder/frameworks/ulp.py index c07fc3d3f..22a4559a2 100644 --- a/builder/frameworks/ulp.py +++ b/builder/frameworks/ulp.py @@ -96,6 +96,10 @@ def _generate_ulp_configuration_action(env, target, source): else: ulp_toolchain = "toolchain-lp-core-riscv.cmake" + comp_includes_list = get_component_includes(target_config) + plain_includes_list = app_includes["plain_includes"] + comp_includes = ";".join(comp_includes_list + plain_includes_list) + cmd = ( os.path.join(platform.get_package_dir("tool-cmake"), "bin", "cmake"), "-DCMAKE_EXPORT_COMPILE_COMMANDS=ON", @@ -111,7 +115,7 @@ def _generate_ulp_configuration_action(env, target, source): "-DULP_S_SOURCES=%s" % ";".join([fs.to_unix_path(s.get_abspath()) for s in source]), "-DULP_APP_NAME=ulp_main", "-DCOMPONENT_DIR=" + os.path.join(ulp_env.subst("$PROJECT_DIR"), "ulp"), - "-DCOMPONENT_INCLUDES=%s" % ";".join(get_component_includes(target_config)), + "-DCOMPONENT_INCLUDES=%s" % comp_includes, "-DIDF_TARGET=%s" % idf_variant, "-DIDF_PATH=" + fs.to_unix_path(FRAMEWORK_DIR), "-DSDKCONFIG_HEADER=" + os.path.join(BUILD_DIR, "config", "sdkconfig.h"),