21
21
"""
22
22
23
23
import copy
24
+ import importlib .util
24
25
import json
25
26
import subprocess
26
27
import sys
44
45
from platformio .compat import IS_WINDOWS
45
46
from platformio .proc import exec_command
46
47
from platformio .builder .tools .piolib import ProjectAsLibBuilder
47
- from platformio .project .config import ProjectConfig
48
48
from platformio .package .version import get_original_version , pepver_to_semver
49
49
50
50
51
51
env = DefaultEnvironment ()
52
52
env .SConscript ("_embed_files.py" , exports = "env" )
53
+ platform = env .PioPlatform ()
54
+
55
+ _penv_setup_file = os .path .join (platform .get_dir (), "builder" , "penv_setup.py" )
56
+ _spec = importlib .util .spec_from_file_location ("penv_setup" , _penv_setup_file )
57
+ _penv_setup = importlib .util .module_from_spec (_spec )
58
+ _spec .loader .exec_module (_penv_setup ) # type: ignore[attr-defined]
59
+ get_executable_path = _penv_setup .get_executable_path
53
60
54
61
# remove maybe existing old map file in project root
55
62
map_file = os .path .join (env .subst ("$PROJECT_DIR" ), env .subst ("$PROGNAME" ) + ".map" )
59
66
# Allow changes in folders of managed components
60
67
os .environ ["IDF_COMPONENT_OVERWRITE_MANAGED_COMPONENTS" ] = "1"
61
68
62
- platform = env .PioPlatform ()
63
69
config = env .GetProjectConfig ()
64
70
board = env .BoardConfig ()
65
71
mcu = board .get ("build.mcu" , "esp32" )
83
89
if mcu in ("esp32" , "esp32s2" , "esp32s3" )
84
90
else "toolchain-riscv32-esp"
85
91
)
86
-
92
+ PLATFORMIO_DIR = env . subst ( "$PROJECT_CORE_DIR" )
87
93
88
94
assert os .path .isdir (FRAMEWORK_DIR )
89
95
assert os .path .isdir (TOOLCHAIN_DIR )
90
96
97
+
91
98
def create_silent_action (action_func ):
92
99
"""Create a silent SCons action that suppresses output"""
93
100
silent_action = env .Action (action_func )
@@ -351,7 +358,7 @@ def HandleCOMPONENTsettings(env):
351
358
352
359
if flag_custom_sdkonfig == True and "arduino" in env .subst ("$PIOFRAMEWORK" ) and "espidf" not in env .subst ("$PIOFRAMEWORK" ):
353
360
HandleArduinoIDFsettings (env )
354
- LIB_SOURCE = os .path .join (ProjectConfig . get_instance (). get ( "platformio" , "platforms_dir" ), "espressif32" , "builder" , "build_lib" )
361
+ LIB_SOURCE = os .path .join (platform . get_dir () , "builder" , "build_lib" )
355
362
if not bool (os .path .exists (os .path .join (PROJECT_DIR , ".dummy" ))):
356
363
shutil .copytree (LIB_SOURCE , os .path .join (PROJECT_DIR , ".dummy" ))
357
364
PROJECT_SRC_DIR = os .path .join (PROJECT_DIR , ".dummy" )
@@ -1488,9 +1495,13 @@ def generate_mbedtls_bundle(sdk_config):
1488
1495
)
1489
1496
1490
1497
1498
+ def _get_uv_exe ():
1499
+ return get_executable_path (os .path .join (PLATFORMIO_DIR , "penv" ), "uv" )
1500
+
1501
+
1491
1502
def install_python_deps ():
1492
- PYTHON_EXE = env . subst ( "$PYTHONEXE" )
1493
- UV_EXE = os . path . join ( os . path . dirname ( PYTHON_EXE ), "uv" + ( ".exe" if IS_WINDOWS else "" ))
1503
+ UV_EXE = _get_uv_exe ( )
1504
+
1494
1505
def _get_installed_uv_packages (python_exe_path ):
1495
1506
result = {}
1496
1507
try :
@@ -1512,7 +1523,6 @@ def _get_installed_uv_packages(python_exe_path):
1512
1523
return
1513
1524
1514
1525
deps = {
1515
- "uv" : ">=0.1.0" ,
1516
1526
# https://github.com/platformio/platformio-core/issues/4614
1517
1527
"urllib3" : "<2" ,
1518
1528
# https://github.com/platformio/platform-espressif32/issues/635
@@ -1563,9 +1573,7 @@ def get_idf_venv_dir():
1563
1573
# as an IDF component requires a different version of the IDF package and
1564
1574
# hence a different set of Python deps or their versions
1565
1575
idf_version = get_framework_version ()
1566
- return os .path .join (
1567
- env .subst ("$PROJECT_CORE_DIR" ), "penv" , ".espidf-" + idf_version
1568
- )
1576
+ return os .path .join (PLATFORMIO_DIR , "penv" , f".espidf-{ idf_version } " )
1569
1577
1570
1578
1571
1579
def ensure_python_venv_available ():
@@ -1607,11 +1615,7 @@ def _is_venv_outdated(venv_data_file):
1607
1615
return True
1608
1616
1609
1617
def _create_venv (venv_dir ):
1610
- pip_path = os .path .join (
1611
- venv_dir ,
1612
- "Scripts" if IS_WINDOWS else "bin" ,
1613
- "pip" + (".exe" if IS_WINDOWS else "" ),
1614
- )
1618
+ uv_path = _get_uv_exe ()
1615
1619
1616
1620
if os .path .isdir (venv_dir ):
1617
1621
try :
@@ -1624,17 +1628,20 @@ def _create_venv(venv_dir):
1624
1628
)
1625
1629
env .Exit (1 )
1626
1630
1627
- # Use the built-in PlatformIO Python to create a standalone IDF virtual env
1631
+ # Use uv to create a standalone IDF virtual env
1628
1632
env .Execute (
1629
1633
env .VerboseAction (
1630
- '"$PYTHONEXE" -m venv --clear "%s"' % venv_dir ,
1631
- "Creating a new virtual environment for IDF Python dependencies" ,
1634
+ '"%s" venv --clear --quiet --python "%s" "%s" ' % ( uv_path , env . subst ( "$PYTHONEXE" ), venv_dir ) ,
1635
+ "Creating a new virtual environment for IDF Python dependencies using uv " ,
1632
1636
)
1633
1637
)
1634
1638
1639
+ # Verify that the venv was created successfully by checking for Python executable
1640
+ python_path = get_executable_path (venv_dir , "python" )
1641
+
1635
1642
assert os .path .isfile (
1636
- pip_path
1637
- ), "Error: Failed to create a proper virtual environment. Missing the `pip` binary !"
1643
+ python_path
1644
+ ), "Error: Failed to create a proper virtual environment. Missing the Python executable !"
1638
1645
1639
1646
venv_dir = get_idf_venv_dir ()
1640
1647
venv_data_file = os .path .join (venv_dir , "pio-idf-venv.json" )
0 commit comments