diff --git a/build/org.eclipse.cdt.build.gcc.core/plugin.xml b/build/org.eclipse.cdt.build.gcc.core/plugin.xml index 47c2c1028ff..596c7623f67 100644 --- a/build/org.eclipse.cdt.build.gcc.core/plugin.xml +++ b/build/org.eclipse.cdt.build.gcc.core/plugin.xml @@ -1,20 +1,15 @@ - - - - + class="org.eclipse.cdt.build.gcc.core.internal.GCCPathToolChainProvider" + id="org.eclipse.cdt.build.gcc.core.gccPathProvider"> + class="org.eclipse.cdt.build.gcc.core.internal.Msys2ToolChainProvider" + id="org.eclipse.cdt.build.gcc.core.msys2Provider"> diff --git a/build/org.eclipse.cdt.build.gcc.core/src/org/eclipse/cdt/build/gcc/core/GCCToolChain.java b/build/org.eclipse.cdt.build.gcc.core/src/org/eclipse/cdt/build/gcc/core/GCCToolChain.java index 5d7c5211fc3..38a8de16414 100644 --- a/build/org.eclipse.cdt.build.gcc.core/src/org/eclipse/cdt/build/gcc/core/GCCToolChain.java +++ b/build/org.eclipse.cdt.build.gcc.core/src/org/eclipse/cdt/build/gcc/core/GCCToolChain.java @@ -26,7 +26,7 @@ import java.util.regex.Pattern; import org.eclipse.cdt.build.gcc.core.internal.Activator; import org.eclipse.cdt.core.CCorePlugin; import org.eclipse.cdt.core.build.IToolChain; -import org.eclipse.cdt.core.build.IToolChainType; +import org.eclipse.cdt.core.build.IToolChainProvider; import org.eclipse.cdt.core.envvar.EnvironmentVariable; import org.eclipse.cdt.core.envvar.IEnvironmentVariable; import org.eclipse.cdt.core.parser.ExtendedScannerInfo; @@ -41,45 +41,47 @@ import org.eclipse.core.runtime.Platform; import org.eclipse.core.runtime.PlatformObject; /** - * The GCC toolchain. Placing it in cdt.core for now. - * - * TODO move to it's own plug-in. - * - * @since 5.12 + * The GCC toolchain. This is the base class for all GCC toolchains. It represents GCC as found on + * the user's PATH. It can be overriden to change environment variable settings. */ public class GCCToolChain extends PlatformObject implements IToolChain { - private final IToolChainType type; + private final IToolChainProvider provider; private final String name; - private final String command; - private String version; - private String target; - private Path path; - private IEnvironmentVariable pathVar; - private IEnvironmentVariable[] envVars; + private final Path path; + private final String prefix; + private final IEnvironmentVariable pathVar; + private final IEnvironmentVariable[] envVars; - public GCCToolChain(IToolChainType type, Path path, String command) { - this.type = type; - this.command = command; - getVersion(path.resolve(command).toString()); - this.name = command + '-' + version; - this.path = path; + protected String[] compileCommands; - pathVar = new EnvironmentVariable("PATH", path.toString(), IEnvironmentVariable.ENVVAR_PREPEND, //$NON-NLS-1$ - File.pathSeparator); - envVars = new IEnvironmentVariable[] { pathVar }; + public GCCToolChain(IToolChainProvider provider, String name) { + this(provider, name, null, null); } - protected GCCToolChain(IToolChainType type, String name, String command) { - this.type = type; + public GCCToolChain(IToolChainProvider provider, String name, Path path) { + this(provider, name, path, null); + } + + public GCCToolChain(IToolChainProvider provider, String name, Path path, String prefix) { + this.provider = provider; this.name = name; - this.command = command; - // TODO need to pull the other info out of preferences + this.path = path; + this.prefix = prefix; + + if (path != null) { + pathVar = new EnvironmentVariable("PATH", path.toString(), IEnvironmentVariable.ENVVAR_PREPEND, //$NON-NLS-1$ + File.pathSeparator); + envVars = new IEnvironmentVariable[] { pathVar }; + } else { + pathVar = null; + envVars = new IEnvironmentVariable[0]; + } } @Override - public IToolChainType getType() { - return type; + public IToolChainProvider getProvider() { + return provider; } @Override @@ -89,8 +91,7 @@ public class GCCToolChain extends PlatformObject implements IToolChain { @Override public String getProperty(String key) { - // TODO for now assume it's a local gcc - // Later use the target, especially to find out arch + // this class represents a local toolchain switch (key) { case ATTR_OS: return Platform.getOS(); @@ -100,36 +101,6 @@ public class GCCToolChain extends PlatformObject implements IToolChain { return null; } - private static Pattern versionPattern = Pattern.compile(".*(gcc|LLVM) version .*"); //$NON-NLS-1$ - private static Pattern targetPattern = Pattern.compile("Target: (.*)"); //$NON-NLS-1$ - - private void getVersion(String command) { - try { - Process proc = new ProcessBuilder(new String[] { command, "-v" }).redirectErrorStream(true) //$NON-NLS-1$ - .start(); - try (BufferedReader reader = new BufferedReader(new InputStreamReader(proc.getInputStream()))) { - for (String line = reader.readLine(); line != null; line = reader.readLine()) { - Matcher versionMatcher = versionPattern.matcher(line); - if (versionMatcher.matches()) { - version = line.trim(); - continue; - } - Matcher targetMatcher = targetPattern.matcher(line); - if (targetMatcher.matches()) { - target = targetMatcher.group(1); - continue; - } - } - } - } catch (IOException e) { - Activator.log(e); - } - } - - public String getTarget() { - return target; - } - protected void addDiscoveryOptions(List command) { command.add("-E"); //$NON-NLS-1$ command.add("-P"); //$NON-NLS-1$ @@ -142,12 +113,12 @@ public class GCCToolChain extends PlatformObject implements IToolChain { IExtendedScannerInfo baseScannerInfo, IResource resource, URI buildDirectoryURI) { try { Path buildDirectory = Paths.get(buildDirectoryURI); - + List commandLine = new ArrayList<>(); if (command.isAbsolute()) { commandLine.add(command.toString()); } else { - commandLine.add(path.resolve(command).toString()); + commandLine.add(getCommandPath(command).toString()); } if (baseScannerInfo != null && baseScannerInfo.getIncludePaths() != null) { @@ -160,12 +131,18 @@ public class GCCToolChain extends PlatformObject implements IToolChain { commandLine.addAll(Arrays.asList(args)); // Change output to stdout + boolean haveOut = false; for (int i = 0; i < commandLine.size() - 1; ++i) { if (commandLine.get(i).equals("-o")) { //$NON-NLS-1$ commandLine.set(i + 1, "-"); //$NON-NLS-1$ + haveOut = true; break; } } + if (!haveOut) { + commandLine.add("-o"); //$NON-NLS-1$ + commandLine.add("-"); //$NON-NLS-1$ + } // Change source file to a tmp file (needs to be empty) Path tmpFile = null; @@ -259,7 +236,7 @@ public class GCCToolChain extends PlatformObject implements IToolChain { @Override public IEnvironmentVariable getVariable(String name) { - if (pathVar.getName().equals(name)) { + if (path != null && name.equals("PATH")) { //$NON-NLS-1$ return pathVar; } return null; @@ -271,30 +248,46 @@ public class GCCToolChain extends PlatformObject implements IToolChain { } @Override - public Path getCommandPath(String command) { - return path.resolve(command); + public Path getCommandPath(Path command) { + if (command.isAbsolute()) { + return command; + } + + if (path != null) { + return path.resolve(command); + } + + // Look for it in the path environment var + String path = System.getenv("PATH"); //$NON-NLS-1$ + for (String entry : path.split(File.pathSeparator)) { + Path entryPath = Paths.get(entry); + Path cmdPath = entryPath.resolve(command); + if (Files.isExecutable(cmdPath)) { + return cmdPath; + } + } + + return null; + } + + @Override + public String[] getCompileCommands() { + if (compileCommands == null) { + List cmds = new ArrayList<>(); + for (String cmd : new String[] { "gcc", "g++", "clang", "clang++" }) { //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ + cmd = prefix != null ? cmd : prefix + cmd; + Path cmdPath = getCommandPath(Paths.get(cmd)); + if (cmdPath != null) { + cmds.add(cmd); + } + } + compileCommands = cmds.toArray(new String[compileCommands.length]); + } + return compileCommands; } @Override public IResource[] getResourcesFromCommand(String[] cmd, URI buildDirectoryURI) { - // Make sure this is our command - boolean found = false; - for (String arg : cmd) { - if (arg.startsWith("-")) { //$NON-NLS-1$ - break; - } - Path cmdPath = Paths.get(arg); - if (cmdPath.getFileName().toString().equals(command)) { - found = true; - break; - } - } - - if (!found) { - // not our command - return null; - } - // Start at the back looking for arguments List resources = new ArrayList<>(); IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot(); @@ -308,7 +301,7 @@ public class GCCToolChain extends PlatformObject implements IToolChain { resources.add(resource); } } - + return resources.toArray(new IResource[resources.size()]); } diff --git a/build/org.eclipse.cdt.build.gcc.core/src/org/eclipse/cdt/build/gcc/core/GCCToolChainType.java b/build/org.eclipse.cdt.build.gcc.core/src/org/eclipse/cdt/build/gcc/core/GCCToolChainType.java deleted file mode 100644 index 20f24bbf639..00000000000 --- a/build/org.eclipse.cdt.build.gcc.core/src/org/eclipse/cdt/build/gcc/core/GCCToolChainType.java +++ /dev/null @@ -1,28 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2015 QNX Software Systems and others. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - *******************************************************************************/ -package org.eclipse.cdt.build.gcc.core; - -import org.eclipse.cdt.core.build.IToolChain; -import org.eclipse.cdt.core.build.IToolChainType; - -public class GCCToolChainType implements IToolChainType { - - public static final String ID = "org.eclipse.cdt.build.gcc"; //$NON-NLS-1$ - - @Override - public String getId() { - return ID; - } - - @Override - public IToolChain getToolChain(String name) { - // TODO Auto-generated method stub - return null; - } - -} diff --git a/build/org.eclipse.cdt.build.gcc.core/src/org/eclipse/cdt/build/gcc/core/internal/GCCPathToolChainProvider.java b/build/org.eclipse.cdt.build.gcc.core/src/org/eclipse/cdt/build/gcc/core/internal/GCCPathToolChainProvider.java index 20bbdb62ced..c057e806bda 100644 --- a/build/org.eclipse.cdt.build.gcc.core/src/org/eclipse/cdt/build/gcc/core/internal/GCCPathToolChainProvider.java +++ b/build/org.eclipse.cdt.build.gcc.core/src/org/eclipse/cdt/build/gcc/core/internal/GCCPathToolChainProvider.java @@ -11,98 +11,53 @@ import java.io.BufferedReader; import java.io.File; import java.io.IOException; import java.io.InputStreamReader; -import java.nio.file.Path; -import java.nio.file.Paths; -import java.util.ArrayList; -import java.util.Collection; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Map.Entry; +import java.util.HashSet; +import java.util.Set; import java.util.regex.Matcher; import java.util.regex.Pattern; import org.eclipse.cdt.build.gcc.core.GCCToolChain; -import org.eclipse.cdt.build.gcc.core.GCCToolChainType; -import org.eclipse.cdt.core.build.IToolChain; import org.eclipse.cdt.core.build.IToolChainManager; import org.eclipse.cdt.core.build.IToolChainProvider; -import org.eclipse.cdt.core.build.IToolChainType; /** * Finds gcc and clang on the path. */ public class GCCPathToolChainProvider implements IToolChainProvider { - private static Pattern gccPattern = Pattern.compile("(.*-)?(gcc|g\\+\\+|clang|clang\\+\\+)(-[0-9].*)?"); //$NON-NLS-1$ + private static final String ID = "org.eclipse.cdt.build.gcc.core.gccPathProvider"; //$NON-NLS-1$ + + private static final Pattern gccPattern = Pattern.compile("(.*-)?(gcc|g\\+\\+|clang|clang\\+\\+)"); //$NON-NLS-1$ @Override - public Collection getToolChains() { - IToolChainManager manager = Activator.getService(IToolChainManager.class); - IToolChainType type = null; - - List toolChains = new ArrayList<>(); - - String path = null; - for (Entry entry : System.getenv().entrySet()) { - if (entry.getKey().equalsIgnoreCase("PATH")) { //$NON-NLS-1$ - path = entry.getValue(); - break; - } - } - - if (path != null) { - Map> installs = new HashMap<>(); - - for (String dirStr : path.split(File.pathSeparator)) { - File dir = new File(dirStr); - if (dir.isDirectory()) { - for (String file : dir.list()) { - Matcher matcher = gccPattern.matcher(file); - if (matcher.matches()) { - String prefix = matcher.group(1); - String suffix = matcher.group(3); - String command = dirStr + File.separatorChar + file; - String version = getVersion(command); - if (version != null) { - List commands = installs.get(version); - if (commands == null) { - commands = new ArrayList<>(); - installs.put(version, commands); - } - commands.add(command); - } - } - } - } - } - - for (Entry> entry : installs.entrySet()) { - String version = entry.getKey(); - String searchStr; - if (version.contains("LLVM")) { - searchStr = "clang++"; - } else { - searchStr = "g++"; - } - - for (String command : entry.getValue()) { - if (command.contains(searchStr)) { - if (type == null) { - type = manager.getToolChainType(GCCToolChainType.ID); - } - Path commandPath = Paths.get(command); - toolChains.add( - new GCCToolChain(type, commandPath.getParent(), commandPath.getFileName().toString())); - break; - } - } - } - } - - return toolChains; + public String getId() { + return ID; } + + @Override + public void init(IToolChainManager manager) { + Set versions = new HashSet<>(); + String path = System.getenv("PATH"); //$NON-NLS-1$ + for (String dirStr : path.split(File.pathSeparator)) { + File dir = new File(dirStr); + if (dir.isDirectory()) { + for (String file : dir.list()) { + Matcher matcher = gccPattern.matcher(file); + if (matcher.matches()) { + String prefix = matcher.group(1); + String command = dirStr + File.separatorChar + file; + String version = getVersion(command); + if (version != null && !versions.contains(version)) { + versions.add(version); + manager.addToolChain(new GCCToolChain(this, version, dir.toPath(), prefix)); + } + } + } + } + } + } + private static Pattern versionPattern = Pattern.compile(".*(gcc|LLVM) version .*"); //$NON-NLS-1$ private static Pattern targetPattern = Pattern.compile("Target: (.*)"); //$NON-NLS-1$ diff --git a/build/org.eclipse.cdt.build.gcc.core/src/org/eclipse/cdt/build/gcc/core/internal/Msys2ToolChainProvider.java b/build/org.eclipse.cdt.build.gcc.core/src/org/eclipse/cdt/build/gcc/core/internal/Msys2ToolChainProvider.java index 7d452f57cfb..263453a0950 100644 --- a/build/org.eclipse.cdt.build.gcc.core/src/org/eclipse/cdt/build/gcc/core/internal/Msys2ToolChainProvider.java +++ b/build/org.eclipse.cdt.build.gcc.core/src/org/eclipse/cdt/build/gcc/core/internal/Msys2ToolChainProvider.java @@ -9,30 +9,28 @@ package org.eclipse.cdt.build.gcc.core.internal; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.List; import org.eclipse.cdt.build.gcc.core.GCCToolChain; -import org.eclipse.cdt.build.gcc.core.GCCToolChainType; -import org.eclipse.cdt.core.build.IToolChain; import org.eclipse.cdt.core.build.IToolChainManager; import org.eclipse.cdt.core.build.IToolChainProvider; -import org.eclipse.cdt.core.build.IToolChainType; import org.eclipse.cdt.utils.WindowsRegistry; import org.eclipse.core.runtime.Platform; public class Msys2ToolChainProvider implements IToolChainProvider { + private static final String ID = "org.eclipse.cdt.build.gcc.core.msys2Provider"; //$NON-NLS-1$ + @Override - public Collection getToolChains() { + public String getId() { + return ID; + } + + @Override + public void init(IToolChainManager manager) { if (Platform.getOS().equals(Platform.OS_WIN32)) { WindowsRegistry registry = WindowsRegistry.getRegistry(); String uninstallKey = "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall"; //$NON-NLS-1$ String subkey; - List toolChains = null; - IToolChainType type = null; for (int i = 0; (subkey = registry.getCurrentUserKeyName(uninstallKey, i)) != null; i++) { String compKey = uninstallKey + '\\' + subkey; String displayName = registry.getCurrentUserValue(compKey, "DisplayName"); //$NON-NLS-1$ @@ -40,24 +38,11 @@ public class Msys2ToolChainProvider implements IToolChainProvider { String installLocation = registry.getCurrentUserValue(compKey, "InstallLocation"); //$NON-NLS-1$ Path gccPath = Paths.get(installLocation + "\\mingw64\\bin\\gcc.exe"); //$NON-NLS-1$ if (Files.exists(gccPath)) { - if (toolChains == null) { - toolChains = new ArrayList<>(); - } - if (type == null) { - type = Activator.getService(IToolChainManager.class).getToolChainType(GCCToolChainType.ID); - } - toolChains.add( - new GCCToolChain(type, gccPath.getParent(), gccPath.getFileName().toString())); + manager.addToolChain(new GCCToolChain(this, "msys2.x86_64", gccPath.getParent())); //$NON-NLS-1$ } } } - - if (toolChains != null) { - return toolChains; - } } - // default - return Collections.emptyList(); } } diff --git a/build/org.eclipse.cdt.cmake.core/src/org/eclipse/cdt/cmake/core/internal/CMakeBuildConfiguration.java b/build/org.eclipse.cdt.cmake.core/src/org/eclipse/cdt/cmake/core/internal/CMakeBuildConfiguration.java index f618791c387..3c9748dd41b 100644 --- a/build/org.eclipse.cdt.cmake.core/src/org/eclipse/cdt/cmake/core/internal/CMakeBuildConfiguration.java +++ b/build/org.eclipse.cdt.cmake.core/src/org/eclipse/cdt/cmake/core/internal/CMakeBuildConfiguration.java @@ -35,7 +35,8 @@ public class CMakeBuildConfiguration extends CBuildConfiguration { } public CMakeBuildConfiguration(IBuildConfiguration config, String name, IToolChain toolChain) { - super(config, name, toolChain); + super(config, name); + setToolChain(toolChain); } @Override diff --git a/core/org.eclipse.cdt.core/plugin.xml b/core/org.eclipse.cdt.core/plugin.xml index 7591899e132..9c5e8589f27 100644 --- a/core/org.eclipse.cdt.core/plugin.xml +++ b/core/org.eclipse.cdt.core/plugin.xml @@ -685,7 +685,6 @@ - diff --git a/core/org.eclipse.cdt.core/schema/toolChainProvider.exsd b/core/org.eclipse.cdt.core/schema/toolChainProvider.exsd index 774f46d80fb..44873b6b79a 100644 --- a/core/org.eclipse.cdt.core/schema/toolChainProvider.exsd +++ b/core/org.eclipse.cdt.core/schema/toolChainProvider.exsd @@ -1,102 +1,109 @@ - - - - - - - - - A toolchain provider provides automatically discovered toolchains when requested. Providers have enablement to make sure they aren't called unless there's a good chance they have toolchains to offer. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - [Enter the first release in which this extension point appears.] - - - - - - - - - [Enter extension point usage example here.] - - - - - - - - - [Enter API information here.] - - - - - - - - - [Enter information about supplied implementation of this extension point.] - - - - - + + + + + + + + + A toolchain provider provides automatically discovered toolchains when requested. Providers have enablement to make sure they aren't called unless there's a good chance they have toolchains to offer. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + [Enter the first release in which this extension point appears.] + + + + + + + + + [Enter extension point usage example here.] + + + + + + + + + [Enter API information here.] + + + + + + + + + [Enter information about supplied implementation of this extension point.] + + + + + diff --git a/core/org.eclipse.cdt.core/schema/toolChainType.exsd b/core/org.eclipse.cdt.core/schema/toolChainType.exsd deleted file mode 100644 index 6c59d041354..00000000000 --- a/core/org.eclipse.cdt.core/schema/toolChainType.exsd +++ /dev/null @@ -1,127 +0,0 @@ - - - - - - - - - Defines toolchain type extensions. Toolchain types provide toolchain objects for a given type of toolchain. They are passed properties that are stored for the toolchain. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - [Enter the first release in which this extension point appears.] - - - - - - - - - [Enter extension point usage example here.] - - - - - - - - - [Enter API information here.] - - - - - - - - - [Enter information about supplied implementation of this extension point.] - - - - - diff --git a/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/CCorePlugin.java b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/CCorePlugin.java index e395dea7fca..50ebcc512e4 100644 --- a/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/CCorePlugin.java +++ b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/CCorePlugin.java @@ -439,7 +439,7 @@ public class CCorePlugin extends Plugin { * @see #setOptions */ public static HashMap getDefaultOptions() { - HashMap defaultOptions = new HashMap(10); + HashMap defaultOptions = new HashMap<>(10); // see #initializeDefaultPluginPreferences() for changing default // settings @@ -502,7 +502,7 @@ public class CCorePlugin extends Plugin { * @see CCorePlugin#getDefaultOptions */ public static HashMap getOptions() { - HashMap options = new HashMap(10); + HashMap options = new HashMap<>(10); // see #initializeDefaultPluginPreferences() for changing default // settings @@ -728,7 +728,7 @@ public class CCorePlugin extends Plugin { ICDescriptor cdesc = getCProjectDescription(project, false); ICExtensionReference[] cextensions = cdesc.get(BINARY_PARSER_UNIQ_ID, true); if (cextensions.length > 0) { - ArrayList list = new ArrayList(cextensions.length); + ArrayList list = new ArrayList<>(cextensions.length); for (ICExtensionReference ref : cextensions) { IBinaryParser parser = null; try { @@ -1538,11 +1538,15 @@ public class CCorePlugin extends Plugin { * @noreference This method is not intended to be referenced by clients. */ public static void log(Throwable e) { - String msg = e.getMessage(); - if (msg == null) { - log("Error", e); //$NON-NLS-1$ + if (e instanceof CoreException) { + log(((CoreException) e).getStatus()); } else { - log("Error: " + msg, e); //$NON-NLS-1$ + String msg = e.getMessage(); + if (msg == null) { + log("Error", e); //$NON-NLS-1$ + } else { + log("Error: " + msg, e); //$NON-NLS-1$ + } } } diff --git a/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/build/CBuildConfiguration.java b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/build/CBuildConfiguration.java index 376d3d7e0b1..a673e5e3d0a 100644 --- a/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/build/CBuildConfiguration.java +++ b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/build/CBuildConfiguration.java @@ -30,6 +30,9 @@ import org.eclipse.cdt.core.ProblemMarkerInfo; import org.eclipse.cdt.core.envvar.IEnvironmentVariable; import org.eclipse.cdt.core.model.CoreModel; import org.eclipse.cdt.core.model.ICModelMarker; +import org.eclipse.cdt.core.model.ICProject; +import org.eclipse.cdt.core.model.IOutputEntry; +import org.eclipse.cdt.core.model.IPathEntry; import org.eclipse.cdt.core.parser.IExtendedScannerInfo; import org.eclipse.cdt.core.parser.IScannerInfo; import org.eclipse.cdt.core.parser.IScannerInfoChangeListener; @@ -67,37 +70,11 @@ public abstract class CBuildConfiguration extends PlatformObject private final String name; private final IBuildConfiguration config; - private final IToolChain toolChain; + private IToolChain toolChain; protected CBuildConfiguration(IBuildConfiguration config, String name) { this.config = config; this.name = name; - - // Load toolchain from prefs - Preferences settings = getSettings(); - String typeId = settings.get(TOOLCHAIN_TYPE, ""); //$NON-NLS-1$ - String id = settings.get(TOOLCHAIN_NAME, ""); //$NON-NLS-1$ - IToolChainManager toolChainManager = CCorePlugin.getService(IToolChainManager.class); - toolChain = !id.isEmpty() ? toolChainManager.getToolChain(typeId, id) : null; - - if (toolChain == null) { - CCorePlugin.log(String.format("Toolchain missing for config: %s", config.getName())); - } - } - - protected CBuildConfiguration(IBuildConfiguration config, String name, IToolChain toolChain) { - this.config = config; - this.name = name; - - this.toolChain = toolChain; - Preferences settings = getSettings(); - settings.put(TOOLCHAIN_TYPE, toolChain.getType().getId()); - settings.put(TOOLCHAIN_NAME, toolChain.getName()); - try { - settings.flush(); - } catch (BackingStoreException e) { - CCorePlugin.log(e); - } } @Override @@ -124,7 +101,16 @@ public abstract class CBuildConfiguration extends PlatformObject IFolder buildFolder = buildRootFolder.getFolder(name); if (!buildFolder.exists()) { buildFolder.create(true, true, new NullProgressMonitor()); + buildFolder.setDerived(true, null); + ICProject cproject = CoreModel.getDefault().create(getProject()); + IOutputEntry output = CoreModel.newOutputEntry(buildFolder.getFullPath()); + IPathEntry[] oldEntries = cproject.getRawPathEntries(); + IPathEntry[] newEntries = new IPathEntry[oldEntries.length + 1]; + System.arraycopy(oldEntries, 0, newEntries, 0, oldEntries.length); + newEntries[oldEntries.length] = output; + cproject.setRawPathEntries(newEntries, null); } + return buildFolder; } @@ -136,7 +122,7 @@ public abstract class CBuildConfiguration extends PlatformObject return Paths.get(getBuildDirectoryURI()); } - protected void setBuildEnvironment(Map env) { + public void setBuildEnvironment(Map env) { CCorePlugin.getDefault().getBuildEnvironmentManager().setEnvironment(env, config, true); } @@ -158,10 +144,35 @@ public abstract class CBuildConfiguration extends PlatformObject } @Override - public IToolChain getToolChain() { + public IToolChain getToolChain() throws CoreException { + if (toolChain == null) { + Preferences settings = getSettings(); + String typeId = settings.get(TOOLCHAIN_TYPE, ""); //$NON-NLS-1$ + String id = settings.get(TOOLCHAIN_NAME, ""); //$NON-NLS-1$ + IToolChainManager toolChainManager = CCorePlugin.getService(IToolChainManager.class); + toolChain = toolChainManager.getToolChain(typeId, id); + + if (toolChain == null) { + CCorePlugin.log(String.format("Toolchain missing for config: %s", config.getName())); + } + } + return toolChain; } + protected void setToolChain(IToolChain toolChain) { + this.toolChain = toolChain; + + Preferences settings = getSettings(); + settings.put(TOOLCHAIN_TYPE, toolChain.getProvider().getId()); + settings.put(TOOLCHAIN_NAME, toolChain.getName()); + try { + settings.flush(); + } catch (BackingStoreException e) { + CCorePlugin.log(e); + } + } + @Override public IEnvironmentVariable getVariable(String name) { // By default, none @@ -346,7 +357,7 @@ public abstract class CBuildConfiguration extends PlatformObject cheaterInfo = new HashMap<>(); } } - + @Override public IScannerInfo getScannerInformation(IResource resource) { initScannerInfo(); @@ -358,8 +369,29 @@ public abstract class CBuildConfiguration extends PlatformObject // TODO smarter line parsing to deal with quoted arguments String[] command = line.split("\\s+"); //$NON-NLS-1$ + // Make sure it's a compile command + boolean found = false; + String[] compileCommands = toolChain.getCompileCommands(); + for (String arg : command) { + if (arg.startsWith("-")) { //$NON-NLS-1$ + // option found, missed our command + break; + } + + for (String cc : compileCommands) { + if (arg.equals(cc)) { + found = true; + break; + } + } + } + + if (!found) { + return false; + } + try { - IResource[] resources = getToolChain().getResourcesFromCommand(command, getBuildDirectoryURI()); + IResource[] resources = toolChain.getResourcesFromCommand(command, getBuildDirectoryURI()); if (resources != null) { for (IResource resource : resources) { initScannerInfo(); diff --git a/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/build/ICBuildConfiguration.java b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/build/ICBuildConfiguration.java index 0bbeaff2490..e40be338c3a 100644 --- a/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/build/ICBuildConfiguration.java +++ b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/build/ICBuildConfiguration.java @@ -34,18 +34,18 @@ public interface ICBuildConfiguration extends IAdaptable, IScannerInfoProvider { * * @return resources build configuration */ - IBuildConfiguration getBuildConfiguration(); + IBuildConfiguration getBuildConfiguration() throws CoreException; /** * Build Configurations are configurations for a given toolchain. * * @return the toolchain for this build configuration */ - IToolChain getToolChain(); + IToolChain getToolChain() throws CoreException; - IEnvironmentVariable getVariable(String name); + IEnvironmentVariable getVariable(String name) throws CoreException; - IEnvironmentVariable[] getVariables(); + IEnvironmentVariable[] getVariables() throws CoreException; IProject[] build(int kind, Map args, IConsole console, IProgressMonitor monitor) throws CoreException; diff --git a/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/build/ICBuildConfigurationManager.java b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/build/ICBuildConfigurationManager.java index 6a70b434b05..b2f1cefffba 100644 --- a/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/build/ICBuildConfigurationManager.java +++ b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/build/ICBuildConfigurationManager.java @@ -35,6 +35,8 @@ public interface ICBuildConfigurationManager { IBuildConfiguration createBuildConfiguration(ICBuildConfigurationProvider provider, IProject project, String configName, IProgressMonitor monitor) throws CoreException; + IBuildConfiguration getBuildConfiguration(ICBuildConfigurationProvider provider, IProject project, String configName) throws CoreException; + /** * Called by providers to add new build configurations as they are created. * @@ -52,8 +54,8 @@ public interface ICBuildConfigurationManager { * @param buildConfig * @return the matching CDT build configuration */ - ICBuildConfiguration getBuildConfiguration(IBuildConfiguration buildConfig); - + ICBuildConfiguration getBuildConfiguration(IBuildConfiguration buildConfig) throws CoreException; + ICBuildConfiguration getDefaultBuildConfiguration(IProject project) throws CoreException; } diff --git a/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/build/ICBuildConfigurationProvider.java b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/build/ICBuildConfigurationProvider.java index 40aa5dde766..7885bf0a559 100644 --- a/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/build/ICBuildConfigurationProvider.java +++ b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/build/ICBuildConfigurationProvider.java @@ -31,7 +31,7 @@ public interface ICBuildConfigurationProvider { * @param config * @return CDT build configuration for the Platform build configuration */ - ICBuildConfiguration getCBuildConfiguration(IBuildConfiguration config, String name); + ICBuildConfiguration getCBuildConfiguration(IBuildConfiguration config, String name) throws CoreException; /** * Returns a default C build configuration for a given project if any. diff --git a/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/build/IToolChain.java b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/build/IToolChain.java index 6510be961e4..375f6afbb51 100644 --- a/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/build/IToolChain.java +++ b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/build/IToolChain.java @@ -28,7 +28,7 @@ public interface IToolChain extends IAdaptable { static final String ATTR_OS = "os"; //$NON-NLS-1$ static final String ATTR_ARCH = "arch"; //$NON-NLS-1$ - IToolChainType getType(); + IToolChainProvider getProvider(); String getName(); @@ -52,8 +52,10 @@ public interface IToolChain extends IAdaptable { String[] getErrorParserIds(); - Path getCommandPath(String command); + Path getCommandPath(Path command); + + String[] getCompileCommands(); IResource[] getResourcesFromCommand(String[] command, URI buildDirectoryURI); - + } diff --git a/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/build/IToolChainManager.java b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/build/IToolChainManager.java index d1ebdd75ea4..bd5282fbd62 100644 --- a/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/build/IToolChainManager.java +++ b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/build/IToolChainManager.java @@ -10,6 +10,8 @@ package org.eclipse.cdt.core.build; import java.util.Collection; import java.util.Map; +import org.eclipse.core.runtime.CoreException; + /** * The global toolchain manager. Accessed as an OSGi service. * @@ -17,9 +19,11 @@ import java.util.Map; */ public interface IToolChainManager { - IToolChainType getToolChainType(String id); - - IToolChain getToolChain(String typeId, String name); + IToolChainProvider getProvider(String providerId) throws CoreException; + + IToolChain getToolChain(String providerId, String name) throws CoreException; + + Collection getToolChains(String providerId) throws CoreException; /** * Returns the list of toolchains that have the given properties. @@ -28,6 +32,10 @@ public interface IToolChainManager { * properties of the toolchains * @return the qualified toolchains */ - Collection getToolChainsMatching(Map properties); + Collection getToolChainsMatching(Map properties) throws CoreException; + + void addToolChain(IToolChain toolChain); + + void removeToolChain(IToolChain toolChain); } diff --git a/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/build/IToolChainProvider.java b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/build/IToolChainProvider.java index 813f6268bef..e17dc46f7ec 100644 --- a/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/build/IToolChainProvider.java +++ b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/build/IToolChainProvider.java @@ -7,7 +7,7 @@ *******************************************************************************/ package org.eclipse.cdt.core.build; -import java.util.Collection; +import org.eclipse.core.runtime.CoreException; /** * A provider of toolchains. Registered with the toolChainProvider extension @@ -17,6 +17,34 @@ import java.util.Collection; */ public interface IToolChainProvider { - Collection getToolChains(); + /** + * Returns the id for this provider. + * + * @return id + */ + String getId(); + + /** + * Initialize the list of toolchains. + * + * @param manager handle on manager to add or remove them + */ + default void init(IToolChainManager manager) throws CoreException { + // By default, toolchains are created on demand + } + + /** + * Called by the manager to dynamically create the named toolchain. + * + * @param name + * the name of the toolchain + * @param properties + * the persisted settings for the toolchain + * @return the toolchain initialized with the settings. + */ + default IToolChain getToolChain(String name) throws CoreException { + // By default, assumes all toolchains were added at init time. + return null; + } } diff --git a/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/build/IToolChainType.java b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/build/IToolChainType.java deleted file mode 100644 index 8e8b9d3f7db..00000000000 --- a/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/build/IToolChainType.java +++ /dev/null @@ -1,31 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2015 QNX Software Systems and others. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - *******************************************************************************/ -package org.eclipse.cdt.core.build; - -/** - * A type of toolchain. - * - * @since 6.0 - */ -public interface IToolChainType { - - String getId(); - - /** - * Called by the toolchain to inflate the toolchain from the user preference - * store. - * - * @param name - * the name of the toolchain - * @param properties - * the persisted settings for the toolchain - * @return the toolchain initialized with the settings. - */ - IToolChain getToolChain(String name); - -} diff --git a/core/org.eclipse.cdt.core/src/org/eclipse/cdt/internal/core/build/CBuildConfigAdapterFactory.java b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/internal/core/build/CBuildConfigAdapterFactory.java index 24669b99228..cf4869d7163 100644 --- a/core/org.eclipse.cdt.core/src/org/eclipse/cdt/internal/core/build/CBuildConfigAdapterFactory.java +++ b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/internal/core/build/CBuildConfigAdapterFactory.java @@ -11,6 +11,7 @@ import org.eclipse.cdt.core.CCorePlugin; import org.eclipse.cdt.core.build.ICBuildConfiguration; import org.eclipse.cdt.core.build.ICBuildConfigurationManager; import org.eclipse.core.resources.IBuildConfiguration; +import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IAdapterFactory; public class CBuildConfigAdapterFactory implements IAdapterFactory { @@ -23,7 +24,11 @@ public class CBuildConfigAdapterFactory implements IAdapterFactory { if (ICBuildConfiguration.class.equals(adapterType) && adaptableObject instanceof IBuildConfiguration) { IBuildConfiguration config = (IBuildConfiguration) adaptableObject; - return (T) manager.getBuildConfiguration(config); + try { + return (T) manager.getBuildConfiguration(config); + } catch (CoreException e) { + CCorePlugin.log(e); + } } return null; } diff --git a/core/org.eclipse.cdt.core/src/org/eclipse/cdt/internal/core/build/CBuildConfigurationManager.java b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/internal/core/build/CBuildConfigurationManager.java index 94a3dbe9fc8..fcd123d1741 100644 --- a/core/org.eclipse.cdt.core/src/org/eclipse/cdt/internal/core/build/CBuildConfigurationManager.java +++ b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/internal/core/build/CBuildConfigurationManager.java @@ -139,7 +139,7 @@ public class CBuildConfigurationManager implements ICBuildConfigurationManager, } @Override - public ICBuildConfiguration getBuildConfiguration(IBuildConfiguration buildConfig) { + public ICBuildConfiguration getBuildConfiguration(IBuildConfiguration buildConfig) throws CoreException { initProviders(); synchronized (configs) { ICBuildConfiguration config = configs.get(buildConfig); @@ -160,6 +160,13 @@ public class CBuildConfigurationManager implements ICBuildConfigurationManager, } } + @Override + public IBuildConfiguration getBuildConfiguration(ICBuildConfigurationProvider provider, IProject project, + String configName) throws CoreException { + String name = provider.getId() + '/' + configName; + return project.getBuildConfig(name); + } + @Override public ICBuildConfiguration getDefaultBuildConfiguration(IProject project) throws CoreException { initProviders(); diff --git a/core/org.eclipse.cdt.core/src/org/eclipse/cdt/internal/core/build/ToolChainManager.java b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/internal/core/build/ToolChainManager.java index e3cdfdd525f..67572bccdfe 100644 --- a/core/org.eclipse.cdt.core/src/org/eclipse/cdt/internal/core/build/ToolChainManager.java +++ b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/internal/core/build/ToolChainManager.java @@ -9,6 +9,7 @@ package org.eclipse.cdt.internal.core.build; import java.util.ArrayList; import java.util.Collection; +import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -17,7 +18,6 @@ import org.eclipse.cdt.core.CCorePlugin; import org.eclipse.cdt.core.build.IToolChain; import org.eclipse.cdt.core.build.IToolChainManager; import org.eclipse.cdt.core.build.IToolChainProvider; -import org.eclipse.cdt.core.build.IToolChainType; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IConfigurationElement; import org.eclipse.core.runtime.IExtensionPoint; @@ -26,41 +26,33 @@ import org.eclipse.core.runtime.Platform; public class ToolChainManager implements IToolChainManager { - private Map typeElements; - private Map types; + private Map providerElements; + private Map providers; private Map> toolChains; private void init() { - if (typeElements == null) { - typeElements = new HashMap<>(); - types = new HashMap<>(); + if (providerElements == null) { + providerElements = new HashMap<>(); + providers = new HashMap<>(); // Load the types IExtensionRegistry registry = Platform.getExtensionRegistry(); - IExtensionPoint typesPoint = registry.getExtensionPoint(CCorePlugin.PLUGIN_ID + ".toolChainType"); //$NON-NLS-1$ + IExtensionPoint typesPoint = registry + .getExtensionPoint(CCorePlugin.PLUGIN_ID + ".toolChainProvider"); //$NON-NLS-1$ for (IConfigurationElement element : typesPoint.getConfigurationElements()) { String id = element.getAttribute("id"); //$NON-NLS-1$ - typeElements.put(id, element); + providerElements.put(id, element); } // Load the discovered toolchains toolChains = new HashMap<>(); - IExtensionPoint providersPoint = registry - .getExtensionPoint(CCorePlugin.PLUGIN_ID + ".toolChainProvider"); //$NON-NLS-1$ - for (IConfigurationElement element : providersPoint.getConfigurationElements()) { + for (IConfigurationElement element : providerElements.values()) { // TODO check for enablement try { IToolChainProvider provider = (IToolChainProvider) element .createExecutableExtension("class"); //$NON-NLS-1$ - for (IToolChain toolChain : provider.getToolChains()) { - String typeId = toolChain.getType().getId(); - Map tcs = toolChains.get(typeId); - if (tcs == null) { - tcs = new HashMap<>(); - toolChains.put(typeId, tcs); - } - tcs.put(toolChain.getName(), toolChain); - } + providers.put(element.getAttribute("id"), provider); //$NON-NLS-1$ + provider.init(this); } catch (CoreException e) { CCorePlugin.log(e); } @@ -69,28 +61,65 @@ public class ToolChainManager implements IToolChainManager { } @Override - public IToolChainType getToolChainType(String id) { + public void addToolChain(IToolChain toolChain) { + String providerId = toolChain.getProvider().getId(); + Map provider = toolChains.get(providerId); + if (provider == null) { + provider = new HashMap<>(); + toolChains.put(providerId, provider); + } + provider.put(toolChain.getName(), toolChain); + } + + @Override + public void removeToolChain(IToolChain toolChain) { + String providerId = toolChain.getProvider().getId(); + Map provider = toolChains.get(providerId); + if (provider != null) { + provider.remove(toolChain.getName()); + } + } + + @Override + public IToolChainProvider getProvider(String providerId) throws CoreException { init(); - IToolChainType type = types.get(id); - if (type == null) { - IConfigurationElement element = typeElements.get(id); + IToolChainProvider provider = providers.get(providerId); + if (provider == null) { + IConfigurationElement element = providerElements.get(providerId); if (element != null) { - try { - type = (IToolChainType) element.createExecutableExtension("class"); //$NON-NLS-1$ - types.put(id, type); - } catch (CoreException e) { - CCorePlugin.log(e); - } + provider = (IToolChainProvider) element.createExecutableExtension("class"); //$NON-NLS-1$ + providers.put(providerId, provider); } } - return type; + return provider; } @Override - public IToolChain getToolChain(String typeId, String name) { + public IToolChain getToolChain(String providerId, String name) throws CoreException { init(); - Map tcs = toolChains.get(typeId); - return tcs != null ? tcs.get(name) : null; + Map provider = toolChains.get(providerId); + if (provider != null) { + IToolChain toolChain = provider.get(name); + if (toolChain != null) { + return toolChain; + } + } + + // Try the provider + IToolChainProvider realProvider = providers.get(providerId); + if (realProvider != null) { + IToolChain toolChain = realProvider.getToolChain(name); + if (toolChain != null) { + if (provider == null) { + provider = new HashMap<>(); + toolChains.put(providerId, provider); + } + provider.put(name, toolChain); + return toolChain; + } + } + + return null; } @Override @@ -111,4 +140,15 @@ public class ToolChainManager implements IToolChainManager { return tcs; } + @Override + public Collection getToolChains(String providerId) { + init(); + Map provider = toolChains.get(providerId); + if (provider != null) { + return Collections.unmodifiableCollection(provider.values()); + } else { + return Collections.emptyList(); + } + } + } diff --git a/core/org.eclipse.cdt.core/src/org/eclipse/cdt/internal/core/envvar/BuildConfigEnvironmentSupplier.java b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/internal/core/envvar/BuildConfigEnvironmentSupplier.java index 53639820d65..3bde8eff65a 100644 --- a/core/org.eclipse.cdt.core/src/org/eclipse/cdt/internal/core/envvar/BuildConfigEnvironmentSupplier.java +++ b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/internal/core/envvar/BuildConfigEnvironmentSupplier.java @@ -7,9 +7,11 @@ *******************************************************************************/ package org.eclipse.cdt.internal.core.envvar; +import org.eclipse.cdt.core.CCorePlugin; import org.eclipse.cdt.core.build.ICBuildConfiguration; import org.eclipse.cdt.core.envvar.IEnvironmentVariable; import org.eclipse.core.resources.IBuildConfiguration; +import org.eclipse.core.runtime.CoreException; public class BuildConfigEnvironmentSupplier implements ICoreEnvironmentVariableSupplier { @@ -19,7 +21,12 @@ public class BuildConfigEnvironmentSupplier implements ICoreEnvironmentVariableS ICBuildConfiguration cconfig = ((IBuildConfiguration) context) .getAdapter(ICBuildConfiguration.class); if (cconfig != null) { - return cconfig.getVariable(name); + try { + return cconfig.getVariable(name); + } catch (CoreException e) { + CCorePlugin.log(e); + return null; + } } } return null; @@ -31,7 +38,12 @@ public class BuildConfigEnvironmentSupplier implements ICoreEnvironmentVariableS ICBuildConfiguration cconfig = ((IBuildConfiguration) context) .getAdapter(ICBuildConfiguration.class); if (cconfig != null) { - return cconfig.getVariables(); + try { + return cconfig.getVariables(); + } catch (CoreException e) { + CCorePlugin.log(e); + return null; + } } } return null; diff --git a/core/org.eclipse.cdt.core/src/org/eclipse/cdt/internal/core/envvar/ToolChainEnvironmentSupplier.java b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/internal/core/envvar/ToolChainEnvironmentSupplier.java index 888606781cb..889fade0c6c 100644 --- a/core/org.eclipse.cdt.core/src/org/eclipse/cdt/internal/core/envvar/ToolChainEnvironmentSupplier.java +++ b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/internal/core/envvar/ToolChainEnvironmentSupplier.java @@ -7,10 +7,12 @@ *******************************************************************************/ package org.eclipse.cdt.internal.core.envvar; +import org.eclipse.cdt.core.CCorePlugin; import org.eclipse.cdt.core.build.ICBuildConfiguration; import org.eclipse.cdt.core.build.IToolChain; import org.eclipse.cdt.core.envvar.IEnvironmentVariable; import org.eclipse.core.resources.IBuildConfiguration; +import org.eclipse.core.runtime.CoreException; public class ToolChainEnvironmentSupplier implements ICoreEnvironmentVariableSupplier { @@ -20,9 +22,14 @@ public class ToolChainEnvironmentSupplier implements ICoreEnvironmentVariableSup ICBuildConfiguration config = ((IBuildConfiguration) context) .getAdapter(ICBuildConfiguration.class); if (config != null) { - IToolChain toolChain = config.getToolChain(); - if (toolChain != null) { - return toolChain.getVariable(name); + try { + IToolChain toolChain = config.getToolChain(); + if (toolChain != null) { + return toolChain.getVariable(name); + } + } catch (CoreException e) { + CCorePlugin.log(e); + return null; } } } @@ -35,9 +42,14 @@ public class ToolChainEnvironmentSupplier implements ICoreEnvironmentVariableSup ICBuildConfiguration config = ((IBuildConfiguration) context) .getAdapter(ICBuildConfiguration.class); if (config != null) { - IToolChain toolChain = config.getToolChain(); - if (toolChain != null) { - return toolChain.getVariables(); + try { + IToolChain toolChain = config.getToolChain(); + if (toolChain != null) { + return toolChain.getVariables(); + } + } catch (CoreException e) { + CCorePlugin.log(e); + return null; } } } diff --git a/qt/org.eclipse.cdt.qt.core/plugin.xml b/qt/org.eclipse.cdt.qt.core/plugin.xml index d6eb6d5449b..8a803076e08 100644 --- a/qt/org.eclipse.cdt.qt.core/plugin.xml +++ b/qt/org.eclipse.cdt.qt.core/plugin.xml @@ -192,7 +192,8 @@ + class="org.eclipse.cdt.qt.core.QtMinGWToolChainProvider" + id="org.eclipse.cdt.qt.core.qtMinGWProvider"> model, IProgressMonitor monitor) throws CoreException { super.generate(model, monitor); diff --git a/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/qt/core/QtLaunchConfigurationDelegate.java b/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/qt/core/QtLaunchConfigurationDelegate.java index dc3862bccca..ad8babf5c5a 100644 --- a/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/qt/core/QtLaunchConfigurationDelegate.java +++ b/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/qt/core/QtLaunchConfigurationDelegate.java @@ -60,7 +60,7 @@ public abstract class QtLaunchConfigurationDelegate extends LaunchConfigurationT properties.put(IToolChain.ATTR_ARCH, arch); } } - + protected IQtBuildConfiguration getQtBuildConfiguration(ILaunchConfiguration configuration, String mode, ILaunchTarget target, IProgressMonitor monitor) throws CoreException { // Find the Qt build config @@ -72,10 +72,13 @@ public abstract class QtLaunchConfigurationDelegate extends LaunchConfigurationT // Find the toolchains that support this target Map properties = new HashMap<>(); populateToolChainProperties(target, properties); - + IToolChainManager toolChainManager = Activator.getService(IToolChainManager.class); for (IToolChain toolChain : toolChainManager.getToolChainsMatching(properties)) { - IQtBuildConfiguration qtConfig = provider.createConfiguration(project, toolChain, mode, monitor); + IQtBuildConfiguration qtConfig = provider.getConfiguration(project, toolChain, mode, monitor); + if (qtConfig == null) { + qtConfig = provider.createConfiguration(project, toolChain, mode, monitor); + } if (qtConfig != null) { return qtConfig; } diff --git a/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/qt/core/QtMinGWToolChainProvider.java b/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/qt/core/QtMinGWToolChainProvider.java index a484f8dedb5..2fb4a213577 100644 --- a/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/qt/core/QtMinGWToolChainProvider.java +++ b/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/qt/core/QtMinGWToolChainProvider.java @@ -11,29 +11,30 @@ import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; -import java.util.Collection; -import java.util.Collections; -import java.util.stream.Collectors; import org.eclipse.cdt.build.gcc.core.GCCToolChain; -import org.eclipse.cdt.build.gcc.core.GCCToolChainType; -import org.eclipse.cdt.core.build.IToolChain; import org.eclipse.cdt.core.build.IToolChainManager; import org.eclipse.cdt.core.build.IToolChainProvider; -import org.eclipse.cdt.core.build.IToolChainType; import org.eclipse.cdt.internal.qt.core.Activator; import org.eclipse.cdt.utils.WindowsRegistry; +import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.Platform; public class QtMinGWToolChainProvider implements IToolChainProvider { + private static final String ID = "org.eclipse.cdt.qt.core.qtMinGWProvider"; //$NON-NLS-1$ + @Override - public Collection getToolChains() { + public String getId() { + return ID; + } + + @Override + public void init(IToolChainManager manager) throws CoreException { if (Platform.getOS().equals(Platform.OS_WIN32)) { WindowsRegistry registry = WindowsRegistry.getRegistry(); String uninstallKey = "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall"; //$NON-NLS-1$ String subkey; - IToolChainType type = Activator.getService(IToolChainManager.class).getToolChainType(GCCToolChainType.ID); for (int i = 0; (subkey = registry.getCurrentUserKeyName(uninstallKey, i)) != null; i++) { String compKey = uninstallKey + '\\' + subkey; String displayName = registry.getCurrentUserValue(compKey, "DisplayName"); //$NON-NLS-1$ @@ -41,18 +42,16 @@ public class QtMinGWToolChainProvider implements IToolChainProvider { String installLocation = registry.getCurrentUserValue(compKey, "InstallLocation"); //$NON-NLS-1$ Path gcc = Paths.get("\\bin\\gcc.exe"); //$NON-NLS-1$ try { - return Files.walk(Paths.get(installLocation).resolve("Tools"), 1) //$NON-NLS-1$ + Files.walk(Paths.get(installLocation).resolve("Tools"), 1) //$NON-NLS-1$ .filter((path) -> Files.exists(path.resolve(gcc))) - .map((path) -> new GCCToolChain(type, path.resolve("bin"), "gcc.exe")) //$NON-NLS-1$ //$NON-NLS-2$ - .collect(Collectors.toList()); + .map((path) -> new GCCToolChain(this, "qt.mingw", path.resolve("bin"))) //$NON-NLS-1$ //$NON-NLS-2$ + .forEach(toolChain -> manager.addToolChain(toolChain)); } catch (IOException e) { Activator.log(e); } } } } - // default - return Collections.emptyList(); } } diff --git a/qt/org.eclipse.cdt.qt.ui/src/org/eclipse/cdt/internal/qt/ui/wizards/HelloWorldWizard.java b/qt/org.eclipse.cdt.qt.ui/src/org/eclipse/cdt/internal/qt/ui/wizards/HelloWorldWizard.java index 8b3f2a23dec..3b9765c274d 100644 --- a/qt/org.eclipse.cdt.qt.ui/src/org/eclipse/cdt/internal/qt/ui/wizards/HelloWorldWizard.java +++ b/qt/org.eclipse.cdt.qt.ui/src/org/eclipse/cdt/internal/qt/ui/wizards/HelloWorldWizard.java @@ -7,75 +7,11 @@ *******************************************************************************/ package org.eclipse.cdt.internal.qt.ui.wizards; -import java.lang.reflect.InvocationTargetException; -import java.util.HashMap; -import java.util.Map; - -import org.eclipse.cdt.internal.qt.core.project.QtProjectGenerator; -import org.eclipse.core.resources.ResourcesPlugin; -import org.eclipse.core.runtime.CoreException; -import org.eclipse.core.runtime.IProgressMonitor; -import org.eclipse.core.runtime.jobs.ISchedulingRule; -import org.eclipse.jface.dialogs.Dialog; -import org.eclipse.swt.widgets.Composite; -import org.eclipse.ui.actions.WorkspaceModifyOperation; -import org.eclipse.ui.dialogs.WizardNewProjectCreationPage; -import org.eclipse.ui.wizards.newresource.BasicNewResourceWizard; - -public class HelloWorldWizard extends BasicNewResourceWizard { - - private WizardNewProjectCreationPage mainPage; +public class HelloWorldWizard extends QtProjectTemplateWizard { @Override - public void addPages() { - mainPage = new WizardNewProjectCreationPage("basicNewProjectPage") { //$NON-NLS-1$ - @Override - public void createControl(Composite parent) { - super.createControl(parent); - createWorkingSetGroup((Composite) getControl(), getSelection(), - new String[] { "org.eclipse.ui.resourceWorkingSetPage" }); //$NON-NLS-1$ - Dialog.applyDialogFont(getControl()); - } - }; - mainPage.setTitle("New Qt Project"); //$NON-NLS-1$ - mainPage.setDescription("Specify properties of new Qt project."); //$NON-NLS-1$ - this.addPage(mainPage); - } - protected String getTemplateManifestPath() { return "templates/project2/appProject/manifest.xml"; //$NON-NLS-1$ } - @Override - public boolean performFinish() { - QtProjectGenerator generator = new QtProjectGenerator(); - generator.setTemplateManifestPath(getTemplateManifestPath()); - generator.setProjectName(mainPage.getProjectName()); - if (!mainPage.useDefaults()) { - generator.setLocationURI(mainPage.getLocationURI()); - } - - Map model = new HashMap<>(); - - try { - getContainer().run(true, true, new WorkspaceModifyOperation() { - @Override - protected void execute(IProgressMonitor monitor) - throws CoreException, InvocationTargetException, InterruptedException { - monitor.beginTask("Generating project", 1); //$NON-NLS-1$ - generator.generate(model, monitor); - monitor.done(); - } - - @Override - public ISchedulingRule getRule() { - return ResourcesPlugin.getWorkspace().getRoot(); - } - }); - } catch (InterruptedException | InvocationTargetException e) { - throw new RuntimeException(e); - } - return true; - } - } diff --git a/qt/org.eclipse.cdt.qt.ui/src/org/eclipse/cdt/internal/qt/ui/wizards/QtProjectTemplateWizard.java b/qt/org.eclipse.cdt.qt.ui/src/org/eclipse/cdt/internal/qt/ui/wizards/QtProjectTemplateWizard.java new file mode 100644 index 00000000000..74eca8925d7 --- /dev/null +++ b/qt/org.eclipse.cdt.qt.ui/src/org/eclipse/cdt/internal/qt/ui/wizards/QtProjectTemplateWizard.java @@ -0,0 +1,49 @@ +/******************************************************************************* + * Copyright (c) 2016 QNX Software Systems and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + *******************************************************************************/ +package org.eclipse.cdt.internal.qt.ui.wizards; + +import org.eclipse.cdt.internal.qt.core.project.QtProjectGenerator; +import org.eclipse.jface.dialogs.Dialog; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.tools.templates.core.IGenerator; +import org.eclipse.tools.templates.ui.TemplateWizard; +import org.eclipse.ui.dialogs.WizardNewProjectCreationPage; + +public abstract class QtProjectTemplateWizard extends TemplateWizard { + + private WizardNewProjectCreationPage mainPage; + + @Override + public void addPages() { + mainPage = new WizardNewProjectCreationPage("basicNewProjectPage") { //$NON-NLS-1$ + @Override + public void createControl(Composite parent) { + super.createControl(parent); + createWorkingSetGroup((Composite) getControl(), getSelection(), + new String[] { "org.eclipse.ui.resourceWorkingSetPage" }); //$NON-NLS-1$ + Dialog.applyDialogFont(getControl()); + } + }; + mainPage.setTitle("New Qt Project"); //$NON-NLS-1$ + mainPage.setDescription("Specify properties of new Qt project."); //$NON-NLS-1$ + this.addPage(mainPage); + } + + protected abstract String getTemplateManifestPath(); + + @Override + protected IGenerator getGenerator() { + QtProjectGenerator generator = new QtProjectGenerator(getTemplateManifestPath()); + generator.setProjectName(mainPage.getProjectName()); + if (!mainPage.useDefaults()) { + generator.setLocationURI(mainPage.getLocationURI()); + } + return generator; + } + +} diff --git a/releng/org.eclipse.cdt.repo/category.xml b/releng/org.eclipse.cdt.repo/category.xml index a8f7c5ca073..52cc1eae5ae 100644 --- a/releng/org.eclipse.cdt.repo/category.xml +++ b/releng/org.eclipse.cdt.repo/category.xml @@ -95,6 +95,7 @@ + diff --git a/toolchains/arduino/org.eclipse.cdt.arduino.core/META-INF/MANIFEST.MF b/toolchains/arduino/org.eclipse.cdt.arduino.core/META-INF/MANIFEST.MF index 7a81a68875e..2f617f1dded 100644 --- a/toolchains/arduino/org.eclipse.cdt.arduino.core/META-INF/MANIFEST.MF +++ b/toolchains/arduino/org.eclipse.cdt.arduino.core/META-INF/MANIFEST.MF @@ -15,14 +15,14 @@ Require-Bundle: org.eclipse.core.runtime, org.eclipse.remote.serial.core;bundle-version="1.0.0", com.google.gson;bundle-version="2.2.4", org.apache.commons.compress;bundle-version="1.6.0", - org.freemarker;bundle-version="2.3.22", - org.eclipse.launchbar.remote.core;bundle-version="1.0.0" + org.eclipse.launchbar.remote.core;bundle-version="1.0.0", + org.eclipse.tools.templates.freemarker;bundle-version="1.0.0";visibility:=reexport, + org.eclipse.cdt.build.gcc.core;bundle-version="1.0.0" Bundle-RequiredExecutionEnvironment: JavaSE-1.8 Bundle-ActivationPolicy: lazy Bundle-ClassPath: . Export-Package: org.eclipse.cdt.arduino.core.internal;x-friends:="org.eclipse.cdt.arduino.ui", org.eclipse.cdt.arduino.core.internal.board;x-friends:="org.eclipse.cdt.arduino.ui", org.eclipse.cdt.arduino.core.internal.build;x-friends:="org.eclipse.cdt.arduino.ui", - org.eclipse.cdt.arduino.core.internal.console;x-friends:="org.eclipse.cdt.arduino.ui", org.eclipse.cdt.arduino.core.internal.remote;x-friends:="org.eclipse.cdt.arduino.ui" Bundle-Localization: plugin diff --git a/toolchains/arduino/org.eclipse.cdt.arduino.core/plugin.xml b/toolchains/arduino/org.eclipse.cdt.arduino.core/plugin.xml index 8399a090f76..8ececf48b6a 100644 --- a/toolchains/arduino/org.eclipse.cdt.arduino.core/plugin.xml +++ b/toolchains/arduino/org.eclipse.cdt.arduino.core/plugin.xml @@ -75,40 +75,9 @@ + id="com.qnx.tools.ide.qde.core.cbuilder"> - - - - - - - - - - - - - - - - + + + + + + + + diff --git a/toolchains/arduino/org.eclipse.cdt.arduino.core/src/org/eclipse/cdt/arduino/core/internal/Activator.java b/toolchains/arduino/org.eclipse.cdt.arduino.core/src/org/eclipse/cdt/arduino/core/internal/Activator.java index 342e8b451cc..e34ed5e625d 100644 --- a/toolchains/arduino/org.eclipse.cdt.arduino.core/src/org/eclipse/cdt/arduino/core/internal/Activator.java +++ b/toolchains/arduino/org.eclipse.cdt.arduino.core/src/org/eclipse/cdt/arduino/core/internal/Activator.java @@ -11,12 +11,8 @@ package org.eclipse.cdt.arduino.core.internal; import org.eclipse.cdt.arduino.core.internal.board.ArduinoManager; -import org.eclipse.cdt.arduino.core.internal.console.ArduinoConsoleService; import org.eclipse.core.runtime.CoreException; -import org.eclipse.core.runtime.IExtension; -import org.eclipse.core.runtime.IExtensionPoint; import org.eclipse.core.runtime.IStatus; -import org.eclipse.core.runtime.Platform; import org.eclipse.core.runtime.Plugin; import org.eclipse.core.runtime.Status; import org.osgi.framework.BundleContext; @@ -46,11 +42,13 @@ public class Activator extends Plugin { } } + @Override public void start(BundleContext bundleContext) throws Exception { plugin = this; bundleContext.registerService(ArduinoManager.class, new ArduinoManager(), null); } + @Override public void stop(BundleContext bundleContext) throws Exception { plugin = null; } @@ -61,10 +59,4 @@ public class Activator extends Plugin { return ref != null ? context.getService(ref) : null; } - public static ArduinoConsoleService getConsoleService() throws CoreException { - IExtensionPoint point = Platform.getExtensionRegistry().getExtensionPoint(Activator.getId(), "consoleService"); //$NON-NLS-1$ - IExtension extension = point.getExtensions()[0]; // should only be one - return (ArduinoConsoleService) extension.getConfigurationElements()[0].createExecutableExtension("class"); //$NON-NLS-1$ - } - } diff --git a/toolchains/arduino/org.eclipse.cdt.arduino.core/src/org/eclipse/cdt/arduino/core/internal/ArduinoProjectGenerator.java b/toolchains/arduino/org.eclipse.cdt.arduino.core/src/org/eclipse/cdt/arduino/core/internal/ArduinoProjectGenerator.java index b54bf1c024a..a5f2218d3ea 100644 --- a/toolchains/arduino/org.eclipse.cdt.arduino.core/src/org/eclipse/cdt/arduino/core/internal/ArduinoProjectGenerator.java +++ b/toolchains/arduino/org.eclipse.cdt.arduino.core/src/org/eclipse/cdt/arduino/core/internal/ArduinoProjectGenerator.java @@ -1,73 +1,54 @@ /******************************************************************************* - * Copyright (c) 2015 QNX Software Systems and others. + * Copyright (c) 2015, 2016 QNX Software Systems and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html - * - * Contributors: - * QNX Software Systems - Initial API and implementation *******************************************************************************/ package org.eclipse.cdt.arduino.core.internal; -import java.util.HashMap; import java.util.Map; -import org.eclipse.cdt.arduino.core.internal.build.ArduinoBuilder; import org.eclipse.cdt.core.CCProjectNature; import org.eclipse.cdt.core.CProjectNature; +import org.eclipse.cdt.core.build.CBuilder; import org.eclipse.cdt.core.model.CoreModel; import org.eclipse.cdt.core.model.IPathEntry; import org.eclipse.core.resources.ICommand; -import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IProjectDescription; -import org.eclipse.core.resources.IncrementalProjectBuilder; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.tools.templates.freemarker.FMProjectGenerator; +import org.osgi.framework.Bundle; -public class ArduinoProjectGenerator { +public class ArduinoProjectGenerator extends FMProjectGenerator { - private final IProject project; - private IFile sourceFile; - - public ArduinoProjectGenerator(IProject project) { - this.project = project; + public ArduinoProjectGenerator(String manifestFile) { + super(manifestFile); + } + + @Override + protected void initProjectDescription(IProjectDescription description) { + description + .setNatureIds(new String[] { CProjectNature.C_NATURE_ID, CCProjectNature.CC_NATURE_ID, ArduinoProjectNature.ID }); + ICommand command = description.newCommand(); + CBuilder.setupBuilder(command); + description.setBuildSpec(new ICommand[] { command }); } - public void generate(IProgressMonitor monitor) throws CoreException { - // Generate files - ArduinoTemplateGenerator templateGen = new ArduinoTemplateGenerator(); - Map fmModel = new HashMap<>(); - fmModel.put("projectName", project.getName()); //$NON-NLS-1$ - - sourceFile = project.getFile(project.getName() + ".cpp"); //$NON-NLS-1$ - templateGen.generateFile(fmModel, "arduino.cpp", sourceFile, monitor); //$NON-NLS-1$ - - // Add natures to project: C, C++, Arduino - IProjectDescription projDesc = project.getDescription(); - String[] oldIds = projDesc.getNatureIds(); - String[] newIds = new String[oldIds.length + 3]; - System.arraycopy(oldIds, 0, newIds, 0, oldIds.length); - newIds[newIds.length - 3] = CProjectNature.C_NATURE_ID; - newIds[newIds.length - 2] = CCProjectNature.CC_NATURE_ID; - newIds[newIds.length - 1] = ArduinoProjectNature.ID; - projDesc.setNatureIds(newIds); - - // Add Arduino Builder - ICommand command = projDesc.newCommand(); - command.setBuilderName(ArduinoBuilder.ID); - command.setBuilding(IncrementalProjectBuilder.AUTO_BUILD, false); - projDesc.setBuildSpec(new ICommand[] { command }); - - project.setDescription(projDesc, monitor); - - IPathEntry[] entries = new IPathEntry[] { CoreModel.newSourceEntry(project.getFullPath()) }; - CoreModel.getDefault().create(project).setRawPathEntries(entries, monitor); + @Override + public Bundle getSourceBundle() { + return Activator.getPlugin().getBundle(); } - - public IFile getSourceFile() { - return sourceFile; + + @Override + public void generate(Map model, IProgressMonitor monitor) throws CoreException { + super.generate(model, monitor); + IProject project = getProject(); + CoreModel.getDefault().create(project).setRawPathEntries(new IPathEntry[] { + CoreModel.newSourceEntry(project.getFullPath()) + }, monitor); } } diff --git a/toolchains/arduino/org.eclipse.cdt.arduino.core/src/org/eclipse/cdt/arduino/core/internal/ArduinoScannerInfoProvider.java b/toolchains/arduino/org.eclipse.cdt.arduino.core/src/org/eclipse/cdt/arduino/core/internal/ArduinoScannerInfoProvider.java deleted file mode 100644 index 648a20c77d0..00000000000 --- a/toolchains/arduino/org.eclipse.cdt.arduino.core/src/org/eclipse/cdt/arduino/core/internal/ArduinoScannerInfoProvider.java +++ /dev/null @@ -1,45 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2015 QNX Software Systems and others. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - *******************************************************************************/ -package org.eclipse.cdt.arduino.core.internal; - -import org.eclipse.cdt.arduino.core.internal.build.ArduinoBuildConfiguration; -import org.eclipse.cdt.core.parser.IScannerInfo; -import org.eclipse.cdt.core.parser.IScannerInfoChangeListener; -import org.eclipse.cdt.core.parser.IScannerInfoProvider; -import org.eclipse.core.resources.IBuildConfiguration; -import org.eclipse.core.resources.IProject; -import org.eclipse.core.resources.IResource; -import org.eclipse.core.runtime.CoreException; - -/** - * Responsible for collecting scanner info on Arduino Projects. - */ -public class ArduinoScannerInfoProvider implements IScannerInfoProvider { - - @Override - public IScannerInfo getScannerInformation(IResource resource) { - try { - IProject project = resource.getProject(); - IBuildConfiguration config = project.getActiveBuildConfig(); - ArduinoBuildConfiguration arduinoConfig = config.getAdapter(ArduinoBuildConfiguration.class); - return arduinoConfig.getScannerInfo(resource); - } catch (CoreException e) { - Activator.log(e); - return null; - } - } - - @Override - public void subscribe(IResource resource, IScannerInfoChangeListener listener) { - } - - @Override - public void unsubscribe(IResource resource, IScannerInfoChangeListener listener) { - } - -} diff --git a/toolchains/arduino/org.eclipse.cdt.arduino.core/src/org/eclipse/cdt/arduino/core/internal/ArduinoTemplateGenerator.java b/toolchains/arduino/org.eclipse.cdt.arduino.core/src/org/eclipse/cdt/arduino/core/internal/ArduinoTemplateGenerator.java deleted file mode 100644 index 3725e794f67..00000000000 --- a/toolchains/arduino/org.eclipse.cdt.arduino.core/src/org/eclipse/cdt/arduino/core/internal/ArduinoTemplateGenerator.java +++ /dev/null @@ -1,95 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2015 QNX Software Systems and others. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - *******************************************************************************/ -package org.eclipse.cdt.arduino.core.internal; - -import java.io.ByteArrayInputStream; -import java.io.File; -import java.io.IOException; -import java.io.InputStreamReader; -import java.io.Reader; -import java.io.StringWriter; -import java.net.URISyntaxException; -import java.net.URL; -import java.nio.charset.StandardCharsets; - -import org.eclipse.core.resources.IFile; -import org.eclipse.core.runtime.CoreException; -import org.eclipse.core.runtime.FileLocator; -import org.eclipse.core.runtime.IProgressMonitor; -import org.eclipse.core.runtime.IStatus; -import org.eclipse.core.runtime.Path; -import org.eclipse.core.runtime.Status; - -import freemarker.cache.TemplateLoader; -import freemarker.template.Configuration; -import freemarker.template.Template; -import freemarker.template.TemplateException; - -public class ArduinoTemplateGenerator implements TemplateLoader { - - private final Configuration config; - private Path templateRoot = new Path("/templates"); //$NON-NLS-1$ - - public ArduinoTemplateGenerator() throws CoreException { - config = new Configuration(Configuration.VERSION_2_3_22); - config.setTemplateLoader(this); - } - - public void generateFile(final Object model, String templateFile, final IFile outputFile, IProgressMonitor monitor) - throws CoreException { - try { - final Template template = config.getTemplate(templateFile); - try (StringWriter writer = new StringWriter()) { - template.process(model, writer); - try (ByteArrayInputStream in = new ByteArrayInputStream( - writer.getBuffer().toString().getBytes(StandardCharsets.UTF_8))) { - if (outputFile.exists()) { - outputFile.setContents(in, true, true, monitor); - } else { - outputFile.create(in, true, monitor); - } - } - } - } catch (IOException | TemplateException e) { - throw new CoreException( - new Status(IStatus.ERROR, Activator.getId(), "Processing template " + templateFile, e)); //$NON-NLS-1$ - } - } - - @Override - public Object findTemplateSource(String name) throws IOException { - return FileLocator.find(Activator.getContext().getBundle(), templateRoot.append(name), null); - } - - @Override - public long getLastModified(Object source) { - try { - URL url = (URL) source; - if (url.getProtocol().equals("file")) { //$NON-NLS-1$ - File file = new File(url.toURI()); - return file.lastModified(); - } else { - return 0; - } - } catch (URISyntaxException e) { - return 0; - } - } - - @Override - public Reader getReader(Object source, String encoding) throws IOException { - URL url = (URL) source; - return new InputStreamReader(url.openStream()); - } - - @Override - public void closeTemplateSource(Object arg0) throws IOException { - // Nothing to do - } - -} diff --git a/toolchains/arduino/org.eclipse.cdt.arduino.core/src/org/eclipse/cdt/arduino/core/internal/board/ArduinoManager.java b/toolchains/arduino/org.eclipse.cdt.arduino.core/src/org/eclipse/cdt/arduino/core/internal/board/ArduinoManager.java index 5fe77c47982..64eb2b07231 100644 --- a/toolchains/arduino/org.eclipse.cdt.arduino.core/src/org/eclipse/cdt/arduino/core/internal/board/ArduinoManager.java +++ b/toolchains/arduino/org.eclipse.cdt.arduino.core/src/org/eclipse/cdt/arduino/core/internal/board/ArduinoManager.java @@ -45,7 +45,7 @@ import org.eclipse.cdt.arduino.core.internal.Activator; import org.eclipse.cdt.arduino.core.internal.ArduinoPreferences; import org.eclipse.cdt.arduino.core.internal.Messages; import org.eclipse.cdt.arduino.core.internal.build.ArduinoBuildConfiguration; -import org.eclipse.core.resources.IBuildConfiguration; +import org.eclipse.cdt.core.build.ICBuildConfiguration; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.ProjectScope; import org.eclipse.core.runtime.CoreException; @@ -76,6 +76,7 @@ public class ArduinoManager { public void loadIndices() { new Job(Messages.ArduinoBoardManager_0) { + @Override protected IStatus run(IProgressMonitor monitor) { synchronized (ArduinoManager.this) { String[] boardUrls = ArduinoPreferences.getBoardUrls().split("\n"); //$NON-NLS-1$ @@ -207,7 +208,7 @@ public class ArduinoManager { private static final String LIBRARIES = "libraries"; //$NON-NLS-1$ private IEclipsePreferences getSettings(IProject project) { - return (IEclipsePreferences) new ProjectScope(project).getNode(Activator.getId()); + return new ProjectScope(project).getNode(Activator.getId()); } public Collection getLibraries(IProject project) throws CoreException { @@ -218,8 +219,8 @@ public class ArduinoManager { Set libraryNames = new Gson().fromJson(librarySetting, stringSet); LibraryIndex index = Activator.getService(ArduinoManager.class).getLibraryIndex(); - ArduinoPlatform platform = project.getActiveBuildConfig().getAdapter(ArduinoBuildConfiguration.class).getBoard() - .getPlatform(); + ICBuildConfiguration cconfig = project.getActiveBuildConfig().getAdapter(ICBuildConfiguration.class); + ArduinoPlatform platform = cconfig.getAdapter(ArduinoBuildConfiguration.class).getBoard().getPlatform(); List libraries = new ArrayList<>(libraryNames.size()); for (String name : libraryNames) { ArduinoLibrary lib = index.getLibrary(name); @@ -247,6 +248,7 @@ public class ArduinoManager { } new Job(Messages.ArduinoManager_0) { + @Override protected IStatus run(IProgressMonitor monitor) { MultiStatus mstatus = new MultiStatus(Activator.getId(), 0, Messages.ArduinoManager_1, null); for (ArduinoLibrary library : libraries) { @@ -255,16 +257,6 @@ public class ArduinoManager { mstatus.add(status); } } - - // Clear the scanner info caches to pick up new includes - try { - for (IBuildConfiguration config : project.getBuildConfigs()) { - ArduinoBuildConfiguration arduinoConfig = config.getAdapter(ArduinoBuildConfiguration.class); - arduinoConfig.clearScannerInfoCache(); - } - } catch (CoreException e) { - mstatus.add(e.getStatus()); - } return mstatus; } }.schedule(); diff --git a/toolchains/arduino/org.eclipse.cdt.arduino.core/src/org/eclipse/cdt/arduino/core/internal/build/ArduinoBuildConfiguration.java b/toolchains/arduino/org.eclipse.cdt.arduino.core/src/org/eclipse/cdt/arduino/core/internal/build/ArduinoBuildConfiguration.java index 0fb96aa25a9..c0ee4bcb215 100644 --- a/toolchains/arduino/org.eclipse.cdt.arduino.core/src/org/eclipse/cdt/arduino/core/internal/build/ArduinoBuildConfiguration.java +++ b/toolchains/arduino/org.eclipse.cdt.arduino.core/src/org/eclipse/cdt/arduino/core/internal/build/ArduinoBuildConfiguration.java @@ -8,25 +8,30 @@ package org.eclipse.cdt.arduino.core.internal.build; import java.io.BufferedReader; +import java.io.ByteArrayInputStream; import java.io.File; import java.io.IOException; import java.io.InputStreamReader; -import java.nio.file.Files; +import java.io.Reader; +import java.io.StringWriter; +import java.net.URISyntaxException; +import java.net.URL; +import java.nio.charset.StandardCharsets; import java.nio.file.Path; +import java.nio.file.Paths; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collection; import java.util.HashMap; -import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Properties; -import java.util.Set; import java.util.regex.Matcher; import java.util.regex.Pattern; +import java.util.stream.Collectors; import org.eclipse.cdt.arduino.core.internal.Activator; import org.eclipse.cdt.arduino.core.internal.ArduinoPreferences; -import org.eclipse.cdt.arduino.core.internal.ArduinoTemplateGenerator; import org.eclipse.cdt.arduino.core.internal.HierarchicalProperties; import org.eclipse.cdt.arduino.core.internal.board.ArduinoBoard; import org.eclipse.cdt.arduino.core.internal.board.ArduinoLibrary; @@ -34,152 +39,107 @@ import org.eclipse.cdt.arduino.core.internal.board.ArduinoManager; import org.eclipse.cdt.arduino.core.internal.board.ArduinoPackage; import org.eclipse.cdt.arduino.core.internal.board.ArduinoPlatform; import org.eclipse.cdt.arduino.core.internal.board.ToolDependency; -import org.eclipse.cdt.arduino.core.internal.console.ArduinoConsoleParser; -import org.eclipse.cdt.arduino.core.internal.console.ArduinoErrorParser; import org.eclipse.cdt.arduino.core.internal.remote.ArduinoRemoteConnection; import org.eclipse.cdt.core.CCorePlugin; -import org.eclipse.cdt.core.model.CoreModel; -import org.eclipse.cdt.core.model.ICProject; -import org.eclipse.cdt.core.model.IOutputEntry; -import org.eclipse.cdt.core.model.IPathEntry; +import org.eclipse.cdt.core.ConsoleOutputStream; +import org.eclipse.cdt.core.ErrorParserManager; +import org.eclipse.cdt.core.IConsoleParser; +import org.eclipse.cdt.core.build.CBuildConfiguration; +import org.eclipse.cdt.core.build.IToolChain; +import org.eclipse.cdt.core.build.IToolChainManager; +import org.eclipse.cdt.core.build.IToolChainProvider; +import org.eclipse.cdt.core.model.ICModelMarker; import org.eclipse.cdt.core.model.ISourceRoot; import org.eclipse.cdt.core.parser.ExtendedScannerInfo; import org.eclipse.cdt.core.parser.IScannerInfo; +import org.eclipse.cdt.core.resources.IConsole; import org.eclipse.core.resources.IBuildConfiguration; +import org.eclipse.core.resources.IContainer; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IFolder; -import org.eclipse.core.resources.IMarker; import org.eclipse.core.resources.IProject; -import org.eclipse.core.resources.IProjectDescription; import org.eclipse.core.resources.IResource; import org.eclipse.core.resources.IResourceProxy; import org.eclipse.core.resources.IResourceProxyVisitor; -import org.eclipse.core.resources.ProjectScope; import org.eclipse.core.runtime.CoreException; -import org.eclipse.core.runtime.IAdapterFactory; +import org.eclipse.core.runtime.FileLocator; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Platform; import org.eclipse.core.runtime.Status; import org.eclipse.core.runtime.content.IContentType; -import org.eclipse.core.runtime.preferences.IEclipsePreferences; import org.osgi.service.prefs.BackingStoreException; +import org.osgi.service.prefs.Preferences; -public class ArduinoBuildConfiguration { +import freemarker.cache.TemplateLoader; +import freemarker.template.Configuration; +import freemarker.template.Template; +import freemarker.template.TemplateException; + +public class ArduinoBuildConfiguration extends CBuildConfiguration implements TemplateLoader { private static final String PACKAGE_NAME = "packageName"; //$NON-NLS-1$ private static final String PLATFORM_NAME = "platformName"; //$NON-NLS-1$ private static final String BOARD_NAME = "boardName"; //$NON-NLS-1$ - private final IBuildConfiguration config; - private static ArduinoManager manager = Activator.getService(ArduinoManager.class); - private ArduinoBoard board; + private final ArduinoBoard board; + private final String launchMode; private Properties properties; - // Cache for scanner info - private IScannerInfo cScannerInfo; - private IScannerInfo cppScannerInfo; + // for Makefile generation + private Configuration templateConfig; private final static boolean isWindows = Platform.getOS().equals(Platform.OS_WIN32); - private ArduinoBuildConfiguration(IBuildConfiguration config) { - this.config = config; - } + public ArduinoBuildConfiguration(IBuildConfiguration config, String name) throws CoreException { + super(config, name); - private static Map cache = new HashMap<>(); + Preferences settings = getSettings(); + String packageName = settings.get(PACKAGE_NAME, ""); //$NON-NLS-1$ + String platformName = settings.get(PLATFORM_NAME, ""); //$NON-NLS-1$ + String boardName = settings.get(BOARD_NAME, ""); //$NON-NLS-1$ + ArduinoBoard b = manager.getBoard(boardName, platformName, packageName); - public static class Factory implements IAdapterFactory { - @SuppressWarnings("unchecked") - @Override - public T getAdapter(Object adaptableObject, Class adapterType) { - if (adapterType.equals(ArduinoBuildConfiguration.class) && adaptableObject instanceof IBuildConfiguration) { - IBuildConfiguration config = (IBuildConfiguration) adaptableObject; - ArduinoBuildConfiguration arduinoConfig = cache.get(config); - if (arduinoConfig == null) { - arduinoConfig = new ArduinoBuildConfiguration(config); - cache.put(config, arduinoConfig); - } - return (T) arduinoConfig; - } - return null; - } - - @Override - public Class[] getAdapterList() { - return new Class[] { ArduinoBuildConfiguration.class }; - } - } - - public static ArduinoBuildConfiguration getConfig(IProject project, ArduinoRemoteConnection target, - IProgressMonitor monitor) throws CoreException { - ArduinoBoard board = target.getBoard(); - - // return it if it exists already - for (IBuildConfiguration config : project.getBuildConfigs()) { - if (!config.getName().equals(IBuildConfiguration.DEFAULT_CONFIG_NAME)) { - ArduinoBuildConfiguration arduinoConfig = config.getAdapter(ArduinoBuildConfiguration.class); - if (arduinoConfig.matches(target)) { - return arduinoConfig; + if (b == null) { + // Default to Uno or first one we find + b = manager.getBoard("Arduino/Genuino Uno", "Arduino AVR Boards", "arduino"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ + if (b == null) { + List boards = manager.getInstalledBoards(); + if (!boards.isEmpty()) { + b = boards.get(0); } } } + board = b; - // Not found, need to create one - Set configNames = new HashSet<>(); - for (IBuildConfiguration config : project.getBuildConfigs()) { - configNames.add(config.getName()); - } - String newName = board.getId(); - int n = 0; - while (configNames.contains(newName)) { - newName = board.getId() + (++n); - } - configNames.add(newName); - IProjectDescription projectDesc = project.getDescription(); - projectDesc.setBuildConfigs(configNames.toArray(new String[configNames.size()])); - project.setDescription(projectDesc, monitor); - - // set it up for the board - IBuildConfiguration config = project.getBuildConfig(newName); - ArduinoBuildConfiguration arduinoConfig = config.getAdapter(ArduinoBuildConfiguration.class); - arduinoConfig.setBoard(target); - - return arduinoConfig; + int i = name.lastIndexOf('.'); + this.launchMode = name.substring(i + 1); } - public void setActive(IProgressMonitor monitor) throws CoreException { - IProject project = config.getProject(); - if (config.equals(project.getActiveBuildConfig())) { - // already set - return; - } - - IProjectDescription projectDesc = project.getDescription(); - projectDesc.setActiveBuildConfig(config.getName()); - project.setDescription(projectDesc, monitor); - - // Reindex - assuming for now each config has different compiler - // settings - CCorePlugin.getIndexManager().reindex(CoreModel.getDefault().create(project)); - } - - public IEclipsePreferences getSettings() { - return (IEclipsePreferences) new ProjectScope(config.getProject()).getNode(Activator.getId()).node("config") //$NON-NLS-1$ - .node(config.getName()); - } - - public void setBoard(ArduinoBoard board) throws CoreException { + ArduinoBuildConfiguration(IBuildConfiguration config, String name, ArduinoBoard board, String launchMode) + throws CoreException { + super(config, name); this.board = board; + this.launchMode = launchMode; + // Create the toolChain + IToolChainManager toolChainManager = Activator.getService(IToolChainManager.class); + IToolChainProvider provider = toolChainManager.getProvider(ArduinoToolChainProvider.ID); + IToolChain toolChain = new ArduinoToolChain(provider, this); + toolChainManager.addToolChain(toolChain); + setToolChain(toolChain); + + // Store the board identifer ArduinoPlatform platform = board.getPlatform(); ArduinoPackage pkg = platform.getPackage(); - IEclipsePreferences settings = getSettings(); + Preferences settings = getSettings(); settings.put(PACKAGE_NAME, pkg.getName()); settings.put(PLATFORM_NAME, platform.getName()); settings.put(BOARD_NAME, board.getName()); + try { settings.flush(); } catch (BackingStoreException e) { @@ -187,19 +147,14 @@ public class ArduinoBuildConfiguration { } } - public void setBoard(ArduinoRemoteConnection target) throws CoreException { - this.board = target.getBoard(); - - ArduinoPlatform platform = board.getPlatform(); - ArduinoPackage pkg = platform.getPackage(); - - IEclipsePreferences settings = getSettings(); - settings.put(PACKAGE_NAME, pkg.getName()); - settings.put(PLATFORM_NAME, platform.getName()); - settings.put(BOARD_NAME, board.getName()); + ArduinoBuildConfiguration(IBuildConfiguration config, String name, ArduinoRemoteConnection target, + String launchMode) throws CoreException { + this(config, name, target.getBoard(), launchMode); + // Store the menu settings HierarchicalProperties menus = board.getMenus(); if (menus != null) { + Preferences settings = getSettings(); for (String id : menus.getChildren().keySet()) { String key = ArduinoBoard.MENU_QUALIFIER + id; String value = target.getRemoteConnection().getAttribute(key); @@ -207,22 +162,39 @@ public class ArduinoBuildConfiguration { settings.put(key, value); } } - } - try { - settings.flush(); - } catch (BackingStoreException e) { - throw new CoreException(new Status(IStatus.ERROR, Activator.getId(), "Saving preferences", e)); //$NON-NLS-1$ + try { + settings.flush(); + } catch (BackingStoreException e) { + throw new CoreException(new Status(IStatus.ERROR, Activator.getId(), "Saving preferences", e)); //$NON-NLS-1$ + } } } + static String generateName(ArduinoBoard board, String launchMode) { + return "arduino." + board.getId() + '.' + launchMode; //$NON-NLS-1$ + } + + @SuppressWarnings("unchecked") + @Override + public T getAdapter(Class adapter) { + if (adapter.equals(ArduinoBuildConfiguration.class)) { + return (T) this; + } + return super.getAdapter(adapter); + } + + public String getLaunchMode() { + return launchMode; + } + public boolean matches(ArduinoRemoteConnection target) throws CoreException { ArduinoBoard otherBoard = target.getBoard(); if (!getBoard().equals(otherBoard)) { return false; } - IEclipsePreferences settings = getSettings(); + Preferences settings = getSettings(); HierarchicalProperties menus = board.getMenus(); if (menus != null) { for (String id : menus.getChildren().keySet()) { @@ -237,24 +209,6 @@ public class ArduinoBuildConfiguration { } public ArduinoBoard getBoard() throws CoreException { - if (board == null) { - IEclipsePreferences settings = getSettings(); - String packageName = settings.get(PACKAGE_NAME, ""); //$NON-NLS-1$ - String platformName = settings.get(PLATFORM_NAME, ""); //$NON-NLS-1$ - String boardName = settings.get(BOARD_NAME, ""); //$NON-NLS-1$ - board = manager.getBoard(boardName, platformName, packageName); - - if (board == null) { - // Default to Uno or first one we find - board = manager.getBoard("Arduino/Genuino Uno", "Arduino AVR Boards", "arduino"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ - if (board == null) { - List boards = manager.getInstalledBoards(); - if (!boards.isEmpty()) { - board = boards.get(0); - } - } - } - } return board; } @@ -268,7 +222,7 @@ public class ArduinoBuildConfiguration { properties.put("runtime.ide.version", "10607"); //$NON-NLS-1$ //$NON-NLS-2$ properties.put("software", "ARDUINO"); //$NON-NLS-1$ //$NON-NLS-2$ properties.put("build.arch", platform.getArchitecture().toUpperCase()); //$NON-NLS-1$ - String configName = config.getName(); + String configName = getBuildConfiguration().getName(); if (configName.equals(IBuildConfiguration.DEFAULT_CONFIG_NAME)) { configName = "default"; //$NON-NLS-1$ } @@ -289,7 +243,7 @@ public class ArduinoBuildConfiguration { properties.putAll(board.getBoardProperties()); // Menus - IEclipsePreferences settings = getSettings(); + Preferences settings = getSettings(); HierarchicalProperties menus = board.getMenus(); if (menus != null) { for (String menuId : menus.getChildren().keySet()) { @@ -302,48 +256,22 @@ public class ArduinoBuildConfiguration { } // always do this in case the project changes names - properties.put("build.project_name", config.getProject().getName()); //$NON-NLS-1$ + properties.put("build.project_name", getProject().getName()); //$NON-NLS-1$ return properties; } - public IFolder getBuildFolder() throws CoreException { - IProject project = config.getProject(); - return project.getFolder("build"); //$NON-NLS-1$ - } - - public File getBuildDirectory() throws CoreException { - return new File(getBuildFolder().getLocationURI()); - } - public IFile getMakeFile() throws CoreException { - IFolder buildFolder = getBuildFolder(); + IFolder buildFolder = (IFolder) getBuildContainer(); ArduinoBoard board = getBoard(); String makeFileName = board.getId() + ".mk"; //$NON-NLS-1$ return buildFolder.getFile(makeFileName); } - public IFile generateMakeFile(IProgressMonitor monitor) throws CoreException { - final IProject project = config.getProject(); - - IFolder buildFolder = getBuildFolder(); - if (!buildFolder.exists()) { - buildFolder.create(true, true, monitor); - buildFolder.setDerived(true, monitor); - ICProject cproject = CoreModel.getDefault().create(project); - IOutputEntry output = CoreModel.newOutputEntry(buildFolder.getFullPath()); - IPathEntry[] oldEntries = cproject.getRawPathEntries(); - IPathEntry[] newEntries = new IPathEntry[oldEntries.length + 1]; - System.arraycopy(oldEntries, 0, newEntries, 0, oldEntries.length); - newEntries[oldEntries.length] = output; - cproject.setRawPathEntries(newEntries, monitor); - } - + public Map getBuildModel() throws CoreException { + IProject project = getProject(); ArduinoBoard board = getBoard(); ArduinoPlatform platform = board.getPlatform(); - IFile makeFile = getMakeFile(); - - // The board id Map buildModel = new HashMap<>(); buildModel.put("boardId", board.getId()); //$NON-NLS-1$ @@ -417,9 +345,56 @@ public class ArduinoBuildConfiguration { buildModel.put("recipe_objcopy_bin_pattern", resolveProperty("recipe.objcopy.bin.pattern", properties)); //$NON-NLS-1$ //$NON-NLS-2$ buildModel.put("recipe_size_pattern", resolveProperty("recipe.size.pattern", properties)); //$NON-NLS-1$ //$NON-NLS-2$ - ArduinoTemplateGenerator templateGen = new ArduinoTemplateGenerator(); - templateGen.generateFile(buildModel, "board.mk", makeFile, monitor); //$NON-NLS-1$ - return makeFile; + return buildModel; + } + + public IFile generateMakeFile(IProgressMonitor monitor) throws CoreException { + IFolder buildFolder = (IFolder) getBuildContainer(); + if (!buildFolder.exists()) { + buildFolder.create(true, true, monitor); + } + + IFile makefile = getMakeFile(); + + Map buildModel = getBuildModel(); + + // Generate the Makefile + try (StringWriter writer = new StringWriter()) { + if (templateConfig == null) { + templateConfig = new Configuration(Configuration.VERSION_2_3_22); + templateConfig.setTemplateLoader(this); + } + + Template template = templateConfig.getTemplate("templates/Makefile"); //$NON-NLS-1$ + template.process(buildModel, writer); + try (ByteArrayInputStream in = new ByteArrayInputStream( + writer.getBuffer().toString().getBytes(StandardCharsets.UTF_8))) { + createParent(makefile, monitor); + if (makefile.exists()) { + makefile.setContents(in, true, true, monitor); + } else { + makefile.create(in, true, monitor); + } + } + } catch (IOException | TemplateException e) { + throw new CoreException(new Status(IStatus.ERROR, Activator.getId(), "Error generating makefile", e)); + } + + return makefile; + } + + protected static void createParent(IResource child, IProgressMonitor monitor) throws CoreException { + if (child == null) + return; + + IContainer container = child.getParent(); + if (container.exists()) { + return; + } + + IFolder parent = container.getAdapter(IFolder.class); + createParent(parent, monitor); + parent.create(true, true, monitor); } public static boolean isSource(String filename) { @@ -435,35 +410,30 @@ public class ArduinoBuildConfiguration { } } - private String resolveProperty(String property, Properties dict) { - String res = dict.getProperty(property); - if (res == null) { - return null; - } - + private String resolvePropertyValue(String value, Properties dict) { String last; do { - last = res; - for (int i = res.indexOf('{'); i >= 0; i = res.indexOf('{', i)) { + last = value; + for (int i = value.indexOf('{'); i >= 0; i = value.indexOf('{', i)) { i++; - int n = res.indexOf('}', i); + int n = value.indexOf('}', i); if (n >= 0) { - String p2 = res.substring(i, n); + String p2 = value.substring(i, n); String r2 = dict.getProperty(p2); if (r2 != null) { - res = res.replace('{' + p2 + '}', r2); + value = value.replace('{' + p2 + '}', r2); } } i = n; } - } while (!res.equals(last)); + } while (!value.equals(last)); - return res; + return value; } - public void setEnvironment(Map env) throws CoreException { - // Everything is specified with full path, do not need to add anything - // to the environment. + private String resolveProperty(String property, Properties dict) { + String value = dict.getProperty(property); + return value != null ? resolvePropertyValue(value, dict) : null; } public String getMakeCommand() { @@ -546,31 +516,75 @@ public class ArduinoBuildConfiguration { } } - public IScannerInfo getScannerInfo(IResource resource) throws CoreException { - IContentType contentType = CCorePlugin.getContentType(resource.getProject(), resource.getName()); - if (contentType != null) { - // what language is this resource and pick the right path; - switch (contentType.getId()) { - case CCorePlugin.CONTENT_TYPE_CXXSOURCE: - case CCorePlugin.CONTENT_TYPE_CXXHEADER: - if (cppScannerInfo == null) { - cppScannerInfo = calculateScannerInfo("recipe.cpp.o.pattern", resource); //$NON-NLS-1$ - } - return cppScannerInfo; - default: - if (cScannerInfo == null) { - cScannerInfo = calculateScannerInfo("recipe.c.o.pattern", resource); //$NON-NLS-1$ - } - return cScannerInfo; - } - } - // use the cpp scanner info if all else fails - return cppScannerInfo; - } + // Scanner Info Cache + private String[] cachedIncludePath; + private String cachedInfoCommand; + private IScannerInfo cachedScannerInfo; - public void clearScannerInfoCache() { - cppScannerInfo = null; - cScannerInfo = null; + @Override + public IScannerInfo getScannerInformation(IResource resource) { + try { + IContentType contentType = CCorePlugin.getContentType(resource.getProject(), resource.getName()); + String recipe; + if (contentType != null && (contentType.getId() == CCorePlugin.CONTENT_TYPE_CSOURCE + || contentType.getId() == CCorePlugin.CONTENT_TYPE_CSOURCE)) { + recipe = "recipe.c.o.pattern"; //$NON-NLS-1$ + } else { + recipe = "recipe.cpp.o.pattern"; //$NON-NLS-1$ + } + + ArduinoPlatform platform = getBoard().getPlatform(); + Properties properties = new Properties(); + properties.putAll(getProperties()); + + // Overrides for scanner discovery + properties.put("source_file", ""); //$NON-NLS-1$ //$NON-NLS-2$ + properties.put("object_file", "-"); //$NON-NLS-1$ //$NON-NLS-2$ + // the base scanner info does includes + properties.put("includes", ""); //$NON-NLS-1$ //$NON-NLS-2$ + String commandString = resolveProperty(recipe, properties); + + List includePath = new ArrayList<>(); + includePath.addAll(platform.getIncludePath()); + Collection libs = manager.getLibraries(getProject()); + for (ArduinoLibrary lib : libs) { + includePath.addAll(lib.getIncludePath()); + } + String[] includes = includePath.stream() + .map(path -> resolvePropertyValue(path.toString(), properties)).collect(Collectors.toList()) + .toArray(new String[includePath.size()]); + + // Use cache if we can + if (cachedScannerInfo != null && cachedInfoCommand.equals(commandString) + && cachedIncludePath.length == includes.length) { + boolean matches = true; + for (int i = 0; i < includes.length; ++i) { + if (!includes[i].equals(cachedIncludePath[i])) { + matches = false; + break; + } + } + + if (matches) { + return cachedScannerInfo; + } + } + + ExtendedScannerInfo baseInfo = new ExtendedScannerInfo(null, includes); + String[] command = splitCommand(commandString); + IScannerInfo info = getToolChain().getScannerInfo(getBuildConfiguration(), Paths.get(command[0]), + Arrays.copyOfRange(command, 1, command.length), baseInfo, resource, getBuildDirectoryURI()); + + // cache the results + cachedScannerInfo = info; + cachedInfoCommand = commandString; + cachedIncludePath = includes; + + return info; + } catch (CoreException e) { + Activator.log(e); + return null; + } } public static String pathString(Path path) { @@ -581,109 +595,151 @@ public class ArduinoBuildConfiguration { return str; } - private IScannerInfo calculateScannerInfo(String recipe, IResource resource) throws CoreException { - try { - ArduinoPlatform platform = getBoard().getPlatform(); - Properties properties = new Properties(); - properties.putAll(getProperties()); - - Path tmpFile = Files.createTempFile("cdt", ".cpp"); //$NON-NLS-1$ //$NON-NLS-2$ - properties.put("source_file", pathString(tmpFile)); //$NON-NLS-1$ - properties.put("object_file", "-"); //$NON-NLS-1$ //$NON-NLS-2$ - - String includes = "-E -P -v -dD"; //$NON-NLS-1$ - for (Path include : platform.getIncludePath()) { - includes += " -I\"" + pathString(include) + '"'; //$NON-NLS-1$ - } - Collection libs = manager.getLibraries(config.getProject()); - for (ArduinoLibrary lib : libs) { - for (Path path : lib.getIncludePath()) { - includes += " -I\"" + pathString(path) + '"'; //$NON-NLS-1$ - } - } - properties.put("includes", includes); //$NON-NLS-1$ - - String[] command; - if (isWindows) { - command = splitCommand(resolveProperty(recipe, properties)); - } else { - command = new String[] { "sh", "-c", resolveProperty(recipe, properties) }; //$NON-NLS-1$ //$NON-NLS-2$ - } - ProcessBuilder processBuilder = new ProcessBuilder(command).directory(tmpFile.getParent().toFile()) - .redirectErrorStream(true); - setEnvironment(processBuilder.environment()); - Process process = processBuilder.start(); - - Map symbols = new HashMap<>(); - List includePath = new ArrayList<>(); - Pattern definePattern = Pattern.compile("#define (.*)\\s(.*)"); //$NON-NLS-1$ - boolean inIncludePaths = false; - try (BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()))) { - for (String line = reader.readLine(); line != null; line = reader.readLine()) { - if (inIncludePaths) { - if (line.equals("End of search list.")) { //$NON-NLS-1$ - inIncludePaths = false; - } else { - includePath.add(line.trim()); - } - } else if (line.startsWith("#define ")) { //$NON-NLS-1$ - Matcher matcher = definePattern.matcher(line); - if (matcher.matches()) { - symbols.put(matcher.group(1), matcher.group(2)); - } - } else if (line.equals("#include <...> search starts here:")) { //$NON-NLS-1$ - inIncludePaths = true; - } - } - } - Files.delete(tmpFile); - ExtendedScannerInfo scannerInfo = new ExtendedScannerInfo(symbols, - includePath.toArray(new String[includePath.size()])); - return scannerInfo; - } catch (IOException e) { - throw new CoreException(new Status(IStatus.ERROR, Activator.getId(), "Compiler built-ins", e)); //$NON-NLS-1$ - } - } - private String[] splitCommand(String command) { // TODO deal with quotes properly, for now just strip return command.replaceAll("\"", "").split("\\s+"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ } - public ArduinoConsoleParser[] getBuildConsoleParsers() { - // ../src/Test.cpp:4:1: error: 'x' was not declared in this scope + @Override + public IProject[] build(int kind, Map args, IConsole console, IProgressMonitor monitor) + throws CoreException { + IProject project = getProject(); + try { + project.deleteMarkers(ICModelMarker.C_MODEL_PROBLEM_MARKER, true, IResource.DEPTH_INFINITE); - return new ArduinoConsoleParser[] { new ArduinoErrorParser("(.*?):(\\d+):(\\d+:)? (fatal )?error: (.*)") { //$NON-NLS-1$ - @Override - protected int getSeverity(Matcher matcher) { - return IMarker.SEVERITY_ERROR; + ConsoleOutputStream consoleOut = console.getOutputStream(); + consoleOut.write(String.format("\nBuilding %s\n", project.getName())); + + generateMakeFile(monitor); + + try (ErrorParserManager epm = new ErrorParserManager(project, getBuildDirectoryURI(), this, + getToolChain().getErrorParserIds())) { + ProcessBuilder processBuilder = new ProcessBuilder().command(getBuildCommand()) + .directory(getBuildDirectory().toFile()); + setBuildEnvironment(processBuilder.environment()); + Process process = processBuilder.start(); + if (watchProcess(process, new IConsoleParser[] { epm }, console) == 0) { + showSizes(console); + } } - @Override - protected String getMessage(Matcher matcher) { - return matcher.group(matcher.groupCount()); + getBuildContainer().refreshLocal(IResource.DEPTH_INFINITE, monitor); + } catch (IOException e) { + throw new CoreException(new Status(IStatus.ERROR, Activator.getId(), "Build error", e)); + } + + // TODO if there are references we want to watch, return them here + return new IProject[] { project }; + } + + @Override + public void clean(IConsole console, IProgressMonitor monitor) throws CoreException { + try { + IProject project = getProject(); + project.deleteMarkers(ICModelMarker.C_MODEL_PROBLEM_MARKER, true, IResource.DEPTH_INFINITE); + + ConsoleOutputStream consoleOut = console.getOutputStream(); + consoleOut.write(String.format("\nCleaning %s\n", project.getName())); + + ProcessBuilder processBuilder = new ProcessBuilder().command(getCleanCommand()) + .directory(getBuildDirectory().toFile()); + setBuildEnvironment(processBuilder.environment()); + Process process = processBuilder.start(); + + watchProcess(process, new IConsoleParser[0], console); + + getBuildContainer().refreshLocal(IResource.DEPTH_INFINITE, monitor); + } catch (IOException e) { + throw new CoreException(new Status(IStatus.ERROR, Activator.getId(), "Build error", e)); + } + } + + private void showSizes(IConsole console) throws CoreException { + try { + int codeSize = -1; + int dataSize = -1; + + String codeSizeRegex = getCodeSizeRegex(); + Pattern codeSizePattern = codeSizeRegex != null ? Pattern.compile(codeSizeRegex) : null; + String dataSizeRegex = getDataSizeRegex(); + Pattern dataSizePattern = dataSizeRegex != null ? Pattern.compile(dataSizeRegex) : null; + + if (codeSizePattern == null && dataSizePattern == null) { + return; } - @Override - protected int getLineNumber(Matcher matcher) { - return Integer.parseInt(matcher.group(2)); + int maxCodeSize = getMaxCodeSize(); + int maxDataSize = getMaxDataSize(); + + ProcessBuilder processBuilder = new ProcessBuilder().command(getSizeCommand()) + .directory(getBuildDirectory().toFile()).redirectErrorStream(true); + setBuildEnvironment(processBuilder.environment()); + Process process = processBuilder.start(); + try (BufferedReader processOut = new BufferedReader(new InputStreamReader(process.getInputStream()))) { + for (String line = processOut.readLine(); line != null; line = processOut.readLine()) { + if (codeSizePattern != null) { + Matcher matcher = codeSizePattern.matcher(line); + if (matcher.matches()) { + codeSize += Integer.parseInt(matcher.group(1)); + } + } + if (dataSizePattern != null) { + Matcher matcher = dataSizePattern.matcher(line); + if (matcher.matches()) { + dataSize += Integer.parseInt(matcher.group(1)); + } + } + } } - @Override - protected String getFileName(Matcher matcher) { - return matcher.group(1); + ConsoleOutputStream consoleOut = console.getOutputStream(); + consoleOut.write("Program store usage: " + codeSize); + if (maxCodeSize > 0) { + consoleOut.write(" of maximum " + maxCodeSize); } + consoleOut.write(" bytes\n"); - @Override - protected int getLinkOffset(Matcher matcher) { + if (maxDataSize >= 0) { + consoleOut.write("Initial RAM usage: " + dataSize); + if (maxCodeSize > 0) { + consoleOut.write(" of maximum " + maxDataSize); + } + consoleOut.write(" bytes\n"); + } + } catch (IOException e) { + throw new CoreException(new Status(IStatus.ERROR, Activator.getId(), "Checking sizes", e)); + } + } + + @Override + public Object findTemplateSource(String name) throws IOException { + return FileLocator.find(Activator.getPlugin().getBundle(), new org.eclipse.core.runtime.Path(name), null); + } + + @Override + public long getLastModified(Object source) { + try { + URL url = (URL) source; + if (url.getProtocol().equals("file")) { //$NON-NLS-1$ + File file = new File(url.toURI()); + return file.lastModified(); + } else { return 0; } + } catch (URISyntaxException e) { + return 0; + } + } - @Override - protected int getLinkLength(Matcher matcher) { - return matcher.group(1).length() + 1 + matcher.group(2).length() + 1 + matcher.group(3).length(); - } - } }; + @Override + public Reader getReader(Object source, String encoding) throws IOException { + URL url = (URL) source; + return new InputStreamReader(url.openStream(), encoding); + } + + @Override + public void closeTemplateSource(Object arg0) throws IOException { + // Nothing } } diff --git a/toolchains/arduino/org.eclipse.cdt.arduino.core/src/org/eclipse/cdt/arduino/core/internal/build/ArduinoBuildConfigurationProvider.java b/toolchains/arduino/org.eclipse.cdt.arduino.core/src/org/eclipse/cdt/arduino/core/internal/build/ArduinoBuildConfigurationProvider.java new file mode 100644 index 00000000000..3268020022e --- /dev/null +++ b/toolchains/arduino/org.eclipse.cdt.arduino.core/src/org/eclipse/cdt/arduino/core/internal/build/ArduinoBuildConfigurationProvider.java @@ -0,0 +1,105 @@ +/******************************************************************************* + * Copyright (c) 2016 QNX Software Systems and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + *******************************************************************************/ +package org.eclipse.cdt.arduino.core.internal.build; + +import java.util.List; + +import org.eclipse.cdt.arduino.core.internal.Activator; +import org.eclipse.cdt.arduino.core.internal.board.ArduinoBoard; +import org.eclipse.cdt.arduino.core.internal.board.ArduinoManager; +import org.eclipse.cdt.arduino.core.internal.remote.ArduinoRemoteConnection; +import org.eclipse.cdt.core.build.ICBuildConfiguration; +import org.eclipse.cdt.core.build.ICBuildConfigurationManager; +import org.eclipse.cdt.core.build.ICBuildConfigurationProvider; +import org.eclipse.core.resources.IBuildConfiguration; +import org.eclipse.core.resources.IProject; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IProgressMonitor; + +public class ArduinoBuildConfigurationProvider implements ICBuildConfigurationProvider { + + public static final String ID = "org.eclipse.cdt.arduino.core.provider"; //$NON-NLS-1$ + + private static final ICBuildConfigurationManager configManager = Activator + .getService(ICBuildConfigurationManager.class); + private static final ArduinoManager arduinoManager = Activator.getService(ArduinoManager.class); + + @Override + public String getId() { + return ID; + } + + @Override + public ICBuildConfiguration getCBuildConfiguration(IBuildConfiguration config, String name) throws CoreException { + return new ArduinoBuildConfiguration(config, name); + } + + @Override + public ICBuildConfiguration getDefaultCBuildConfiguration(IProject project) throws CoreException { + ArduinoBoard board = arduinoManager.getBoard("Arduino/Genuino Uno", "Arduino AVR Boards", "arduino"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ + if (board == null) { + List boards = arduinoManager.getInstalledBoards(); + if (!boards.isEmpty()) { + board = boards.get(0); + } + } + if (board != null) { + String launchMode = "run"; //$NON-NLS-1$ + for (IBuildConfiguration config : project.getBuildConfigs()) { + ICBuildConfiguration cconfig = config.getAdapter(ICBuildConfiguration.class); + if (cconfig != null) { + ArduinoBuildConfiguration arduinoConfig = cconfig.getAdapter(ArduinoBuildConfiguration.class); + if (arduinoConfig != null && arduinoConfig.getLaunchMode().equals(launchMode) + && arduinoConfig.getBoard().equals(board)) { + return arduinoConfig; + } + } + } + + // not found, create one + String configName = ArduinoBuildConfiguration.generateName(board, launchMode); + IBuildConfiguration config = configManager.createBuildConfiguration(this, project, configName, + null); + ArduinoBuildConfiguration arduinoConfig = new ArduinoBuildConfiguration(config, configName, board, + launchMode); + arduinoConfig.setActive(null); + configManager.addBuildConfiguration(config, arduinoConfig); + return arduinoConfig; + } + return null; + } + + public ArduinoBuildConfiguration getConfiguration(IProject project, ArduinoRemoteConnection target, + String launchMode, + IProgressMonitor monitor) throws CoreException { + ArduinoBoard board = target.getBoard(); + for (IBuildConfiguration config : project.getBuildConfigs()) { + ICBuildConfiguration cconfig = config.getAdapter(ICBuildConfiguration.class); + if (cconfig != null) { + ArduinoBuildConfiguration arduinoConfig = cconfig.getAdapter(ArduinoBuildConfiguration.class); + if (arduinoConfig != null && arduinoConfig.getLaunchMode().equals(launchMode) + && arduinoConfig.getBoard().equals(board) && arduinoConfig.matches(target)) { + return arduinoConfig; + } + } + } + return null; + } + + public ArduinoBuildConfiguration createConfiguration(IProject project, ArduinoRemoteConnection target, + String launchMode, + IProgressMonitor monitor) throws CoreException { + ArduinoBoard board = target.getBoard(); + String configName = ArduinoBuildConfiguration.generateName(board, launchMode); + IBuildConfiguration config = configManager.createBuildConfiguration(this, project, configName, + monitor); + ArduinoBuildConfiguration arduinoConfig = new ArduinoBuildConfiguration(config, configName, target, launchMode); + return arduinoConfig; + } + +} diff --git a/toolchains/arduino/org.eclipse.cdt.arduino.core/src/org/eclipse/cdt/arduino/core/internal/build/ArduinoBuilder.java b/toolchains/arduino/org.eclipse.cdt.arduino.core/src/org/eclipse/cdt/arduino/core/internal/build/ArduinoBuilder.java deleted file mode 100644 index 18753269114..00000000000 --- a/toolchains/arduino/org.eclipse.cdt.arduino.core/src/org/eclipse/cdt/arduino/core/internal/build/ArduinoBuilder.java +++ /dev/null @@ -1,147 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2015 QNX Software Systems and others. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - *******************************************************************************/ -package org.eclipse.cdt.arduino.core.internal.build; - -import java.io.BufferedReader; -import java.io.IOException; -import java.io.InputStreamReader; -import java.util.Map; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -import org.eclipse.cdt.arduino.core.internal.Activator; -import org.eclipse.cdt.arduino.core.internal.console.ArduinoConsoleService; -import org.eclipse.cdt.core.model.ICModelMarker; -import org.eclipse.core.resources.IProject; -import org.eclipse.core.resources.IResource; -import org.eclipse.core.resources.IncrementalProjectBuilder; -import org.eclipse.core.runtime.CoreException; -import org.eclipse.core.runtime.IProgressMonitor; -import org.eclipse.core.runtime.IStatus; -import org.eclipse.core.runtime.Status; - -/** - * This class is responsible for generating the Makefile for the current build config. - */ -public class ArduinoBuilder extends IncrementalProjectBuilder { - - public static final String ID = Activator.getId() + ".arduinoBuilder"; //$NON-NLS-1$ - - @Override - protected IProject[] build(int kind, Map args, IProgressMonitor monitor) throws CoreException { - IProject project = getProject(); - try { - project.deleteMarkers(ICModelMarker.C_MODEL_PROBLEM_MARKER, true, IResource.DEPTH_INFINITE); - - ArduinoConsoleService consoleService = Activator.getConsoleService(); - consoleService.writeOutput(String.format("\nBuilding %s\n", project.getName())); - - ArduinoBuildConfiguration config = getBuildConfig().getAdapter(ArduinoBuildConfiguration.class); - config.generateMakeFile(monitor); - - ProcessBuilder processBuilder = new ProcessBuilder().command(config.getBuildCommand()) - .directory(config.getBuildDirectory()); - config.setEnvironment(processBuilder.environment()); - Process process = processBuilder.start(); - - consoleService.monitor(process, config.getBuildConsoleParsers(), config.getBuildFolder()); - - if (process.exitValue() == 0) { - showSizes(config, consoleService); - } - - config.getBuildFolder().refreshLocal(IResource.DEPTH_INFINITE, monitor); - } catch (IOException e) { - throw new CoreException(new Status(IStatus.ERROR, Activator.getId(), "Build error", e)); - } - - // TODO if there are references we want to watch, return them here - return new IProject[] { project }; - } - - @Override - protected void clean(IProgressMonitor monitor) throws CoreException { - try { - IProject project = getProject(); - project.deleteMarkers(ICModelMarker.C_MODEL_PROBLEM_MARKER, true, IResource.DEPTH_INFINITE); - - ArduinoConsoleService consoleService = Activator.getConsoleService(); - consoleService.writeOutput(String.format("\nCleaning %s\n", project.getName())); - - ArduinoBuildConfiguration config = getBuildConfig().getAdapter(ArduinoBuildConfiguration.class); - - ProcessBuilder processBuilder = new ProcessBuilder().command(config.getCleanCommand()) - .directory(config.getBuildDirectory()); - config.setEnvironment(processBuilder.environment()); - Process process = processBuilder.start(); - - consoleService.monitor(process, config.getBuildConsoleParsers(), config.getBuildFolder()); - - config.getBuildFolder().refreshLocal(IResource.DEPTH_INFINITE, monitor); - } catch (IOException e) { - throw new CoreException(new Status(IStatus.ERROR, Activator.getId(), "Build error", e)); - } - } - - private void showSizes(ArduinoBuildConfiguration config, ArduinoConsoleService console) throws CoreException { - try { - int codeSize = -1; - int dataSize = -1; - - String codeSizeRegex = config.getCodeSizeRegex(); - Pattern codeSizePattern = codeSizeRegex != null ? Pattern.compile(codeSizeRegex) : null; - String dataSizeRegex = config.getDataSizeRegex(); - Pattern dataSizePattern = dataSizeRegex != null ? Pattern.compile(dataSizeRegex) : null; - - if (codeSizePattern == null && dataSizePattern == null) { - return; - } - - int maxCodeSize = config.getMaxCodeSize(); - int maxDataSize = config.getMaxDataSize(); - - ProcessBuilder processBuilder = new ProcessBuilder().command(config.getSizeCommand()) - .directory(config.getBuildDirectory()).redirectErrorStream(true); - config.setEnvironment(processBuilder.environment()); - Process process = processBuilder.start(); - try (BufferedReader processOut = new BufferedReader(new InputStreamReader(process.getInputStream()))) { - for (String line = processOut.readLine(); line != null; line = processOut.readLine()) { - if (codeSizePattern != null) { - Matcher matcher = codeSizePattern.matcher(line); - if (matcher.matches()) { - codeSize += Integer.parseInt(matcher.group(1)); - } - } - if (dataSizePattern != null) { - Matcher matcher = dataSizePattern.matcher(line); - if (matcher.matches()) { - dataSize += Integer.parseInt(matcher.group(1)); - } - } - } - } - - console.writeOutput("Program store usage: " + codeSize); - if (maxCodeSize > 0) { - console.writeOutput(" of maximum " + maxCodeSize); - } - console.writeOutput(" bytes\n"); - - if (maxDataSize >= 0) { - console.writeOutput("Initial RAM usage: " + dataSize); - if (maxCodeSize > 0) { - console.writeOutput(" of maximum " + maxDataSize); - } - console.writeOutput(" bytes\n"); - } - } catch (IOException e) { - throw new CoreException(new Status(IStatus.ERROR, Activator.getId(), "Checking sizes", e)); - } - } - -} diff --git a/toolchains/arduino/org.eclipse.cdt.arduino.core/src/org/eclipse/cdt/arduino/core/internal/build/ArduinoToolChain.java b/toolchains/arduino/org.eclipse.cdt.arduino.core/src/org/eclipse/cdt/arduino/core/internal/build/ArduinoToolChain.java new file mode 100644 index 00000000000..2f4fd2effef --- /dev/null +++ b/toolchains/arduino/org.eclipse.cdt.arduino.core/src/org/eclipse/cdt/arduino/core/internal/build/ArduinoToolChain.java @@ -0,0 +1,62 @@ +package org.eclipse.cdt.arduino.core.internal.build; + +import org.eclipse.cdt.arduino.core.internal.Activator; +import org.eclipse.cdt.build.gcc.core.GCCToolChain; +import org.eclipse.cdt.core.build.ICBuildConfiguration; +import org.eclipse.cdt.core.build.ICBuildConfigurationManager; +import org.eclipse.cdt.core.build.IToolChain; +import org.eclipse.cdt.core.build.IToolChainProvider; +import org.eclipse.core.resources.IBuildConfiguration; +import org.eclipse.core.resources.IProject; +import org.eclipse.core.resources.ResourcesPlugin; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Status; + +public class ArduinoToolChain extends GCCToolChain { + + private final ArduinoBuildConfiguration buildConfig; + + public ArduinoToolChain(IToolChainProvider provider, ArduinoBuildConfiguration config) { + super(provider, config.getProject().getName() + '#' + config.getName()); + this.buildConfig = config; + } + + ArduinoToolChain(IToolChainProvider provider, String name) throws CoreException { + super(provider, name); + String[] segments = name.split("#"); //$NON-NLS-1$ + if (segments.length == 2) { + String projectName = segments[0]; + String configName = segments[1]; + + IProject project = ResourcesPlugin.getWorkspace().getRoot().getProject(projectName); + if (project != null) { + ICBuildConfigurationManager configManager = Activator.getService(ICBuildConfigurationManager.class); + IBuildConfiguration config = configManager.getBuildConfiguration( + configManager.getProvider(ArduinoBuildConfigurationProvider.ID), project, configName); + ICBuildConfiguration cconfig = config.getAdapter(ICBuildConfiguration.class); + buildConfig = cconfig.getAdapter(ArduinoBuildConfiguration.class); + } else { + throw new CoreException(new Status(IStatus.ERROR, Activator.getId(), "No project")); + } + } else { + throw new CoreException(new Status(IStatus.ERROR, Activator.getId(), "Bad Name")); + } + } + + @Override + public String getProperty(String key) { + // TODO architecture if I need it + if (key.equals(IToolChain.ATTR_OS)) { + return "arduino"; //$NON-NLS-1$ + } else { + return null; + } + } + + // TODO do I really need this? + public ArduinoBuildConfiguration getBuildConfig() { + return buildConfig; + } + +} diff --git a/toolchains/arduino/org.eclipse.cdt.arduino.core/src/org/eclipse/cdt/arduino/core/internal/build/ArduinoToolChainProvider.java b/toolchains/arduino/org.eclipse.cdt.arduino.core/src/org/eclipse/cdt/arduino/core/internal/build/ArduinoToolChainProvider.java new file mode 100644 index 00000000000..79ecce03562 --- /dev/null +++ b/toolchains/arduino/org.eclipse.cdt.arduino.core/src/org/eclipse/cdt/arduino/core/internal/build/ArduinoToolChainProvider.java @@ -0,0 +1,21 @@ +package org.eclipse.cdt.arduino.core.internal.build; + +import org.eclipse.cdt.core.build.IToolChain; +import org.eclipse.cdt.core.build.IToolChainProvider; +import org.eclipse.core.runtime.CoreException; + +public class ArduinoToolChainProvider implements IToolChainProvider { + + public static final String ID = "org.eclipse.cdt.arduino.core.toolChainProvider"; //$NON-NLS-1$ + + @Override + public String getId() { + return ID; + } + + @Override + public IToolChain getToolChain(String name) throws CoreException { + return new ArduinoToolChain(this, name); + } + +} diff --git a/toolchains/arduino/org.eclipse.cdt.arduino.core/src/org/eclipse/cdt/arduino/core/internal/console/ArduinoConsoleParser.java b/toolchains/arduino/org.eclipse.cdt.arduino.core/src/org/eclipse/cdt/arduino/core/internal/console/ArduinoConsoleParser.java deleted file mode 100644 index 582a7f485c7..00000000000 --- a/toolchains/arduino/org.eclipse.cdt.arduino.core/src/org/eclipse/cdt/arduino/core/internal/console/ArduinoConsoleParser.java +++ /dev/null @@ -1,60 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2015 QNX Software Systems and others. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - *******************************************************************************/ -package org.eclipse.cdt.arduino.core.internal.console; - -public abstract class ArduinoConsoleParser { - - private final String pattern; - private final int flags; - private final String lineQualifier; - - protected ArduinoConsoleParser(String pattern, int flags, String lineQualifier) { - this.pattern = pattern; - this.flags = flags; - this.lineQualifier = lineQualifier; - } - - /** - * Returns the pattern to be used for matching. The pattern is a string - * representing a regular expression. - * - * @return the regular expression to be used for matching - */ - public String getPattern() { - return pattern; - } - - /** - * Returns the flags to use when compiling this pattern match listener's - * regular expression, as defined by by - * Pattern.compile(String regex, int flags) - * - * @return the flags to use when compiling this pattern match listener's - * regular expression - * @see java.util.regex.Pattern#compile(java.lang.String, int) - */ - public int getCompilerFlags() { - return flags; - } - - /** - * Returns a simple regular expression used to identify lines that may match - * this pattern matcher's complete pattern, or null. Use of - * this attribute can improve performance by disqualifying lines from the - * search. When a line is found containing a match for this expression, the - * line is searched from the beginning for this pattern matcher's complete - * pattern. Lines not containing this pattern are discarded. - * - * @return a simple regular expression used to identify lines that may match - * this pattern matcher's complete pattern, or null - */ - public String getLineQualifier() { - return lineQualifier; - } - -} diff --git a/toolchains/arduino/org.eclipse.cdt.arduino.core/src/org/eclipse/cdt/arduino/core/internal/console/ArduinoConsoleService.java b/toolchains/arduino/org.eclipse.cdt.arduino.core/src/org/eclipse/cdt/arduino/core/internal/console/ArduinoConsoleService.java deleted file mode 100644 index 5ac7dba8731..00000000000 --- a/toolchains/arduino/org.eclipse.cdt.arduino.core/src/org/eclipse/cdt/arduino/core/internal/console/ArduinoConsoleService.java +++ /dev/null @@ -1,25 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2015 QNX Software Systems and others. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - * - * Contributors: - * QNX Software Systems - Initial API and implementation - *******************************************************************************/ -package org.eclipse.cdt.arduino.core.internal.console; - -import java.io.IOException; - -import org.eclipse.core.resources.IFolder; - -public interface ArduinoConsoleService { - - void monitor(Process process, ArduinoConsoleParser[] consoleParsers, IFolder buildDirectory) throws IOException; - - void writeOutput(String msg) throws IOException; - - void writeError(String msg) throws IOException; - -} diff --git a/toolchains/arduino/org.eclipse.cdt.arduino.core/src/org/eclipse/cdt/arduino/core/internal/console/ArduinoErrorParser.java b/toolchains/arduino/org.eclipse.cdt.arduino.core/src/org/eclipse/cdt/arduino/core/internal/console/ArduinoErrorParser.java deleted file mode 100644 index 4adaac9fc85..00000000000 --- a/toolchains/arduino/org.eclipse.cdt.arduino.core/src/org/eclipse/cdt/arduino/core/internal/console/ArduinoErrorParser.java +++ /dev/null @@ -1,83 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2015 QNX Software Systems and others. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - *******************************************************************************/ -package org.eclipse.cdt.arduino.core.internal.console; - -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -import org.eclipse.cdt.arduino.core.internal.Activator; -import org.eclipse.cdt.core.model.ICModelMarker; -import org.eclipse.core.resources.IFile; -import org.eclipse.core.resources.IFolder; -import org.eclipse.core.resources.IMarker; -import org.eclipse.core.resources.IResource; -import org.eclipse.core.runtime.CoreException; - -public abstract class ArduinoErrorParser extends ArduinoConsoleParser { - - public static final String LINK_OFFSET = "arduino.link.offset"; //$NON-NLS-1$ - public static final String LINK_LENGTH = "arduino.link.length"; //$NON-NLS-1$ - - private final Pattern errorPattern; - - public ArduinoErrorParser(String pattern, int flags, String lineQualifier) { - super(pattern, flags, lineQualifier); - this.errorPattern = Pattern.compile(pattern); - } - - public ArduinoErrorParser(String pattern) { - this(pattern, 0, null); - } - - protected abstract String getFileName(Matcher matcher); - - protected abstract int getLineNumber(Matcher matcher); - - protected abstract String getMessage(Matcher matcher); - - protected abstract int getSeverity(Matcher matcher); - - protected abstract int getLinkOffset(Matcher matcher); - - protected abstract int getLinkLength(Matcher matcher); - - public IMarker generateMarker(IFolder buildDirectory, String text) throws CoreException { - Matcher matcher = errorPattern.matcher(text); - if (matcher.matches()) { - String fileName = getFileName(matcher); - - IFile file = buildDirectory.getFile(fileName); - if (file.exists()) { - for (IMarker marker : file.findMarkers(ICModelMarker.C_MODEL_PROBLEM_MARKER, false, - IResource.DEPTH_ZERO)) { - if (marker.getAttribute(IMarker.SEVERITY, -1) == getSeverity(matcher) - && marker.getAttribute(IMarker.LINE_NUMBER, -1) == getLineNumber(matcher) - && marker.getAttribute(IMarker.MESSAGE, "").equals(getMessage(matcher))) { //$NON-NLS-1$ - return marker; - } - } - try { - IMarker marker = file.createMarker(ICModelMarker.C_MODEL_PROBLEM_MARKER); - marker.setAttribute(IMarker.MESSAGE, getMessage(matcher)); - marker.setAttribute(IMarker.SEVERITY, getSeverity(matcher)); - marker.setAttribute(IMarker.LINE_NUMBER, getLineNumber(matcher)); - marker.setAttribute(IMarker.CHAR_START, -1); - marker.setAttribute(IMarker.CHAR_END, -1); - marker.setAttribute(LINK_OFFSET, getLinkOffset(matcher)); - marker.setAttribute(LINK_LENGTH, getLinkLength(matcher)); - return marker; - } catch (CoreException e) { - Activator.log(e); - return null; - } - } - } - return null; - } - -} diff --git a/toolchains/arduino/org.eclipse.cdt.arduino.core/src/org/eclipse/cdt/arduino/core/internal/launch/ArduinoLaunchConfigurationDelegate.java b/toolchains/arduino/org.eclipse.cdt.arduino.core/src/org/eclipse/cdt/arduino/core/internal/launch/ArduinoLaunchConfigurationDelegate.java index b3b1d361887..6ec1d0c9385 100644 --- a/toolchains/arduino/org.eclipse.cdt.arduino.core/src/org/eclipse/cdt/arduino/core/internal/launch/ArduinoLaunchConfigurationDelegate.java +++ b/toolchains/arduino/org.eclipse.cdt.arduino.core/src/org/eclipse/cdt/arduino/core/internal/launch/ArduinoLaunchConfigurationDelegate.java @@ -15,7 +15,9 @@ import java.io.IOException; import org.eclipse.cdt.arduino.core.internal.Activator; import org.eclipse.cdt.arduino.core.internal.Messages; import org.eclipse.cdt.arduino.core.internal.build.ArduinoBuildConfiguration; +import org.eclipse.cdt.arduino.core.internal.build.ArduinoBuildConfigurationProvider; import org.eclipse.cdt.arduino.core.internal.remote.ArduinoRemoteConnection; +import org.eclipse.cdt.core.build.ICBuildConfigurationManager; import org.eclipse.core.resources.IProject; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IProgressMonitor; @@ -34,6 +36,9 @@ public class ArduinoLaunchConfigurationDelegate extends LaunchConfigurationTarge public static final String TYPE_ID = "org.eclipse.cdt.arduino.core.launchConfigurationType"; //$NON-NLS-1$ public static final String CONNECTION_NAME = Activator.getId() + ".connectionName"; //$NON-NLS-1$ + private static final ICBuildConfigurationManager buildConfigManager = Activator + .getService(ICBuildConfigurationManager.class); + @Override public ITargetedLaunch getLaunch(ILaunchConfiguration configuration, String mode, ILaunchTarget target) throws CoreException { @@ -49,7 +54,7 @@ public class ArduinoLaunchConfigurationDelegate extends LaunchConfigurationTarge // 1. make sure proper build config is set active IProject project = configuration.getMappedResources()[0].getProject(); - ArduinoBuildConfiguration arduinoConfig = ArduinoBuildConfiguration.getConfig(project, arduinoTarget, + ArduinoBuildConfiguration arduinoConfig = getArduinoConfiguration(project, mode, arduinoTarget, monitor); arduinoConfig.setActive(monitor); } @@ -81,7 +86,7 @@ public class ArduinoLaunchConfigurationDelegate extends LaunchConfigurationTarge IProject project = (IProject) configuration.getMappedResources()[0]; // The build config - ArduinoBuildConfiguration arduinoConfig = ArduinoBuildConfiguration.getConfig(project, arduinoTarget, + ArduinoBuildConfiguration arduinoConfig = getArduinoConfiguration(project, mode, arduinoTarget, monitor); String[] uploadCmd = arduinoConfig.getUploadCommand(arduinoTarget.getPortName()); @@ -94,8 +99,9 @@ public class ArduinoLaunchConfigurationDelegate extends LaunchConfigurationTarge ((ArduinoLaunch) launch).start(); // Run the process and capture the results in the console - ProcessBuilder processBuilder = new ProcessBuilder(uploadCmd).directory(arduinoConfig.getBuildDirectory()); - arduinoConfig.setEnvironment(processBuilder.environment()); + ProcessBuilder processBuilder = new ProcessBuilder(uploadCmd) + .directory(arduinoConfig.getBuildDirectory().toFile()); + arduinoConfig.setBuildEnvironment(processBuilder.environment()); Process process = processBuilder.start(); DebugPlugin.newProcess(launch, process, cmdStr.toString()); } catch (IOException e) { @@ -104,4 +110,15 @@ public class ArduinoLaunchConfigurationDelegate extends LaunchConfigurationTarge } + public ArduinoBuildConfiguration getArduinoConfiguration(IProject project, String launchMode, + ArduinoRemoteConnection arduinoTarget, + IProgressMonitor monitor) throws CoreException { + ArduinoBuildConfigurationProvider provider = (ArduinoBuildConfigurationProvider) buildConfigManager + .getProvider(ArduinoBuildConfigurationProvider.ID); + ArduinoBuildConfiguration config = provider.getConfiguration(project, arduinoTarget, launchMode, monitor); + if (config == null) { + config = provider.createConfiguration(project, arduinoTarget, launchMode, monitor); + } + return config; + } } diff --git a/toolchains/arduino/org.eclipse.cdt.arduino.core/templates/board.mk b/toolchains/arduino/org.eclipse.cdt.arduino.core/templates/Makefile similarity index 97% rename from toolchains/arduino/org.eclipse.cdt.arduino.core/templates/board.mk rename to toolchains/arduino/org.eclipse.cdt.arduino.core/templates/Makefile index 1f0971bd120..48888521aa8 100644 --- a/toolchains/arduino/org.eclipse.cdt.arduino.core/templates/board.mk +++ b/toolchains/arduino/org.eclipse.cdt.arduino.core/templates/Makefile @@ -91,7 +91,7 @@ size: <#list project_srcs as file> <#assign cpp = file?matches("(.*)\\.cpp")> <#if cpp> -${build_path}/project/${cpp?groups[1]}.cpp.o: ../${file} ${build_path}/project/${cpp?groups[1]}.cpp.d +${build_path}/project/${cpp?groups[1]}.cpp.o: ../../${file} ${build_path}/project/${cpp?groups[1]}.cpp.d @$(call mymkdir,$(dir $@)) ${recipe_cpp_o_pattern} diff --git a/toolchains/arduino/org.eclipse.cdt.arduino.core/templates/arduino.cpp b/toolchains/arduino/org.eclipse.cdt.arduino.core/templates/cppsketch/arduino.cpp similarity index 100% rename from toolchains/arduino/org.eclipse.cdt.arduino.core/templates/arduino.cpp rename to toolchains/arduino/org.eclipse.cdt.arduino.core/templates/cppsketch/arduino.cpp diff --git a/toolchains/arduino/org.eclipse.cdt.arduino.core/templates/cppsketch/manifest.xml b/toolchains/arduino/org.eclipse.cdt.arduino.core/templates/cppsketch/manifest.xml new file mode 100644 index 00000000000..148f5c807ca --- /dev/null +++ b/toolchains/arduino/org.eclipse.cdt.arduino.core/templates/cppsketch/manifest.xml @@ -0,0 +1,4 @@ + + + \ No newline at end of file diff --git a/toolchains/arduino/org.eclipse.cdt.arduino.ui/META-INF/MANIFEST.MF b/toolchains/arduino/org.eclipse.cdt.arduino.ui/META-INF/MANIFEST.MF index 85291e2145f..c66654bacc6 100644 --- a/toolchains/arduino/org.eclipse.cdt.arduino.ui/META-INF/MANIFEST.MF +++ b/toolchains/arduino/org.eclipse.cdt.arduino.ui/META-INF/MANIFEST.MF @@ -19,7 +19,8 @@ Require-Bundle: org.eclipse.core.runtime, org.eclipse.remote.ui;bundle-version="2.0.0", org.eclipse.cdt.core, org.eclipse.cdt.native.serial;bundle-version="1.0.0", - org.eclipse.launchbar.remote.ui;bundle-version="1.0.0" + org.eclipse.launchbar.remote.ui;bundle-version="1.0.0", + org.eclipse.tools.templates.ui;bundle-version="1.0.0" Bundle-RequiredExecutionEnvironment: JavaSE-1.7 Bundle-ActivationPolicy: lazy Bundle-Vendor: %providerName diff --git a/toolchains/arduino/org.eclipse.cdt.arduino.ui/icons/arduino48.png b/toolchains/arduino/org.eclipse.cdt.arduino.ui/icons/arduino48.png new file mode 100644 index 00000000000..1fa5d248086 Binary files /dev/null and b/toolchains/arduino/org.eclipse.cdt.arduino.ui/icons/arduino48.png differ diff --git a/toolchains/arduino/org.eclipse.cdt.arduino.ui/plugin.xml b/toolchains/arduino/org.eclipse.cdt.arduino.ui/plugin.xml index 1a6410413b3..3e5c883c989 100644 --- a/toolchains/arduino/org.eclipse.cdt.arduino.ui/plugin.xml +++ b/toolchains/arduino/org.eclipse.cdt.arduino.ui/plugin.xml @@ -112,8 +112,7 @@ @@ -149,4 +148,23 @@ name="Arduino"> + + + + + diff --git a/toolchains/arduino/org.eclipse.cdt.arduino.ui/src/org/eclipse/cdt/arduino/ui/internal/launch/ArduinoConsole.java b/toolchains/arduino/org.eclipse.cdt.arduino.ui/src/org/eclipse/cdt/arduino/ui/internal/launch/ArduinoConsole.java deleted file mode 100644 index fc14c9fe2fc..00000000000 --- a/toolchains/arduino/org.eclipse.cdt.arduino.ui/src/org/eclipse/cdt/arduino/ui/internal/launch/ArduinoConsole.java +++ /dev/null @@ -1,162 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2015 QNX Software Systems and others. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - * - * Contributors: - * QNX Software Systems - Initial API and implementation - *******************************************************************************/ -package org.eclipse.cdt.arduino.ui.internal.launch; - -import java.io.BufferedReader; -import java.io.IOException; -import java.io.InputStreamReader; -import java.util.ArrayList; -import java.util.List; -import java.util.concurrent.Semaphore; - -import org.eclipse.cdt.arduino.core.internal.console.ArduinoConsoleParser; -import org.eclipse.cdt.arduino.core.internal.console.ArduinoConsoleService; -import org.eclipse.cdt.arduino.core.internal.console.ArduinoErrorParser; -import org.eclipse.cdt.arduino.ui.internal.Activator; -import org.eclipse.cdt.arduino.ui.internal.Messages; -import org.eclipse.core.resources.IFolder; -import org.eclipse.core.resources.IResourceChangeEvent; -import org.eclipse.core.resources.IResourceChangeListener; -import org.eclipse.core.resources.IncrementalProjectBuilder; -import org.eclipse.core.resources.ResourcesPlugin; -import org.eclipse.swt.SWT; -import org.eclipse.swt.widgets.Display; -import org.eclipse.ui.console.ConsolePlugin; -import org.eclipse.ui.console.IConsole; -import org.eclipse.ui.console.MessageConsole; -import org.eclipse.ui.console.MessageConsoleStream; - -public class ArduinoConsole implements ArduinoConsoleService, IResourceChangeListener { - - private static MessageConsole console; - private static MessageConsoleStream out; - private static MessageConsoleStream err; - - private IFolder buildDirectory; - List listeners = new ArrayList<>(); - - public ArduinoConsole() { - if (console == null) { - console = new MessageConsole(Messages.ArduinoLaunchConsole_0, null); - ConsolePlugin.getDefault().getConsoleManager().addConsoles(new IConsole[] { console }); - out = console.newMessageStream(); - err = console.newMessageStream(); - - // set the colors - final Display display = Display.getDefault(); - display.syncExec(new Runnable() { - @Override - public void run() { - out.setColor(display.getSystemColor(SWT.COLOR_BLACK)); - err.setColor(display.getSystemColor(SWT.COLOR_RED)); - } - }); - ResourcesPlugin.getWorkspace().addResourceChangeListener(this, IResourceChangeEvent.PRE_BUILD); - } - } - - @Override - public void resourceChanged(IResourceChangeEvent event) { - switch (event.getType()) { - case IResourceChangeEvent.PRE_BUILD: - if (event.getBuildKind() != IncrementalProjectBuilder.AUTO_BUILD) { - // TODO this really should be done from the core and only when - // our projects are being built - console.clearConsole(); - } - break; - } - } - - public IFolder getBuildDirectory() { - return buildDirectory; - } - - @Override - public void monitor(final Process process, ArduinoConsoleParser[] consoleParsers, IFolder buildDirectory) - throws IOException { - this.buildDirectory = buildDirectory; - - // Clear the old listeners - for (ArduinoPatternMatchListener listener : listeners) { - console.removePatternMatchListener(listener); - } - listeners.clear(); - - // Add in the new ones if any - if (consoleParsers != null) { - for (ArduinoConsoleParser parser : consoleParsers) { - ArduinoPatternMatchListener listener; - if (parser instanceof ArduinoErrorParser) { - listener = new ArduinoErrorMatchListener(this, (ArduinoErrorParser) parser); - } else { - continue; - } - listeners.add(listener); - console.addPatternMatchListener(listener); - } - } - - console.activate(); - - final Semaphore sema = new Semaphore(-1); - - // Output stream reader - new Thread(Messages.ArduinoLaunchConsole_2) { - public void run() { - try (BufferedReader processOut = new BufferedReader(new InputStreamReader(process.getInputStream()))) { - for (String line = processOut.readLine(); line != null; line = processOut.readLine()) { - out.write(line); - out.write('\n'); - } - } catch (IOException e) { - e.printStackTrace(); - } finally { - sema.release(); - } - } - }.start(); - - // Error stream reader - new Thread(Messages.ArduinoLaunchConsole_2) { - public void run() { - try (BufferedReader processErr = new BufferedReader(new InputStreamReader(process.getErrorStream()))) { - for (String line = processErr.readLine(); line != null; line = processErr.readLine()) { - err.write(line); - out.write('\n'); - } - } catch (IOException e) { - e.printStackTrace(); - } finally { - sema.release(); - } - } - }.start(); - - try { - sema.acquire(); - process.waitFor(); - } catch (InterruptedException e) { - Activator.log(e); - } - } - - @Override - public void writeOutput(String msg) throws IOException { - out.write(msg); - } - - @Override - public void writeError(String msg) throws IOException { - err.write(msg); - } - -} diff --git a/toolchains/arduino/org.eclipse.cdt.arduino.ui/src/org/eclipse/cdt/arduino/ui/internal/launch/ArduinoErrorMatchListener.java b/toolchains/arduino/org.eclipse.cdt.arduino.ui/src/org/eclipse/cdt/arduino/ui/internal/launch/ArduinoErrorMatchListener.java deleted file mode 100644 index b2113940093..00000000000 --- a/toolchains/arduino/org.eclipse.cdt.arduino.ui/src/org/eclipse/cdt/arduino/ui/internal/launch/ArduinoErrorMatchListener.java +++ /dev/null @@ -1,38 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2015 QNX Software Systems and others. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - *******************************************************************************/ -package org.eclipse.cdt.arduino.ui.internal.launch; - -import org.eclipse.cdt.arduino.core.internal.console.ArduinoErrorParser; -import org.eclipse.cdt.arduino.ui.internal.Activator; -import org.eclipse.core.resources.IMarker; -import org.eclipse.core.runtime.CoreException; -import org.eclipse.jface.text.BadLocationException; -import org.eclipse.ui.console.PatternMatchEvent; - -public class ArduinoErrorMatchListener extends ArduinoPatternMatchListener { - - public ArduinoErrorMatchListener(ArduinoConsole arduinoConsole, ArduinoErrorParser parser) { - super(arduinoConsole, parser); - } - - @Override - public void matchFound(PatternMatchEvent event) { - try { - String text = textConsole.getDocument().get(event.getOffset(), event.getLength()); - IMarker marker = ((ArduinoErrorParser) parser).generateMarker(arduinoConsole.getBuildDirectory(), text); - if (marker != null) { - textConsole.addHyperlink(new ArduinoHyperlink(marker), - event.getOffset() + marker.getAttribute(ArduinoErrorParser.LINK_OFFSET, 0), - marker.getAttribute(ArduinoErrorParser.LINK_LENGTH, event.getLength())); - } - } catch (BadLocationException | CoreException e) { - Activator.log(e); - } - } - -} diff --git a/toolchains/arduino/org.eclipse.cdt.arduino.ui/src/org/eclipse/cdt/arduino/ui/internal/launch/ArduinoHyperlink.java b/toolchains/arduino/org.eclipse.cdt.arduino.ui/src/org/eclipse/cdt/arduino/ui/internal/launch/ArduinoHyperlink.java deleted file mode 100644 index 51927a45cf0..00000000000 --- a/toolchains/arduino/org.eclipse.cdt.arduino.ui/src/org/eclipse/cdt/arduino/ui/internal/launch/ArduinoHyperlink.java +++ /dev/null @@ -1,44 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2015 QNX Software Systems and others. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - *******************************************************************************/ -package org.eclipse.cdt.arduino.ui.internal.launch; - -import org.eclipse.cdt.arduino.ui.internal.Activator; -import org.eclipse.core.resources.IMarker; -import org.eclipse.ui.IWorkbenchPage; -import org.eclipse.ui.PartInitException; -import org.eclipse.ui.PlatformUI; -import org.eclipse.ui.console.IHyperlink; -import org.eclipse.ui.ide.IDE; - -public class ArduinoHyperlink implements IHyperlink { - - private final IMarker marker; - - public ArduinoHyperlink(IMarker marker) { - this.marker = marker; - } - - @Override - public void linkEntered() { - } - - @Override - public void linkExited() { - } - - @Override - public void linkActivated() { - IWorkbenchPage page = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage(); - try { - IDE.openEditor(page, marker); - } catch (PartInitException e) { - Activator.log(e); - } - } - -} diff --git a/toolchains/arduino/org.eclipse.cdt.arduino.ui/src/org/eclipse/cdt/arduino/ui/internal/launch/ArduinoPatternMatchListener.java b/toolchains/arduino/org.eclipse.cdt.arduino.ui/src/org/eclipse/cdt/arduino/ui/internal/launch/ArduinoPatternMatchListener.java deleted file mode 100644 index ea222570f14..00000000000 --- a/toolchains/arduino/org.eclipse.cdt.arduino.ui/src/org/eclipse/cdt/arduino/ui/internal/launch/ArduinoPatternMatchListener.java +++ /dev/null @@ -1,50 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2015 QNX Software Systems and others. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - *******************************************************************************/ -package org.eclipse.cdt.arduino.ui.internal.launch; - -import org.eclipse.cdt.arduino.core.internal.console.ArduinoConsoleParser; -import org.eclipse.ui.console.IPatternMatchListener; -import org.eclipse.ui.console.TextConsole; - -public abstract class ArduinoPatternMatchListener implements IPatternMatchListener { - - protected final ArduinoConsole arduinoConsole; - protected final ArduinoConsoleParser parser; - - protected TextConsole textConsole; - - public ArduinoPatternMatchListener(ArduinoConsole arduinoConsole, ArduinoConsoleParser parser) { - this.arduinoConsole = arduinoConsole; - this.parser = parser; - } - - @Override - public void connect(TextConsole console) { - this.textConsole = console; - } - - @Override - public void disconnect() { - } - - @Override - public String getPattern() { - return parser.getPattern(); - } - - @Override - public int getCompilerFlags() { - return parser.getCompilerFlags(); - } - - @Override - public String getLineQualifier() { - return parser.getLineQualifier(); - } - -} diff --git a/toolchains/arduino/org.eclipse.cdt.arduino.ui/src/org/eclipse/cdt/arduino/ui/internal/project/NewArduinoCPPSketchWizard.java b/toolchains/arduino/org.eclipse.cdt.arduino.ui/src/org/eclipse/cdt/arduino/ui/internal/project/NewArduinoCPPSketchWizard.java new file mode 100644 index 00000000000..65b096de228 --- /dev/null +++ b/toolchains/arduino/org.eclipse.cdt.arduino.ui/src/org/eclipse/cdt/arduino/ui/internal/project/NewArduinoCPPSketchWizard.java @@ -0,0 +1,47 @@ +/******************************************************************************* + * Copyright (c) 2015 QNX Software Systems and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + *******************************************************************************/ +package org.eclipse.cdt.arduino.ui.internal.project; + +import org.eclipse.cdt.arduino.core.internal.ArduinoProjectGenerator; +import org.eclipse.jface.dialogs.Dialog; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.tools.templates.core.IGenerator; +import org.eclipse.tools.templates.ui.TemplateWizard; +import org.eclipse.ui.dialogs.WizardNewProjectCreationPage; + +public class NewArduinoCPPSketchWizard extends TemplateWizard { + + private WizardNewProjectCreationPage mainPage; + + @Override + public void addPages() { + mainPage = new WizardNewProjectCreationPage("basicNewProjectPage") { //$NON-NLS-1$ + @Override + public void createControl(Composite parent) { + super.createControl(parent); + createWorkingSetGroup((Composite) getControl(), getSelection(), + new String[] { "org.eclipse.ui.resourceWorkingSetPage" }); //$NON-NLS-1$ + Dialog.applyDialogFont(getControl()); + } + }; + mainPage.setTitle("New Arduino Project"); //$NON-NLS-1$ + mainPage.setDescription("Specify properties of new Arduino project."); //$NON-NLS-1$ + this.addPage(mainPage); + } + + @Override + protected IGenerator getGenerator() { + ArduinoProjectGenerator generator = new ArduinoProjectGenerator("templates/cppsketch/manifest.xml"); //$NON-NLS-1$ + generator.setProjectName(mainPage.getProjectName()); + if (!mainPage.useDefaults()) { + generator.setLocationURI(mainPage.getLocationURI()); + } + return generator; + } + +} diff --git a/toolchains/arduino/org.eclipse.cdt.arduino.ui/src/org/eclipse/cdt/arduino/ui/internal/project/NewArduinoProjectWizard.java b/toolchains/arduino/org.eclipse.cdt.arduino.ui/src/org/eclipse/cdt/arduino/ui/internal/project/NewArduinoProjectWizard.java index 1ad1f0df6d7..7280d958f74 100644 --- a/toolchains/arduino/org.eclipse.cdt.arduino.ui/src/org/eclipse/cdt/arduino/ui/internal/project/NewArduinoProjectWizard.java +++ b/toolchains/arduino/org.eclipse.cdt.arduino.ui/src/org/eclipse/cdt/arduino/ui/internal/project/NewArduinoProjectWizard.java @@ -7,55 +7,28 @@ *******************************************************************************/ package org.eclipse.cdt.arduino.ui.internal.project; -import org.eclipse.cdt.arduino.core.internal.ArduinoProjectGenerator; -import org.eclipse.cdt.arduino.ui.internal.Activator; -import org.eclipse.cdt.arduino.ui.internal.Messages; -import org.eclipse.core.runtime.CoreException; -import org.eclipse.core.runtime.IProgressMonitor; -import org.eclipse.core.runtime.IStatus; -import org.eclipse.core.runtime.Status; -import org.eclipse.core.runtime.jobs.Job; -import org.eclipse.ui.IWorkbenchPage; -import org.eclipse.ui.PartInitException; -import org.eclipse.ui.ide.IDE; +import org.eclipse.tools.templates.ui.TemplateSelectionPage; import org.eclipse.ui.wizards.newresource.BasicNewProjectResourceWizard; public class NewArduinoProjectWizard extends BasicNewProjectResourceWizard { + private static final String ARDUINO_TAG_ID = "org.eclipse.cdt.arduino.ui.tag"; //$NON-NLS-1$ + + private TemplateSelectionPage templateSelectionPage; + + public NewArduinoProjectWizard() { + setForcePreviousAndNextButtons(true); + } + @Override public void addPages() { - super.addPages(); + templateSelectionPage = new TemplateSelectionPage("templateSelection", ARDUINO_TAG_ID); //$NON-NLS-1$ + templateSelectionPage.setTitle("Template for New Arduino Project"); + this.addPage(templateSelectionPage); } @Override public boolean performFinish() { - if (!super.performFinish()) - return false; - - new Job(Messages.NewArduinoProjectWizard_0) { - @Override - protected IStatus run(IProgressMonitor monitor) { - try { - final ArduinoProjectGenerator generator = new ArduinoProjectGenerator(getNewProject()); - generator.generate(monitor); - getWorkbench().getDisplay().asyncExec(new Runnable() { - @Override - public void run() { - try { - IWorkbenchPage activePage = getWorkbench().getActiveWorkbenchWindow().getActivePage(); - IDE.openEditor(activePage, generator.getSourceFile()); - } catch (PartInitException e) { - Activator.getDefault().getLog().log(e.getStatus()); - } - } - }); - return Status.OK_STATUS; - } catch (CoreException e) { - return e.getStatus(); - } - } - }.schedule(); - return true; }