1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-07-25 01:45:33 +02:00

Modernize Arduino plug-ins. Adjust APIs to suite.

Change-Id: Ic877c8f0992874e647d4b464502165d7bd3ebe0e
This commit is contained in:
Doug Schaefer 2016-04-27 16:44:47 -04:00
parent b2300cbcfe
commit 7139dc2f1e
60 changed files with 1264 additions and 1864 deletions

View file

@ -1,20 +1,15 @@
<?xml version="1.0" encoding="UTF-8"?>
<?eclipse version="3.4"?>
<plugin>
<extension
point="org.eclipse.cdt.core.toolChainType">
<toolChainType
class="org.eclipse.cdt.build.gcc.core.GCCToolChainType"
id="org.eclipse.cdt.build.gcc">
</toolChainType>
</extension>
<extension
point="org.eclipse.cdt.core.toolChainProvider">
<provider
class="org.eclipse.cdt.build.gcc.core.internal.GCCPathToolChainProvider">
class="org.eclipse.cdt.build.gcc.core.internal.GCCPathToolChainProvider"
id="org.eclipse.cdt.build.gcc.core.gccPathProvider">
</provider>
<provider
class="org.eclipse.cdt.build.gcc.core.internal.Msys2ToolChainProvider">
class="org.eclipse.cdt.build.gcc.core.internal.Msys2ToolChainProvider"
id="org.eclipse.cdt.build.gcc.core.msys2Provider">
</provider>
</extension>

View file

@ -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<String> 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<String> 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<String> 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<IResource> 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()]);
}

View file

@ -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;
}
}

View file

@ -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<IToolChain> getToolChains() {
IToolChainManager manager = Activator.getService(IToolChainManager.class);
IToolChainType type = null;
List<IToolChain> toolChains = new ArrayList<>();
String path = null;
for (Entry<String, String> entry : System.getenv().entrySet()) {
if (entry.getKey().equalsIgnoreCase("PATH")) { //$NON-NLS-1$
path = entry.getValue();
break;
}
}
if (path != null) {
Map<String, List<String>> 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<String> commands = installs.get(version);
if (commands == null) {
commands = new ArrayList<>();
installs.put(version, commands);
}
commands.add(command);
}
}
}
}
}
for (Entry<String, List<String>> 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<String> 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$

View file

@ -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<IToolChain> 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<IToolChain> 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();
}
}

View file

@ -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

View file

@ -685,7 +685,6 @@
<extension-point id="ProblemMarkerFilter" name="%problemMarkerFilter.name" schema="schema/ProblemMarkerFilter.exsd"/>
<extension-point id="buildConfigProvider" name="buildConfigProvider" schema="schema/buildConfigProvider.exsd"/>
<extension-point id="toolChainProvider" name="Tool Chain Provider" schema="schema/toolChainProvider.exsd"/>
<extension-point id="toolChainType" name="Tool Chain Type" schema="schema/toolChainType.exsd"/>
<extension
point="org.eclipse.cdt.core.templateProcessTypes">

View file

@ -1,102 +1,109 @@
<?xml version='1.0' encoding='UTF-8'?>
<!-- Schema file written by PDE -->
<schema targetNamespace="org.eclipse.cdt.core" xmlns="http://www.w3.org/2001/XMLSchema">
<annotation>
<appInfo>
<meta.schema plugin="org.eclipse.cdt.core" id="ToolChainProvider" name="Tool Chain Provider"/>
</appInfo>
<documentation>
A toolchain provider provides automatically discovered toolchains when requested. Providers have enablement to make sure they aren&apos;t called unless there&apos;s a good chance they have toolchains to offer.
</documentation>
</annotation>
<element name="extension">
<annotation>
<appInfo>
<meta.element />
</appInfo>
</annotation>
<complexType>
<sequence minOccurs="1" maxOccurs="unbounded">
<element ref="provider"/>
</sequence>
<attribute name="point" type="string" use="required">
<annotation>
<documentation>
</documentation>
</annotation>
</attribute>
<attribute name="id" type="string">
<annotation>
<documentation>
</documentation>
</annotation>
</attribute>
<attribute name="name" type="string">
<annotation>
<documentation>
</documentation>
<appInfo>
<meta.attribute translatable="true"/>
</appInfo>
</annotation>
</attribute>
</complexType>
</element>
<element name="provider">
<complexType>
<attribute name="class" type="string" use="required">
<annotation>
<documentation>
</documentation>
<appInfo>
<meta.attribute kind="java" basedOn=":org.eclipse.cdt.core.build.IToolChainProvider"/>
</appInfo>
</annotation>
</attribute>
</complexType>
</element>
<annotation>
<appInfo>
<meta.section type="since"/>
</appInfo>
<documentation>
[Enter the first release in which this extension point appears.]
</documentation>
</annotation>
<annotation>
<appInfo>
<meta.section type="examples"/>
</appInfo>
<documentation>
[Enter extension point usage example here.]
</documentation>
</annotation>
<annotation>
<appInfo>
<meta.section type="apiinfo"/>
</appInfo>
<documentation>
[Enter API information here.]
</documentation>
</annotation>
<annotation>
<appInfo>
<meta.section type="implementation"/>
</appInfo>
<documentation>
[Enter information about supplied implementation of this extension point.]
</documentation>
</annotation>
</schema>
<?xml version='1.0' encoding='UTF-8'?>
<!-- Schema file written by PDE -->
<schema targetNamespace="org.eclipse.cdt.core" xmlns="http://www.w3.org/2001/XMLSchema">
<annotation>
<appInfo>
<meta.schema plugin="org.eclipse.cdt.core" id="ToolChainProvider" name="Tool Chain Provider"/>
</appInfo>
<documentation>
A toolchain provider provides automatically discovered toolchains when requested. Providers have enablement to make sure they aren&apos;t called unless there&apos;s a good chance they have toolchains to offer.
</documentation>
</annotation>
<element name="extension">
<annotation>
<appInfo>
<meta.element />
</appInfo>
</annotation>
<complexType>
<sequence minOccurs="1" maxOccurs="unbounded">
<element ref="provider"/>
</sequence>
<attribute name="point" type="string" use="required">
<annotation>
<documentation>
</documentation>
</annotation>
</attribute>
<attribute name="id" type="string">
<annotation>
<documentation>
</documentation>
</annotation>
</attribute>
<attribute name="name" type="string">
<annotation>
<documentation>
</documentation>
<appInfo>
<meta.attribute translatable="true"/>
</appInfo>
</annotation>
</attribute>
</complexType>
</element>
<element name="provider">
<complexType>
<attribute name="id" type="string" use="required">
<annotation>
<documentation>
</documentation>
</annotation>
</attribute>
<attribute name="class" type="string" use="required">
<annotation>
<documentation>
</documentation>
<appInfo>
<meta.attribute kind="java" basedOn=":org.eclipse.cdt.core.build.IToolChainProvider"/>
</appInfo>
</annotation>
</attribute>
</complexType>
</element>
<annotation>
<appInfo>
<meta.section type="since"/>
</appInfo>
<documentation>
[Enter the first release in which this extension point appears.]
</documentation>
</annotation>
<annotation>
<appInfo>
<meta.section type="examples"/>
</appInfo>
<documentation>
[Enter extension point usage example here.]
</documentation>
</annotation>
<annotation>
<appInfo>
<meta.section type="apiinfo"/>
</appInfo>
<documentation>
[Enter API information here.]
</documentation>
</annotation>
<annotation>
<appInfo>
<meta.section type="implementation"/>
</appInfo>
<documentation>
[Enter information about supplied implementation of this extension point.]
</documentation>
</annotation>
</schema>

View file

@ -1,127 +0,0 @@
<?xml version='1.0' encoding='UTF-8'?>
<!-- Schema file written by PDE -->
<schema targetNamespace="org.eclipse.cdt.core" xmlns="http://www.w3.org/2001/XMLSchema">
<annotation>
<appInfo>
<meta.schema plugin="org.eclipse.cdt.core" id="ToolChainType" name="Tool Chain Type"/>
</appInfo>
<documentation>
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.
</documentation>
</annotation>
<element name="extension">
<annotation>
<appInfo>
<meta.element />
</appInfo>
</annotation>
<complexType>
<sequence minOccurs="1" maxOccurs="unbounded">
<element ref="toolChainType"/>
</sequence>
<attribute name="point" type="string" use="required">
<annotation>
<documentation>
</documentation>
</annotation>
</attribute>
<attribute name="id" type="string">
<annotation>
<documentation>
</documentation>
</annotation>
</attribute>
<attribute name="name" type="string">
<annotation>
<documentation>
</documentation>
<appInfo>
<meta.attribute translatable="true"/>
</appInfo>
</annotation>
</attribute>
</complexType>
</element>
<element name="toolChainType">
<complexType>
<sequence minOccurs="0" maxOccurs="unbounded">
<element ref="targetType"/>
</sequence>
<attribute name="id" type="string" use="required">
<annotation>
<documentation>
</documentation>
</annotation>
</attribute>
<attribute name="class" type="string" use="required">
<annotation>
<documentation>
</documentation>
<appInfo>
<meta.attribute kind="java" basedOn=":org.eclipse.cdt.core.build.IToolChainType"/>
</appInfo>
</annotation>
</attribute>
</complexType>
</element>
<element name="targetType">
<complexType>
<attribute name="id" type="string" use="required">
<annotation>
<documentation>
</documentation>
<appInfo>
<meta.attribute kind="identifier" basedOn="org.eclipse.launchbar.core.launchTargetTypes/launchTargetType/@id"/>
</appInfo>
</annotation>
</attribute>
</complexType>
</element>
<annotation>
<appInfo>
<meta.section type="since"/>
</appInfo>
<documentation>
[Enter the first release in which this extension point appears.]
</documentation>
</annotation>
<annotation>
<appInfo>
<meta.section type="examples"/>
</appInfo>
<documentation>
[Enter extension point usage example here.]
</documentation>
</annotation>
<annotation>
<appInfo>
<meta.section type="apiinfo"/>
</appInfo>
<documentation>
[Enter API information here.]
</documentation>
</annotation>
<annotation>
<appInfo>
<meta.section type="implementation"/>
</appInfo>
<documentation>
[Enter information about supplied implementation of this extension point.]
</documentation>
</annotation>
</schema>

View file

@ -439,7 +439,7 @@ public class CCorePlugin extends Plugin {
* @see #setOptions
*/
public static HashMap<String, String> getDefaultOptions() {
HashMap<String, String> defaultOptions = new HashMap<String, String>(10);
HashMap<String, String> 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<String, String> getOptions() {
HashMap<String, String> options = new HashMap<String, String>(10);
HashMap<String, String> 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<IBinaryParser> list = new ArrayList<IBinaryParser>(cextensions.length);
ArrayList<IBinaryParser> 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$
}
}
}

View file

@ -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<String, String> env) {
public void setBuildEnvironment(Map<String, String> 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();

View file

@ -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<String, String> args, IConsole console, IProgressMonitor monitor) throws CoreException;

View file

@ -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;
}

View file

@ -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.

View file

@ -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);
}

View file

@ -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<IToolChain> 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<IToolChain> getToolChainsMatching(Map<String, String> properties);
Collection<IToolChain> getToolChainsMatching(Map<String, String> properties) throws CoreException;
void addToolChain(IToolChain toolChain);
void removeToolChain(IToolChain toolChain);
}

View file

@ -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<IToolChain> 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;
}
}

View file

@ -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);
}

View file

@ -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;
}

View file

@ -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();

View file

@ -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<String, IConfigurationElement> typeElements;
private Map<String, IToolChainType> types;
private Map<String, IConfigurationElement> providerElements;
private Map<String, IToolChainProvider> providers;
private Map<String, Map<String, IToolChain>> 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<String, IToolChain> 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<String, IToolChain> 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<String, IToolChain> 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<String, IToolChain> tcs = toolChains.get(typeId);
return tcs != null ? tcs.get(name) : null;
Map<String, IToolChain> 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<IToolChain> getToolChains(String providerId) {
init();
Map<String, IToolChain> provider = toolChains.get(providerId);
if (provider != null) {
return Collections.unmodifiableCollection(provider.values());
} else {
return Collections.emptyList();
}
}
}

View file

@ -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;

View file

@ -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;
}
}
}

View file

@ -192,7 +192,8 @@
<extension
point="org.eclipse.cdt.core.toolChainProvider">
<provider
class="org.eclipse.cdt.qt.core.QtMinGWToolChainProvider">
class="org.eclipse.cdt.qt.core.QtMinGWToolChainProvider"
id="org.eclipse.cdt.qt.core.qtMinGWProvider">
</provider>
</extension>
<extension

View file

@ -74,7 +74,8 @@ public class QtBuildConfiguration extends CBuildConfiguration implements ICBuild
QtBuildConfiguration(IBuildConfiguration config, String name, IToolChain toolChain, IQtInstall qtInstall,
String launchMode)
throws CoreException {
super(config, name, toolChain);
super(config, name);
setToolChain(toolChain);
this.qtInstall = qtInstall;
this.launchMode = launchMode;

View file

@ -8,6 +8,7 @@
package org.eclipse.cdt.internal.qt.core.launch;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.concurrent.ExecutionException;
import org.eclipse.cdt.core.build.IToolChain;
@ -64,7 +65,7 @@ public class QtLocalDebugLaunchConfigDelegate extends QtLaunchConfigurationDeleg
IQtBuildConfiguration qtBuildConfig = getQtBuildConfiguration(configuration, mode, target, monitor);
IToolChain toolChain = qtBuildConfig.getToolChain();
gdbLaunch.setGDBPath(toolChain.getCommandPath("gdb").toString()); //$NON-NLS-1$
gdbLaunch.setGDBPath(toolChain.getCommandPath(Paths.get("gdb")).toString()); //$NON-NLS-1$
String gdbVersion = gdbLaunch.getGDBVersion();
Path exeFile = qtBuildConfig.getProgramPath();

View file

@ -28,6 +28,10 @@ import org.osgi.framework.Bundle;
public class QtProjectGenerator extends FMProjectGenerator {
public QtProjectGenerator(String manifestPath) {
super(manifestPath);
}
@Override
protected void initProjectDescription(IProjectDescription description) {
description
@ -39,7 +43,7 @@ public class QtProjectGenerator extends FMProjectGenerator {
public Bundle getSourceBundle() {
return Activator.getDefault().getBundle();
}
@Override
public void generate(Map<String, Object> model, IProgressMonitor monitor) throws CoreException {
super.generate(model, monitor);

View file

@ -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<String, String> 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;
}

View file

@ -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<IToolChain> 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();
}
}

View file

@ -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<String, Object> 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;
}
}

View file

@ -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;
}
}

View file

@ -95,6 +95,7 @@
<feature id="org.eclipse.cdt.arduino">
</feature>
<iu id="org.freemarker" version="0.0.0"/>
<iu id="org.eclipse.tools.templates.core" version="0.0.0"/>
<iu id="org.eclipse.tools.templates.freemarker" version="0.0.0"/>
<iu id="org.eclipse.tools.templates.ui" version="0.0.0"/>
</site>

View file

@ -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

View file

@ -75,40 +75,9 @@
</run>
</runtime>
<builder
id="org.eclipse.cdt.arduino.core.arduinoBuilder">
id="com.qnx.tools.ide.qde.core.cbuilder">
</builder>
</extension>
<extension
id="arduinoBuilder"
name="%ArduinoBuilder.name"
point="org.eclipse.core.resources.builders">
<builder
callOnEmptyDelta="true"
hasNature="true"
isConfigurable="true"
supportsConfigurations="true">
<run
class="org.eclipse.cdt.arduino.core.internal.build.ArduinoBuilder">
</run>
</builder>
</extension>
<extension
point="org.eclipse.cdt.core.ScannerInfoProvider2">
<provider
builder="org.eclipse.cdt.arduino.core.arduinoBuilder"
class="org.eclipse.cdt.arduino.core.internal.ArduinoScannerInfoProvider">
</provider>
</extension>
<extension
point="org.eclipse.core.runtime.adapters">
<factory
adaptableType="org.eclipse.core.resources.IBuildConfiguration"
class="org.eclipse.cdt.arduino.core.internal.build.ArduinoBuildConfiguration$Factory">
<adapter
type="org.eclipse.cdt.arduino.core.internal.build.ArduinoBuildConfiguration">
</adapter>
</factory>
</extension>
<extension
point="org.eclipse.launchbar.core.launchTargetTypes">
<launchTargetType
@ -116,4 +85,19 @@
provider="org.eclipse.cdt.arduino.core.internal.remote.ArduinoLaunchTargetProvider">
</launchTargetType>
</extension>
<extension
point="org.eclipse.cdt.core.buildConfigProvider">
<provider
class="org.eclipse.cdt.arduino.core.internal.build.ArduinoBuildConfigurationProvider"
id="org.eclipse.cdt.arduino.core.provider"
natureId="org.eclipse.cdt.arduino.core.arduinoNature">
</provider>
</extension>
<extension
point="org.eclipse.cdt.core.toolChainProvider">
<provider
class="org.eclipse.cdt.arduino.core.internal.build.ArduinoToolChainProvider"
id="org.eclipse.cdt.arduino.core.toolChainProvider">
</provider>
</extension>
</plugin>

View file

@ -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$
}
}

View file

@ -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<String, Object> 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<String, Object> model, IProgressMonitor monitor) throws CoreException {
super.generate(model, monitor);
IProject project = getProject();
CoreModel.getDefault().create(project).setRawPathEntries(new IPathEntry[] {
CoreModel.newSourceEntry(project.getFullPath())
}, monitor);
}
}

View file

@ -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) {
}
}

View file

@ -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
}
}

View file

@ -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<ArduinoLibrary> getLibraries(IProject project) throws CoreException {
@ -218,8 +219,8 @@ public class ArduinoManager {
Set<String> 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<ArduinoLibrary> 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();

View file

@ -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<IBuildConfiguration, ArduinoBuildConfiguration> 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> T getAdapter(Object adaptableObject, Class<T> 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<ArduinoBoard> boards = manager.getInstalledBoards();
if (!boards.isEmpty()) {
b = boards.get(0);
}
}
}
board = b;
// Not found, need to create one
Set<String> 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> T getAdapter(Class<T> 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<ArduinoBoard> 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<String, Object> getBuildModel() throws CoreException {
IProject project = getProject();
ArduinoBoard board = getBoard();
ArduinoPlatform platform = board.getPlatform();
IFile makeFile = getMakeFile();
// The board id
Map<String, Object> 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<String, Object> 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<String, String> 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<Path> includePath = new ArrayList<>();
includePath.addAll(platform.getIncludePath());
Collection<ArduinoLibrary> 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<ArduinoLibrary> 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<String, String> symbols = new HashMap<>();
List<String> 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<String, String> 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
}
}

View file

@ -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<ArduinoBoard> 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;
}
}

View file

@ -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<String, String> 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));
}
}
}

View file

@ -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;
}
}

View file

@ -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);
}
}

View file

@ -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
* <code>Pattern.compile(String regex, int flags)</code>
*
* @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 <code>null</code>. 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 <code>null</code>
*/
public String getLineQualifier() {
return lineQualifier;
}
}

View file

@ -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;
}

View file

@ -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;
}
}

View file

@ -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;
}
}

View file

@ -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}

View file

@ -0,0 +1,4 @@
<templateManifest>
<file src="/templates/cppsketch/arduino.cpp"
dest="/${projectName}/${projectName}.cpp"/>
</templateManifest>

View file

@ -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

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

View file

@ -112,8 +112,7 @@
<view
id="org.eclipse.remote.ui.view.connections"
minimized="false"
ratio="0.75"
relationship="bottom"
relationship="stack"
relative="org.eclipse.ui.navigator.ProjectExplorer">
</view>
</perspectiveExtension>
@ -149,4 +148,23 @@
name="Arduino">
</wizard>
</extension>
<extension
point="org.eclipse.tools.templates.ui.templates">
<tag
id="org.eclipse.cdt.arduino.ui.tag"
label="Arduino">
</tag>
<template
icon="icons/arduino48.png"
id="org.eclipse.cdt.arduino.ui.template.sketch"
label="Arduino C++ Sketch"
wizard="org.eclipse.cdt.arduino.ui.internal.project.NewArduinoCPPSketchWizard">
<tagReference
id="org.eclipse.cdt.arduino.ui.tag">
</tagReference>
<description>
A single C++ file with empty setup() and loop() functions.
</description>
</template>
</extension>
</plugin>

View file

@ -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<ArduinoPatternMatchListener> 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);
}
}

View file

@ -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);
}
}
}

View file

@ -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);
}
}
}

View file

@ -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();
}
}

View file

@ -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;
}
}

View file

@ -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;
}