Skip to content

Commit 1c92ec9

Browse files
Dynamic ESP-IDF Target Discovery and Support Preview Targets (#1302)
* fix: toolchain refactoring and support preview targets Co-authored-by: Ali Azam Rana <[email protected]>
1 parent 7b63a44 commit 1c92ec9

File tree

7 files changed

+365
-89
lines changed

7 files changed

+365
-89
lines changed

bundles/com.espressif.idf.core/plugin.xml

Lines changed: 0 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -244,72 +244,6 @@ config-only component and an interface library is created instead."
244244
name="KCONFIG_PROJBUILD">
245245
</property>
246246
</extension>
247-
<extension point="com.espressif.idf.core.toolchain">
248-
<ToolChain
249-
arch="xtensa"
250-
compilerPattern="(?:xtensa-esp-elf|xtensa-esp32-elf)[\\/]+bin[\\/]+xtensa-esp32-elf-gcc(?:\.exe)?$"
251-
debuggerPattern="xtensa-esp32-elf-gdb(\.exe)?$"
252-
fileName="toolchain-esp32.cmake"
253-
id="xtensa-esp32-elf"
254-
name="esp32">
255-
</ToolChain>
256-
<ToolChain
257-
arch="xtensa"
258-
compilerPattern="(?:xtensa-esp-elf|xtensa-esp32s2-elf)[\\/]+bin[\\/]+xtensa-esp32s2-elf-gcc(?:\.exe)?$"
259-
debuggerPattern="xtensa-esp32s2-elf-gdb(\.exe)?$"
260-
fileName="toolchain-esp32s2.cmake"
261-
id="xtensa-esp32s2-elf"
262-
name="esp32s2">
263-
</ToolChain>
264-
<ToolChain
265-
arch="xtensa"
266-
compilerPattern="(?:xtensa-esp-elf|xtensa-esp32s3-elf)[\\/]+bin[\\/]+xtensa-esp32s3-elf-gcc(?:\.exe)?$"
267-
debuggerPattern="xtensa-esp32s3-elf-gdb(\.exe)?$"
268-
fileName="toolchain-esp32s3.cmake"
269-
id="xtensa-esp32s3-elf"
270-
name="esp32s3">
271-
</ToolChain>
272-
<ToolChain
273-
arch="riscv32"
274-
compilerPattern="riscv32-esp-elf[\\/]+bin[\\/]+riscv32-esp-elf-gcc(?:\.exe)?$"
275-
debuggerPattern="riscv32-esp-elf-gdb(\.exe)?$"
276-
fileName="toolchain-esp32c2.cmake"
277-
id="riscv32-esp-elf"
278-
name="esp32c2">
279-
</ToolChain>
280-
<ToolChain
281-
arch="riscv32"
282-
compilerPattern="riscv32-esp-elf[\\/]+bin[\\/]+riscv32-esp-elf-gcc(?:\.exe)?$"
283-
debuggerPattern="riscv32-esp-elf-gdb(\.exe)?$"
284-
fileName="toolchain-esp32c3.cmake"
285-
id="riscv32-esp-elf"
286-
name="esp32c3">
287-
</ToolChain>
288-
<ToolChain
289-
arch="riscv32"
290-
compilerPattern="riscv32-esp-elf[\\/]+bin[\\/]+riscv32-esp-elf-gcc(?:\.exe)?$"
291-
debuggerPattern="riscv32-esp-elf-gdb(\.exe)?$"
292-
fileName="toolchain-esp32c6.cmake"
293-
id="riscv32-esp-elf"
294-
name="esp32c6">
295-
</ToolChain>
296-
<ToolChain
297-
arch="riscv32"
298-
compilerPattern="riscv32-esp-elf[\\/]+bin[\\/]+riscv32-esp-elf-gcc(?:\.exe)?$"
299-
debuggerPattern="riscv32-esp-elf-gdb(\.exe)?$"
300-
fileName="toolchain-esp32h2.cmake"
301-
id="riscv32-esp-elf"
302-
name="esp32h2">
303-
</ToolChain>
304-
<ToolChain
305-
arch="riscv32"
306-
compilerPattern="riscv32-esp-elf[\\/]+bin[\\/]+riscv32-esp-elf-gcc(?:\.exe)?$"
307-
debuggerPattern="riscv32-esp-elf-gdb(\.exe)?$"
308-
fileName="toolchain-esp32p4.cmake"
309-
id="riscv32-esp-elf"
310-
name="esp32p4">
311-
</ToolChain>
312-
</extension>
313247
<extension point="org.eclipse.core.variables.dynamicVariables">
314248
<variable
315249
description="%openocd_bin_path"

bundles/com.espressif.idf.core/src/com/espressif/idf/core/DefaultBoardProvider.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,12 @@ public String getDefaultBoard(String targetName)
5858
{
5959
List<Board> boardsList = this.espConfigParser.getBoardsForTarget(targetName);
6060
String[] boards = boardsList.stream().map(Board::name).toArray(String[]::new);
61+
62+
if (boards.length == 0)
63+
{
64+
return EspTarget.enumOf(targetName).board;
65+
}
66+
6167
return boards[getIndexOfDefaultBoard(targetName, boards)];
6268
}
6369

bundles/com.espressif.idf.core/src/com/espressif/idf/core/toolchain/ESPToolChainManager.java

Lines changed: 15 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -34,10 +34,8 @@
3434
import org.eclipse.cdt.core.build.IToolChainManager;
3535
import org.eclipse.cdt.core.build.IToolChainProvider;
3636
import org.eclipse.core.runtime.CoreException;
37-
import org.eclipse.core.runtime.IConfigurationElement;
3837
import org.eclipse.core.runtime.IPath;
3938
import org.eclipse.core.runtime.IStatus;
40-
import org.eclipse.core.runtime.Platform;
4139
import org.eclipse.launchbar.core.target.ILaunchTarget;
4240
import org.eclipse.launchbar.core.target.ILaunchTargetManager;
4341
import org.eclipse.launchbar.core.target.ILaunchTargetWorkingCopy;
@@ -74,23 +72,27 @@ public ESPToolChainManager()
7472

7573
private static Map<String, ESPToolChainElement> readESPToolchainRegistry()
7674
{
77-
IConfigurationElement[] configElements = Platform.getExtensionRegistry()
78-
.getConfigurationElementsFor("com.espressif.idf.core.toolchain"); //$NON-NLS-1$
79-
for (IConfigurationElement iConfigurationElement : configElements)
75+
// Read targets dynamically from ESP-IDF constants.py instead of plugin.xml
76+
String idfPath = IDFUtil.getIDFPath();
77+
IDFTargets idfTargets = IDFTargetsReader.readTargetsFromEspIdf(idfPath);
78+
79+
// Convert dynamic targets to toolchain elements
80+
for (IDFTargets.IDFTarget target : idfTargets.getAllTargets())
8081
{
81-
String name = iConfigurationElement.getAttribute("name"); //$NON-NLS-1$
82-
String id = iConfigurationElement.getAttribute("id"); //$NON-NLS-1$
83-
String arch = iConfigurationElement.getAttribute("arch"); //$NON-NLS-1$
84-
String fileName = iConfigurationElement.getAttribute("fileName"); //$NON-NLS-1$
85-
String compilerPattern = iConfigurationElement.getAttribute("compilerPattern"); //$NON-NLS-1$
86-
String debuggerPatten = iConfigurationElement.getAttribute("debuggerPattern"); //$NON-NLS-1$
82+
String name = target.getName();
83+
String id = target.getToolchainId();
84+
String arch = target.getArchitecture();
85+
String fileName = target.getToolchainFileName();
86+
String compilerPattern = target.getCompilerPattern();
87+
String debuggerPattern = target.getDebuggerPattern();
8788

8889
String uniqueToolChainId = name.concat("/").concat(arch).concat("/").concat(fileName); //$NON-NLS-1$ //$NON-NLS-2$
8990

9091
toolchainElements.put(uniqueToolChainId,
91-
new ESPToolChainElement(name, id, arch, fileName, compilerPattern, debuggerPatten));
92-
92+
new ESPToolChainElement(name, id, arch, fileName, compilerPattern, debuggerPattern));
9393
}
94+
95+
Logger.log("Dynamically loaded " + toolchainElements.size() + " toolchain elements from ESP-IDF"); //$NON-NLS-1$ //$NON-NLS-2$
9496
return toolchainElements;
9597
}
9698

Lines changed: 215 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,215 @@
1+
/*******************************************************************************
2+
* Copyright 2025 Espressif Systems (Shanghai) PTE LTD. All rights reserved.
3+
* Use is subject to license terms.
4+
*******************************************************************************/
5+
6+
package com.espressif.idf.core.toolchain;
7+
8+
import java.util.ArrayList;
9+
import java.util.List;
10+
import java.util.Set;
11+
12+
/**
13+
* Class to hold ESP-IDF target information including preview status
14+
*
15+
* @author Kondal Kolipaka <[email protected]>
16+
*
17+
*/
18+
public class IDFTargets
19+
{
20+
private static final Set<String> XTENSA_CHIPS = Set.of("esp32", "esp32s2", "esp32s3"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
21+
private static final String XTENSA = "xtensa"; //$NON-NLS-1$
22+
private static final String RISCV32 = "riscv32"; //$NON-NLS-1$
23+
private static final String XTENSA_TOOLCHAIN_ID = XTENSA + "-%s-elf"; //$NON-NLS-1$
24+
private static final String RISCV32_TOOLCHAIN_ID = RISCV32 + "-esp-elf"; //$NON-NLS-1$
25+
private static final String XTENSA_UNIFIED_DIR = XTENSA + "-esp-elf"; //$NON-NLS-1$
26+
private static final String TOOLCHAIN_NAME = "toolchain-%s.cmake"; //$NON-NLS-1$
27+
private List<IDFTarget> supportedTargets;
28+
private List<IDFTarget> previewTargets;
29+
30+
public IDFTargets()
31+
{
32+
this.supportedTargets = new ArrayList<>();
33+
this.previewTargets = new ArrayList<>();
34+
}
35+
36+
public void addSupportedTarget(String target)
37+
{
38+
supportedTargets.add(new IDFTarget(target, false));
39+
}
40+
41+
public void addPreviewTarget(String target)
42+
{
43+
previewTargets.add(new IDFTarget(target, true));
44+
}
45+
46+
public List<IDFTarget> getAllTargets()
47+
{
48+
List<IDFTarget> allTargets = new ArrayList<>();
49+
allTargets.addAll(supportedTargets);
50+
allTargets.addAll(previewTargets);
51+
return allTargets;
52+
}
53+
54+
public List<IDFTarget> getSupportedTargets()
55+
{
56+
return supportedTargets;
57+
}
58+
59+
public List<IDFTarget> getPreviewTargets()
60+
{
61+
return previewTargets;
62+
}
63+
64+
public boolean hasTarget(String targetName)
65+
{
66+
return getAllTargets().stream().anyMatch(target -> target.getName().equals(targetName));
67+
}
68+
69+
/**
70+
* Get a specific target by name
71+
*
72+
* @param targetName Name of the target to find
73+
* @return IDFTarget if found, null otherwise
74+
*/
75+
public IDFTarget getTarget(String targetName)
76+
{
77+
return getAllTargets().stream().filter(target -> target.getName().equals(targetName)).findFirst().orElse(null);
78+
}
79+
80+
/**
81+
* Get all target names as strings
82+
*
83+
* @return List of target names
84+
*/
85+
public List<String> getAllTargetNames()
86+
{
87+
return getAllTargets().stream().map(IDFTarget::getName).collect(java.util.stream.Collectors.toList());
88+
}
89+
90+
/**
91+
* Get supported target names as strings
92+
*
93+
* @return List of supported target names
94+
*/
95+
public List<String> getSupportedTargetNames()
96+
{
97+
return getSupportedTargets().stream().map(IDFTarget::getName).collect(java.util.stream.Collectors.toList());
98+
}
99+
100+
/**
101+
* Get preview target names as strings
102+
*
103+
* @return List of preview target names
104+
*/
105+
public List<String> getPreviewTargetNames()
106+
{
107+
return getPreviewTargets().stream().map(IDFTarget::getName).collect(java.util.stream.Collectors.toList());
108+
}
109+
110+
/**
111+
* Inner class representing a single IDF target
112+
*/
113+
public static class IDFTarget
114+
{
115+
private final String name;
116+
private final boolean isPreview;
117+
118+
public IDFTarget(String name, boolean isPreview)
119+
{
120+
this.name = name;
121+
this.isPreview = isPreview;
122+
}
123+
124+
public String getName()
125+
{
126+
return name;
127+
}
128+
129+
public boolean isPreview()
130+
{
131+
return isPreview;
132+
}
133+
134+
/**
135+
* Get the architecture for this target
136+
*
137+
* @return "xtensa" for esp32/esp32s2/esp32s3, "riscv32" for others
138+
*/
139+
public String getArchitecture()
140+
{
141+
return XTENSA_CHIPS.contains(name) ? XTENSA : RISCV32;
142+
}
143+
144+
/**
145+
* Get the toolchain ID for this target
146+
*
147+
* @return toolchain ID string
148+
*/
149+
public String getToolchainId()
150+
{
151+
return XTENSA_CHIPS.contains(name) ? String.format(XTENSA_TOOLCHAIN_ID, name) : RISCV32_TOOLCHAIN_ID;
152+
}
153+
154+
/**
155+
* Get the compiler pattern for this target
156+
*
157+
* @return regex pattern for compiler
158+
*/
159+
public String getCompilerPattern()
160+
{
161+
String executableName = getExecutableName();
162+
163+
// Support both old and new unified directory structures
164+
String targetSpecificDir = getTargetSpecificDirectoryName();
165+
String unifiedDir = getUnifiedDirectoryName();
166+
167+
// Create pattern that matches either directory structure
168+
return "(?:" + targetSpecificDir + "|" + unifiedDir + ")[\\\\/]+bin[\\\\/]+" + executableName //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
169+
+ "-gcc(?:\\.exe)?$"; //$NON-NLS-1$
170+
}
171+
172+
/**
173+
* Get the debugger pattern for this target
174+
*
175+
* @return regex pattern for debugger
176+
*/
177+
public String getDebuggerPattern()
178+
{
179+
String executableName = getExecutableName();
180+
return executableName + "-gdb(?:\\.exe)?$"; //$NON-NLS-1$
181+
}
182+
183+
/**
184+
* Get the executable name prefix for this target (different from directory structure in ESP-IDF v5.5+)
185+
*
186+
* @return executable name prefix
187+
*/
188+
private String getExecutableName()
189+
{
190+
return XTENSA_CHIPS.contains(name) ? String.format(XTENSA_TOOLCHAIN_ID, name)
191+
: RISCV32_TOOLCHAIN_ID;
192+
}
193+
194+
private String getTargetSpecificDirectoryName()
195+
{
196+
return XTENSA_CHIPS.contains(name) ? String.format(XTENSA_TOOLCHAIN_ID, name)
197+
: RISCV32_TOOLCHAIN_ID;
198+
}
199+
200+
private String getUnifiedDirectoryName()
201+
{
202+
return XTENSA_CHIPS.contains(name) ? XTENSA_UNIFIED_DIR : RISCV32_TOOLCHAIN_ID;
203+
}
204+
205+
/**
206+
* Get the CMake toolchain file name for this target
207+
*
208+
* @return toolchain file name
209+
*/
210+
public String getToolchainFileName()
211+
{
212+
return String.format(TOOLCHAIN_NAME, name);
213+
}
214+
}
215+
}

0 commit comments

Comments
 (0)