diff --git a/bundles/com.espressif.idf.core/plugin.xml b/bundles/com.espressif.idf.core/plugin.xml index 015375aec..d27a041df 100644 --- a/bundles/com.espressif.idf.core/plugin.xml +++ b/bundles/com.espressif.idf.core/plugin.xml @@ -244,72 +244,6 @@ config-only component and an interface library is created instead." name="KCONFIG_PROJBUILD"> - - - - - - - - - - - - - - - - - - boardsList = this.espConfigParser.getBoardsForTarget(targetName); String[] boards = boardsList.stream().map(Board::name).toArray(String[]::new); + + if (boards.length == 0) + { + return EspTarget.enumOf(targetName).board; + } + return boards[getIndexOfDefaultBoard(targetName, boards)]; } diff --git a/bundles/com.espressif.idf.core/src/com/espressif/idf/core/toolchain/ESPToolChainManager.java b/bundles/com.espressif.idf.core/src/com/espressif/idf/core/toolchain/ESPToolChainManager.java index 659677982..c647f6f4d 100644 --- a/bundles/com.espressif.idf.core/src/com/espressif/idf/core/toolchain/ESPToolChainManager.java +++ b/bundles/com.espressif.idf.core/src/com/espressif/idf/core/toolchain/ESPToolChainManager.java @@ -34,10 +34,8 @@ import org.eclipse.cdt.core.build.IToolChainManager; import org.eclipse.cdt.core.build.IToolChainProvider; import org.eclipse.core.runtime.CoreException; -import org.eclipse.core.runtime.IConfigurationElement; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.IStatus; -import org.eclipse.core.runtime.Platform; import org.eclipse.launchbar.core.target.ILaunchTarget; import org.eclipse.launchbar.core.target.ILaunchTargetManager; import org.eclipse.launchbar.core.target.ILaunchTargetWorkingCopy; @@ -74,23 +72,27 @@ public ESPToolChainManager() private static Map readESPToolchainRegistry() { - IConfigurationElement[] configElements = Platform.getExtensionRegistry() - .getConfigurationElementsFor("com.espressif.idf.core.toolchain"); //$NON-NLS-1$ - for (IConfigurationElement iConfigurationElement : configElements) + // Read targets dynamically from ESP-IDF constants.py instead of plugin.xml + String idfPath = IDFUtil.getIDFPath(); + IDFTargets idfTargets = IDFTargetsReader.readTargetsFromEspIdf(idfPath); + + // Convert dynamic targets to toolchain elements + for (IDFTargets.IDFTarget target : idfTargets.getAllTargets()) { - String name = iConfigurationElement.getAttribute("name"); //$NON-NLS-1$ - String id = iConfigurationElement.getAttribute("id"); //$NON-NLS-1$ - String arch = iConfigurationElement.getAttribute("arch"); //$NON-NLS-1$ - String fileName = iConfigurationElement.getAttribute("fileName"); //$NON-NLS-1$ - String compilerPattern = iConfigurationElement.getAttribute("compilerPattern"); //$NON-NLS-1$ - String debuggerPatten = iConfigurationElement.getAttribute("debuggerPattern"); //$NON-NLS-1$ + String name = target.getName(); + String id = target.getToolchainId(); + String arch = target.getArchitecture(); + String fileName = target.getToolchainFileName(); + String compilerPattern = target.getCompilerPattern(); + String debuggerPattern = target.getDebuggerPattern(); String uniqueToolChainId = name.concat("/").concat(arch).concat("/").concat(fileName); //$NON-NLS-1$ //$NON-NLS-2$ toolchainElements.put(uniqueToolChainId, - new ESPToolChainElement(name, id, arch, fileName, compilerPattern, debuggerPatten)); - + new ESPToolChainElement(name, id, arch, fileName, compilerPattern, debuggerPattern)); } + + Logger.log("Dynamically loaded " + toolchainElements.size() + " toolchain elements from ESP-IDF"); //$NON-NLS-1$ //$NON-NLS-2$ return toolchainElements; } diff --git a/bundles/com.espressif.idf.core/src/com/espressif/idf/core/toolchain/IDFTargets.java b/bundles/com.espressif.idf.core/src/com/espressif/idf/core/toolchain/IDFTargets.java new file mode 100644 index 000000000..9f677e33e --- /dev/null +++ b/bundles/com.espressif.idf.core/src/com/espressif/idf/core/toolchain/IDFTargets.java @@ -0,0 +1,215 @@ +/******************************************************************************* + * Copyright 2025 Espressif Systems (Shanghai) PTE LTD. All rights reserved. + * Use is subject to license terms. + *******************************************************************************/ + +package com.espressif.idf.core.toolchain; + +import java.util.ArrayList; +import java.util.List; +import java.util.Set; + +/** + * Class to hold ESP-IDF target information including preview status + * + * @author Kondal Kolipaka + * + */ +public class IDFTargets +{ + private static final Set XTENSA_CHIPS = Set.of("esp32", "esp32s2", "esp32s3"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ + private static final String XTENSA = "xtensa"; //$NON-NLS-1$ + private static final String RISCV32 = "riscv32"; //$NON-NLS-1$ + private static final String XTENSA_TOOLCHAIN_ID = XTENSA + "-%s-elf"; //$NON-NLS-1$ + private static final String RISCV32_TOOLCHAIN_ID = RISCV32 + "-esp-elf"; //$NON-NLS-1$ + private static final String XTENSA_UNIFIED_DIR = XTENSA + "-esp-elf"; //$NON-NLS-1$ + private static final String TOOLCHAIN_NAME = "toolchain-%s.cmake"; //$NON-NLS-1$ + private List supportedTargets; + private List previewTargets; + + public IDFTargets() + { + this.supportedTargets = new ArrayList<>(); + this.previewTargets = new ArrayList<>(); + } + + public void addSupportedTarget(String target) + { + supportedTargets.add(new IDFTarget(target, false)); + } + + public void addPreviewTarget(String target) + { + previewTargets.add(new IDFTarget(target, true)); + } + + public List getAllTargets() + { + List allTargets = new ArrayList<>(); + allTargets.addAll(supportedTargets); + allTargets.addAll(previewTargets); + return allTargets; + } + + public List getSupportedTargets() + { + return supportedTargets; + } + + public List getPreviewTargets() + { + return previewTargets; + } + + public boolean hasTarget(String targetName) + { + return getAllTargets().stream().anyMatch(target -> target.getName().equals(targetName)); + } + + /** + * Get a specific target by name + * + * @param targetName Name of the target to find + * @return IDFTarget if found, null otherwise + */ + public IDFTarget getTarget(String targetName) + { + return getAllTargets().stream().filter(target -> target.getName().equals(targetName)).findFirst().orElse(null); + } + + /** + * Get all target names as strings + * + * @return List of target names + */ + public List getAllTargetNames() + { + return getAllTargets().stream().map(IDFTarget::getName).collect(java.util.stream.Collectors.toList()); + } + + /** + * Get supported target names as strings + * + * @return List of supported target names + */ + public List getSupportedTargetNames() + { + return getSupportedTargets().stream().map(IDFTarget::getName).collect(java.util.stream.Collectors.toList()); + } + + /** + * Get preview target names as strings + * + * @return List of preview target names + */ + public List getPreviewTargetNames() + { + return getPreviewTargets().stream().map(IDFTarget::getName).collect(java.util.stream.Collectors.toList()); + } + + /** + * Inner class representing a single IDF target + */ + public static class IDFTarget + { + private final String name; + private final boolean isPreview; + + public IDFTarget(String name, boolean isPreview) + { + this.name = name; + this.isPreview = isPreview; + } + + public String getName() + { + return name; + } + + public boolean isPreview() + { + return isPreview; + } + + /** + * Get the architecture for this target + * + * @return "xtensa" for esp32/esp32s2/esp32s3, "riscv32" for others + */ + public String getArchitecture() + { + return XTENSA_CHIPS.contains(name) ? XTENSA : RISCV32; + } + + /** + * Get the toolchain ID for this target + * + * @return toolchain ID string + */ + public String getToolchainId() + { + return XTENSA_CHIPS.contains(name) ? String.format(XTENSA_TOOLCHAIN_ID, name) : RISCV32_TOOLCHAIN_ID; + } + + /** + * Get the compiler pattern for this target + * + * @return regex pattern for compiler + */ + public String getCompilerPattern() + { + String executableName = getExecutableName(); + + // Support both old and new unified directory structures + String targetSpecificDir = getTargetSpecificDirectoryName(); + String unifiedDir = getUnifiedDirectoryName(); + + // Create pattern that matches either directory structure + return "(?:" + targetSpecificDir + "|" + unifiedDir + ")[\\\\/]+bin[\\\\/]+" + executableName //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ + + "-gcc(?:\\.exe)?$"; //$NON-NLS-1$ + } + + /** + * Get the debugger pattern for this target + * + * @return regex pattern for debugger + */ + public String getDebuggerPattern() + { + String executableName = getExecutableName(); + return executableName + "-gdb(?:\\.exe)?$"; //$NON-NLS-1$ + } + + /** + * Get the executable name prefix for this target (different from directory structure in ESP-IDF v5.5+) + * + * @return executable name prefix + */ + private String getExecutableName() + { + return XTENSA_CHIPS.contains(name) ? String.format(XTENSA_TOOLCHAIN_ID, name) + : RISCV32_TOOLCHAIN_ID; + } + + private String getTargetSpecificDirectoryName() + { + return XTENSA_CHIPS.contains(name) ? String.format(XTENSA_TOOLCHAIN_ID, name) + : RISCV32_TOOLCHAIN_ID; + } + + private String getUnifiedDirectoryName() + { + return XTENSA_CHIPS.contains(name) ? XTENSA_UNIFIED_DIR : RISCV32_TOOLCHAIN_ID; + } + + /** + * Get the CMake toolchain file name for this target + * + * @return toolchain file name + */ + public String getToolchainFileName() + { + return String.format(TOOLCHAIN_NAME, name); + } + } +} diff --git a/bundles/com.espressif.idf.core/src/com/espressif/idf/core/toolchain/IDFTargetsReader.java b/bundles/com.espressif.idf.core/src/com/espressif/idf/core/toolchain/IDFTargetsReader.java new file mode 100644 index 000000000..91adc10b6 --- /dev/null +++ b/bundles/com.espressif.idf.core/src/com/espressif/idf/core/toolchain/IDFTargetsReader.java @@ -0,0 +1,121 @@ +/******************************************************************************* + * Copyright 2025 Espressif Systems (Shanghai) PTE LTD. All rights reserved. + * Use is subject to license terms. + *******************************************************************************/ + +package com.espressif.idf.core.toolchain; + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.ArrayList; +import java.util.List; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import com.espressif.idf.core.logging.Logger; + +/** + * Class to read ESP-IDF targets from constants.py file + * + * @author Kondal Kolipaka + * + */ +public class IDFTargetsReader +{ + private static final String CONSTANTS_FILE_PATH = "tools/idf_py_actions/constants.py"; //$NON-NLS-1$ + private static final Pattern SUPPORTED_TARGETS_PATTERN = Pattern + .compile("SUPPORTED_TARGETS\\s*=\\s*\\[([^\\]]*)\\]", Pattern.MULTILINE); //$NON-NLS-1$ + private static final Pattern PREVIEW_TARGETS_PATTERN = Pattern.compile("PREVIEW_TARGETS\\s*=\\s*\\[([^\\]]*)\\]", //$NON-NLS-1$ + Pattern.MULTILINE); + + /** + * Read ESP-IDF targets from the constants.py file + * + * @param idfPath ESP-IDF installation path + * @return IDFTargets object containing all targets + */ + public static IDFTargets readTargetsFromEspIdf(String idfPath) + { + IDFTargets targets = new IDFTargets(); + + if (idfPath == null || idfPath.trim().isEmpty()) + { + Logger.log("ESP-IDF path is null or empty, cannot read targets"); //$NON-NLS-1$ + return targets; + } + + Path constantsFilePath = Paths.get(idfPath, CONSTANTS_FILE_PATH); + + if (!Files.exists(constantsFilePath)) + { + Logger.log("Constants file not found at: " + constantsFilePath); //$NON-NLS-1$ + return targets; + } + + try + { + String content = new String(Files.readAllBytes(constantsFilePath)); + + // Extract supported targets + List supportedTargets = extractTargets(content, SUPPORTED_TARGETS_PATTERN); + for (String target : supportedTargets) + { + targets.addSupportedTarget(target.trim()); + } + + // Extract preview targets + List previewTargets = extractTargets(content, PREVIEW_TARGETS_PATTERN); + for (String target : previewTargets) + { + targets.addPreviewTarget(target.trim()); + } + + Logger.log("Successfully read " + supportedTargets.size() + " supported targets and " //$NON-NLS-1$ //$NON-NLS-2$ + + previewTargets.size() + " preview targets"); //$NON-NLS-1$ + + } + catch (IOException e) + { + Logger.log("Error reading constants file: " + e.getMessage()); //$NON-NLS-1$ + } + catch (Exception e) + { + Logger.log("Unexpected error reading targets: " + e.getMessage()); //$NON-NLS-1$ + } + + return targets; + } + + /** + * Extract target names from the constants.py content using regex pattern + * + * @param content File content as string + * @param pattern Regex pattern to match + * @return List of target names + */ + private static List extractTargets(String content, Pattern pattern) + { + List targets = new ArrayList<>(); + + Matcher matcher = pattern.matcher(content); + if (matcher.find()) + { + String targetsString = matcher.group(1); + // Split by comma and clean up + String[] targetArray = targetsString.split(","); //$NON-NLS-1$ + for (String target : targetArray) + { + // Remove quotes, whitespace and filter empty strings + String cleanTarget = target.replaceAll("['\"\\s]", "").trim(); //$NON-NLS-1$ //$NON-NLS-2$ + if (!cleanTarget.isEmpty()) + { + targets.add(cleanTarget); + } + } + } + + return targets; + } +} diff --git a/bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/templates/NewProjectCreationWizardPage.java b/bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/templates/NewProjectCreationWizardPage.java index 30c40ce54..2be453566 100644 --- a/bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/templates/NewProjectCreationWizardPage.java +++ b/bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/templates/NewProjectCreationWizardPage.java @@ -32,8 +32,9 @@ import org.eclipse.ui.internal.ide.dialogs.ProjectContentsLocationArea; import org.eclipse.ui.internal.ide.dialogs.ProjectContentsLocationArea.IErrorMessageReporter; -import com.espressif.idf.core.configparser.EspConfigParser; import com.espressif.idf.core.logging.Logger; +import com.espressif.idf.core.toolchain.IDFTargets; +import com.espressif.idf.core.toolchain.IDFTargetsReader; import com.espressif.idf.core.util.IDFUtil; /** @@ -77,9 +78,9 @@ private void createProjectTargetSelection(Composite container) mainComposite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false)); Label label = new Label(mainComposite, SWT.NONE); label.setText(Messages.NewProjectTargetSelection_Label); - EspConfigParser parser = new EspConfigParser(); + IDFTargets idfTargets = IDFTargetsReader.readTargetsFromEspIdf(IDFUtil.getIDFPath()); targetCombo = new Combo(mainComposite, SWT.READ_ONLY); - targetCombo.setItems(parser.getTargets().toArray(new String[0])); + targetCombo.setItems(idfTargets.getAllTargetNames().toArray(String[]::new)); targetCombo.select(0); targetCombo.setToolTipText(Messages.NewProjectTargetSelection_Tooltip); } diff --git a/bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/ToolsActivationJob.java b/bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/ToolsActivationJob.java index 63c0c994d..91a56368d 100644 --- a/bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/ToolsActivationJob.java +++ b/bundles/com.espressif.idf.ui/src/com/espressif/idf/ui/tools/ToolsActivationJob.java @@ -26,6 +26,7 @@ import com.espressif.idf.core.IDFEnvironmentVariables; import com.espressif.idf.core.logging.Logger; import com.espressif.idf.core.toolchain.ESPToolChainManager; +import com.espressif.idf.core.toolchain.IDFTargetsReader; import com.espressif.idf.core.tools.vo.IDFToolSet; import com.espressif.idf.core.util.IDFUtil; import com.espressif.idf.core.util.LspService; @@ -172,14 +173,10 @@ public void run() private void setUpToolChainsAndTargets() { - IStatus status = loadTargetsAvailableFromIdfInCurrentToolSet(); - if (status.getSeverity() == IStatus.ERROR) - { - Logger.log("Unable to get IDF targets from current toolset"); - return; - } + //Get current active idf + String idfPath = IDFUtil.getIDFPath(); + List targets = IDFTargetsReader.readTargetsFromEspIdf(idfPath).getAllTargetNames(); - List targets = extractTargets(status.getMessage()); ESPToolChainManager espToolChainManager = new ESPToolChainManager(); espToolChainManager.removeLaunchTargetsNotPresent(targets); espToolChainManager.removeCmakeToolChains();