Skip to content

Commit f8ec6d4

Browse files
authored
Add tl-install to install tools not in pio registry. Using for install of newer OpenOCD (#148)
1 parent 2bdbd35 commit f8ec6d4

File tree

3 files changed

+94
-32
lines changed

3 files changed

+94
-32
lines changed

examples/arduino-blink/platformio.ini

+1
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,7 @@ custom_component_remove = espressif/esp_hosted
9393
[env:esp32-c6-devkitc-1]
9494
platform = espressif32
9595
framework = arduino
96+
build_type = debug
9697
board = esp32-c6-devkitc-1
9798
monitor_speed = 115200
9899
custom_component_remove = espressif/esp_hosted

platform.json

+28-8
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,13 @@
66
"license": "Apache-2.0",
77
"keywords": [
88
"dev-platform",
9-
"Wi-Fi",
9+
"WiFi",
1010
"Bluetooth",
1111
"Xtensa",
1212
"RISC-V"
1313
],
1414
"engines": {
15-
"platformio": ">=6.1.16"
15+
"platformio": ">=6.1.18"
1616
},
1717
"repository": {
1818
"type": "git",
@@ -85,9 +85,16 @@
8585
},
8686
"tool-esptoolpy": {
8787
"type": "uploader",
88+
"optional": false,
8889
"owner": "pioarduino",
8990
"version": "https://github.com/pioarduino/esptool/releases/download/v4.8.9/esptool.zip"
9091
},
92+
"tl-install": {
93+
"type": "tool",
94+
"optional": false,
95+
"owner": "pioarduino",
96+
"version": "https://github.com/pioarduino/esp_install/releases/download/v5.0.0/esp_install-v5.0.0.zip"
97+
},
9198
"tool-dfuutil-arduino": {
9299
"type": "uploader",
93100
"optional": true,
@@ -97,11 +104,12 @@
97104
"tool-openocd-esp32": {
98105
"type": "debugger",
99106
"optional": true,
100-
"owner": "platformio",
101-
"version": "~2.1100.0"
107+
"owner": "pioarduino",
108+
"version": "https://github.com/pioarduino/registry/releases/download/0.0.1/openocd-v0.12.0-esp32-20250226.zip"
102109
},
103110
"tool-mklittlefs": {
104111
"type": "uploader",
112+
"optional": true,
105113
"owner": "tasmota",
106114
"version": "^3.2.0"
107115
},
@@ -118,34 +126,46 @@
118126
"version": "~2.230.0"
119127
},
120128
"tool-cppcheck": {
129+
"type": "tool",
121130
"optional": true,
122131
"owner": "platformio",
123132
"version": "~1.21100"
124133
},
125134
"tool-clangtidy": {
135+
"type": "tool",
126136
"optional": true,
127137
"owner": "platformio",
128138
"version": "^1.190100.0"
129139
},
130140
"tool-pvs-studio": {
141+
"type": "tool",
131142
"optional": true,
132143
"owner": "platformio",
133144
"version": "^7.18.59866"
134145
},
135146
"tool-cmake": {
147+
"type": "tool",
136148
"optional": true,
137149
"owner": "platformio",
138150
"version": "~3.30.2"
139151
},
140-
"tool-esp-rom-elfs": {
141-
"optional": true,
142-
"owner": "platformio",
143-
"version": "0.0.1+20241011"
152+
"tool-esp-rom-elfs": {
153+
"type": "tool",
154+
"optional": true,
155+
"owner": "platformio",
156+
"version": "0.0.1+20241011"
144157
},
145158
"tool-ninja": {
159+
"type": "tool",
146160
"optional": true,
147161
"owner": "platformio",
148162
"version": "^1.7.0"
163+
},
164+
"tool-scons": {
165+
"type": "tool",
166+
"optional": true,
167+
"owner": "platformio",
168+
"version": "~4.40801.0"
149169
}
150170
}
151171
}

platform.py

+65-24
Original file line numberDiff line numberDiff line change
@@ -13,22 +13,26 @@
1313
# limitations under the License.
1414

1515
import os
16-
import urllib
16+
import subprocess
1717
import sys
18-
import json
19-
import re
20-
import requests
18+
import shutil
19+
from os.path import join
2120

2221
from platformio.public import PlatformBase, to_unix_path
22+
from platformio.proc import get_pythonexe_path
23+
from platformio.project.config import ProjectConfig
24+
from platformio.package.manager.tool import ToolPackageManager
2325

2426

2527
IS_WINDOWS = sys.platform.startswith("win")
2628
# Set Platformio env var to use windows_amd64 for all windows architectures
2729
# only windows_amd64 native espressif toolchains are available
28-
# needs platformio core >= 6.1.16b2 or pioarduino core 6.1.16+test
30+
# needs platformio/pioarduino core >= 6.1.17
2931
if IS_WINDOWS:
3032
os.environ["PLATFORMIO_SYSTEM_TYPE"] = "windows_amd64"
3133

34+
python_exe = get_pythonexe_path()
35+
pm = ToolPackageManager()
3236

3337
class Espressif32Platform(PlatformBase):
3438
def configure_default_packages(self, variables, targets):
@@ -38,11 +42,55 @@ def configure_default_packages(self, variables, targets):
3842
board_config = self.board_config(variables.get("board"))
3943
mcu = variables.get("board_build.mcu", board_config.get("build.mcu", "esp32"))
4044
board_sdkconfig = variables.get("board_espidf.custom_sdkconfig", board_config.get("espidf.custom_sdkconfig", ""))
41-
core_variant_board = ''.join(variables.get("board_build.extra_flags", board_config.get("build.extra_flags", "")))
42-
core_variant_board = core_variant_board.replace("-D", " ")
43-
core_variant_build = (''.join(variables.get("build_flags", []))).replace("-D", " ")
4445
frameworks = variables.get("pioframework", [])
4546

47+
def install_tool(TOOL):
48+
self.packages[TOOL]["optional"] = False
49+
TOOL_PATH = os.path.join(ProjectConfig.get_instance().get("platformio", "packages_dir"), TOOL)
50+
TOOL_PACKAGE_PATH = os.path.join(TOOL_PATH, "package.json")
51+
TOOLS_PATH_DEFAULT = os.path.join(os.path.expanduser("~"), ".platformio")
52+
IDF_TOOLS = os.path.join(ProjectConfig.get_instance().get("platformio", "packages_dir"), "tl-install", "tools", "idf_tools.py")
53+
TOOLS_JSON_PATH = os.path.join(TOOL_PATH, "tools.json")
54+
TOOLS_PIO_PATH = os.path.join(TOOL_PATH, ".piopm")
55+
IDF_TOOLS_CMD = (
56+
python_exe,
57+
IDF_TOOLS,
58+
"--quiet",
59+
"--non-interactive",
60+
"--tools-json",
61+
TOOLS_JSON_PATH,
62+
"install"
63+
)
64+
65+
tl_flag = bool(os.path.exists(IDF_TOOLS))
66+
json_flag = bool(os.path.exists(TOOLS_JSON_PATH))
67+
pio_flag = bool(os.path.exists(TOOLS_PIO_PATH))
68+
if tl_flag and json_flag:
69+
rc = subprocess.run(IDF_TOOLS_CMD).returncode
70+
if rc != 0:
71+
sys.stderr.write("Error: Couldn't execute 'idf_tools.py install'\n")
72+
else:
73+
tl_path = "file://" + join(TOOLS_PATH_DEFAULT, "tools", TOOL)
74+
if not os.path.exists(join(TOOLS_PATH_DEFAULT, "tools", TOOL, "package.json")):
75+
shutil.copyfile(TOOL_PACKAGE_PATH, join(TOOLS_PATH_DEFAULT, "tools", TOOL, "package.json"))
76+
self.packages.pop(TOOL, None)
77+
if os.path.exists(TOOL_PATH) and os.path.isdir(TOOL_PATH):
78+
try:
79+
shutil.rmtree(TOOL_PATH)
80+
except Exception as e:
81+
print(f"Error while removing the tool folder: {e}")
82+
pm.install(tl_path)
83+
# tool is already installed, just activate it
84+
if tl_flag and pio_flag and not json_flag:
85+
self.packages[TOOL]["version"] = TOOL_PATH
86+
self.packages[TOOL]["optional"] = False
87+
88+
return
89+
90+
# Installer only needed for setup, deactivate when installed
91+
if bool(os.path.exists(os.path.join(ProjectConfig.get_instance().get("platformio", "packages_dir"), "tl-install", "tools", "idf_tools.py"))):
92+
self.packages["tl-install"]["optional"] = True
93+
4694
if "arduino" in frameworks:
4795
self.packages["framework-arduinoespressif32"]["optional"] = False
4896
self.packages["framework-arduinoespressif32-libs"]["optional"] = False
@@ -73,8 +121,7 @@ def configure_default_packages(self, variables, targets):
73121
self.packages["tool-mkfatfs"]["optional"] = False
74122
else:
75123
self.packages["tool-mkspiffs"]["optional"] = False
76-
if variables.get("upload_protocol"):
77-
self.packages["tool-openocd-esp32"]["optional"] = False
124+
78125
if os.path.isdir("ulp"):
79126
self.packages["toolchain-esp32ulp"]["optional"] = False
80127

@@ -90,37 +137,31 @@ def configure_default_packages(self, variables, targets):
90137
else:
91138
del self.packages["tool-dfuutil-arduino"]
92139

93-
# Starting from v12, Espressif's toolchains are shipped without
94-
# bundled GDB. Instead, it's distributed as separate packages for Xtensa
95-
# and RISC-V targets.
96-
for gdb_package in ("tool-xtensa-esp-elf-gdb", "tool-riscv32-esp-elf-gdb"):
97-
self.packages[gdb_package]["optional"] = False
98-
# if IS_WINDOWS:
99-
# Note: On Windows GDB v12 is not able to
100-
# launch a GDB server in pipe mode while v11 works fine
101-
# self.packages[gdb_package]["version"] = "~11.2.0"
140+
# install GDB and OpenOCD when debug mode or upload_protocol is set
141+
if (variables.get("build_type") or "debug" in "".join(targets)) or variables.get("upload_protocol"):
142+
for gdb_package in ("tool-xtensa-esp-elf-gdb", "tool-riscv32-esp-elf-gdb"):
143+
self.packages[gdb_package]["optional"] = False
144+
install_tool("tool-openocd-esp32")
102145

103146
# Common packages for IDF and mixed Arduino+IDF projects
104147
if "espidf" in frameworks:
105148
self.packages["toolchain-esp32ulp"]["optional"] = False
106149
for p in self.packages:
107150
if p in (
108-
"tool-scons",
109151
"tool-cmake",
110152
"tool-ninja",
153+
"tool-scons",
111154
"tool-esp-rom-elfs",
112155
):
113156
self.packages[p]["optional"] = False
114-
# elif p in ("tool-mconf", "tool-idf") and IS_WINDOWS:
115-
# self.packages[p]["optional"] = False
116157

117158
if mcu in ("esp32", "esp32s2", "esp32s3"):
118159
self.packages["toolchain-xtensa-esp-elf"]["optional"] = False
119160
else:
120161
self.packages.pop("toolchain-xtensa-esp-elf", None)
121162

122-
if mcu in ("esp32s2", "esp32s3", "esp32c2", "esp32c3", "esp32c6", "esp32h2", "esp32p4"):
123-
if mcu in ("esp32c2", "esp32c3", "esp32c6", "esp32h2", "esp32p4"):
163+
if mcu in ("esp32s2", "esp32s3", "esp32c2", "esp32c3", "esp32c5", "esp32c6", "esp32h2", "esp32p4"):
164+
if mcu in ("esp32c2", "esp32c3", "esp32c5", "esp32c6", "esp32h2", "esp32p4"):
124165
self.packages.pop("toolchain-esp32ulp", None)
125166
# RISC-V based toolchain for ESP32C3, ESP32C6 ESP32S2, ESP32S3 ULP
126167
self.packages["toolchain-riscv32-esp"]["optional"] = False

0 commit comments

Comments
 (0)