1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-07-24 17:35:35 +02:00

Starting to put Qt onto the new build system and launch.

Change-Id: I3e65f5d69bfb35d16b2d1135f99517c7a2b2c437
This commit is contained in:
Doug Schaefer 2015-09-25 17:01:37 -04:00 committed by Gerrit Code Review @ Eclipse.org
parent 7ba4959cf4
commit 64bf3c4f69
35 changed files with 1362 additions and 287 deletions

View file

@ -0,0 +1,17 @@
package org.eclipse.cdt.core.internal.build;
import java.io.IOException;
import org.eclipse.cdt.core.build.gcc.GCCToolChainFactory;
import org.junit.Test;
public class GCCTests {
@Test
public void tryGCCDiscovery() throws IOException {
long start = System.currentTimeMillis();
new GCCToolChainFactory().discover();
System.out.println("Time: " + (System.currentTimeMillis() - start));
}
}

View file

@ -1,12 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8"/>
<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
<classpathentry kind="src" path="model"/>
<classpathentry kind="src" path="browser"/>
<classpathentry kind="src" path="src"/>
<classpathentry kind="src" path="utils"/>
<classpathentry kind="src" path="parser"/>
<classpathentry kind="src" path="templateengine"/>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.7"/>
<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
<classpathentry kind="output" path="bin"/>
</classpath>

View file

@ -1,8 +1,8 @@
eclipse.preferences.version=1
org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.7
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8
org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
org.eclipse.jdt.core.compiler.compliance=1.7
org.eclipse.jdt.core.compiler.compliance=1.8
org.eclipse.jdt.core.compiler.debug.lineNumber=generate
org.eclipse.jdt.core.compiler.debug.localVariable=generate
org.eclipse.jdt.core.compiler.debug.sourceFile=generate
@ -77,7 +77,7 @@ org.eclipse.jdt.core.compiler.problem.unusedParameterWhenOverridingConcrete=disa
org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=warning
org.eclipse.jdt.core.compiler.problem.unusedWarningToken=warning
org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning
org.eclipse.jdt.core.compiler.source=1.7
org.eclipse.jdt.core.compiler.source=1.8
org.eclipse.jdt.core.formatter.align_type_members_on_columns=false
org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression=16
org.eclipse.jdt.core.formatter.alignment_for_arguments_in_annotation=0

View file

@ -9,6 +9,7 @@ Bundle-Localization: plugin
Export-Package: org.eclipse.cdt.core,
org.eclipse.cdt.core.browser,
org.eclipse.cdt.core.build,
org.eclipse.cdt.core.build.gcc,
org.eclipse.cdt.core.cdtvariables,
org.eclipse.cdt.core.dom,
org.eclipse.cdt.core.dom.ast,
@ -130,4 +131,4 @@ Require-Bundle: org.eclipse.cdt.core.native;bundle-version="[5.7.0,6.0.0)";visib
com.ibm.icu;bundle-version="4.4.2",
com.google.gson;bundle-version="2.2.4"
Bundle-ActivationPolicy: lazy
Bundle-RequiredExecutionEnvironment: JavaSE-1.7
Bundle-RequiredExecutionEnvironment: JavaSE-1.8

View file

@ -1,5 +1,5 @@
###############################################################################
# Copyright (c) 2003, 2014 IBM Corporation and others.
# Copyright (c) 2003, 2015 IBM Corporation 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
@ -30,7 +30,3 @@ source.. = src/,\
browser/,\
templateengine/,\
utils/
jre.compilation.profile=JavaSE-1.7
javacSource=1.7
javacTarget=1.7

View file

@ -683,7 +683,7 @@
<extension-point id="LanguageSettingsProvider" name="%LanguageSettingsProvider.name" schema="schema/LanguageSettingsProvider.exsd"/>
<extension-point id="UNCPathConverter" name="%uncPathConverter.name" schema="schema/UNCPathConverter.exsd"/>
<extension-point id="ProblemMarkerFilter" name="%problemMarkerFilter.name" schema="schema/ProblemMarkerFilter.exsd"/>
<extension-point id="ToolChain" name="ToolChain" schema="schema/ToolChain.exsd"/>
<extension-point id="ToolChainFactory" name="Tool Chain Factory" schema="schema/ToolChainFactory.exsd"/>
<extension
point="org.eclipse.cdt.core.templateProcessTypes">
@ -858,20 +858,10 @@
</filterMatcher>
</extension>
<extension
point="org.eclipse.cdt.core.ToolChain">
<toolChain
adaptor="org.eclipse.cdt.core.build.GCCToolChain"
id="org.eclipse.cdt.core.gcc">
</toolChain>
</extension>
<extension
point="org.eclipse.core.runtime.adapters">
point="org.eclipse.cdt.core.ToolChainFactory">
<factory
adaptableType="org.eclipse.cdt.core.build.CBuildConfiguration"
class="org.eclipse.cdt.core.build.GCCToolChain$Factory">
<adapter
type="org.eclipse.cdt.core.build.GCCToolChain">
</adapter>
class="org.eclipse.cdt.core.build.gcc.GCCToolChainFactory"
family="GCC">
</factory>
</extension>

View file

@ -3,7 +3,7 @@
<schema targetNamespace="org.eclipse.cdt.core" xmlns="http://www.w3.org/2001/XMLSchema">
<annotation>
<appInfo>
<meta.schema plugin="org.eclipse.cdt.core" id="ToolChain" name="ToolChain"/>
<meta.schema plugin="org.eclipse.cdt.core" id="ToolChainFactory" name="Tool Chain Factory"/>
</appInfo>
<documentation>
[Enter description of this extension point.]
@ -18,7 +18,7 @@
</annotation>
<complexType>
<sequence minOccurs="1" maxOccurs="unbounded">
<element ref="toolChain"/>
<element ref="factory"/>
</sequence>
<attribute name="point" type="string" use="required">
<annotation>
@ -47,27 +47,22 @@
</complexType>
</element>
<element name="toolChain">
<annotation>
<documentation>
A toolchain that implements the CToolChain interface and identified with the id attribute.
</documentation>
</annotation>
<element name="factory">
<complexType>
<attribute name="id" type="string" use="required">
<attribute name="family" type="string" use="required">
<annotation>
<documentation>
id for the toolchain.
</documentation>
</annotation>
</attribute>
<attribute name="adaptor" type="string" use="required">
<attribute name="class" type="string" use="required">
<annotation>
<documentation>
The adaptor class for the toolchain. This is passed to getAdaptor on the CBuildConfiguration object.
</documentation>
<appInfo>
<meta.attribute kind="java" basedOn="org.eclipse.cdt.core.build.CToolChain:"/>
<meta.attribute kind="java" basedOn=":org.eclipse.cdt.core.build.IToolChainFactory"/>
</appInfo>
</annotation>
</attribute>

View file

@ -8,7 +8,11 @@
package org.eclipse.cdt.core.build;
import org.eclipse.cdt.core.CCorePlugin;
import org.eclipse.cdt.core.model.ILanguage;
import org.eclipse.cdt.core.parser.ExtendedScannerInfo;
import org.eclipse.cdt.core.parser.IScannerInfo;
import org.eclipse.cdt.internal.core.build.ScannerInfoData;
import org.eclipse.cdt.internal.core.build.ToolChainScannerInfo;
import org.eclipse.core.resources.IBuildConfiguration;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IProjectDescription;
@ -39,6 +43,7 @@ public abstract class CBuildConfiguration extends PlatformObject {
private final IBuildConfiguration config;
private CToolChain toolChain;
private ScannerInfoData scannerInfoData;
protected CBuildConfiguration(IBuildConfiguration config) {
this.config = config;
@ -97,23 +102,17 @@ public abstract class CBuildConfiguration extends PlatformObject {
return null;
}
public synchronized void setToolChain(String id) throws CoreException {
CToolChain newtc = getToolChain(id);
if (newtc == null) {
throw new CoreException(
new Status(IStatus.ERROR, CCorePlugin.PLUGIN_ID, "unknown toolchain: " + id)); //$NON-NLS-1$
}
public synchronized void setToolChain(CToolChain toolChain) throws CoreException {
this.toolChain = toolChain;
IEclipsePreferences settings = getSettings();
settings.put(TOOLCHAIN, id);
settings.put(TOOLCHAIN, toolChain.getId());
try {
settings.flush();
} catch (BackingStoreException e) {
throw new CoreException(
new Status(IStatus.ERROR, CCorePlugin.PLUGIN_ID, "saving toolchain id", e)); //$NON-NLS-1$
}
toolChain = newtc;
}
public CToolChain getToolChain() throws CoreException {
@ -130,12 +129,26 @@ public abstract class CBuildConfiguration extends PlatformObject {
}
public IScannerInfo getScannerInfo(IResource resource) throws CoreException {
// By default, get it from the toolchain.
CToolChain toolChain = getToolChain();
return toolChain != null ? toolChain.getScannerInfo(resource) : null;
return getScannerInfoData().getScannerInfo(resource);
}
public void putScannerInfo(ILanguage language, ExtendedScannerInfo info) {
getScannerInfoData().putScannerInfo(language, info);
}
public void putScannerInfo(IResource resource, ToolChainScannerInfo info) {
getScannerInfoData().putScannerInfo(resource, info);
}
private ScannerInfoData getScannerInfoData() {
if (scannerInfoData == null) {
scannerInfoData = ScannerInfoData.load(this);
}
return scannerInfoData;
}
public void clearScannerInfo() throws CoreException {
scannerInfoData = null;
}
public CConsoleParser[] getConsoleParsers() throws CoreException {

View file

@ -10,14 +10,12 @@ package org.eclipse.cdt.core.build;
import java.util.List;
import java.util.Map;
import org.eclipse.cdt.core.model.ILanguage;
import org.eclipse.cdt.core.parser.IScannerInfo;
import org.eclipse.cdt.internal.core.build.ScannerInfoData;
import org.eclipse.cdt.internal.core.build.ToolChainScannerInfo;
import org.eclipse.cdt.core.parser.ExtendedScannerInfo;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IFolder;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.PlatformObject;
import org.osgi.service.prefs.Preferences;
/**
* Root class for CDT toolchains.
@ -26,12 +24,38 @@ import org.eclipse.core.runtime.PlatformObject;
*/
public abstract class CToolChain extends PlatformObject {
private final CBuildConfiguration config;
public static final String FAMILY = "family"; //$NON-NLS-1$
private static final String NAME = "name"; //$NON-NLS-1$
private ScannerInfoData scannerInfo;
private String id;
private String name;
protected CToolChain(CBuildConfiguration config) {
this.config = config;
protected CToolChain(String id, Preferences settings) {
this.id = id;
this.name = settings.get(NAME, "<Unknown>"); //$NON-NLS-1$
}
protected CToolChain(String name) {
this.name = name;
}
public abstract String getFamily();
public String getId() {
return id;
}
void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void save(Preferences settings) {
settings.put(FAMILY, getFamily());
settings.put(NAME, name);
}
public static String[] splitCommand(String command) {
@ -39,8 +63,13 @@ public abstract class CToolChain extends PlatformObject {
return command.replace("\"", "").split("\\s+"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
}
public CBuildConfiguration getBuildConfiguration() {
return config;
public static String[] fixPaths(String[] command) {
for (int i = 0; i < command.length; ++i) {
if (command[i].indexOf('\\') >= 0) {
command[i] = command[i].replace('\\', '/');
}
}
return command;
}
/**
@ -53,71 +82,40 @@ public abstract class CToolChain extends PlatformObject {
}
/**
* Scan the commandLine and save the scanner info for the resource being
* built, or if perProject is true, for all resources in the project. The
* buildFolder to help find the resource is where the command ran.
* Find the file mentioned in the command line.
*
* @param buildFolder
* @param commandLine
* @throws CoreException
* @return the file in the command line or null if can't be found.
*/
public void scanBuildOutput(IFolder buildFolder, String commandLine, boolean perProject)
throws CoreException {
// default, nothing
public IFile getResource(IFolder buildFolder, String[] commandLine) {
// default, not found
return null;
}
protected void putScannerInfo(IResource resource, Map<String, String> definedSymbols,
List<String> includePaths, List<String> macroFiles, List<String> includeFiles,
List<String> localIncludePath) throws CoreException {
if (scannerInfo == null) {
loadScannerInfo();
}
scannerInfo.putScannerInfo(resource, new ToolChainScannerInfo(definedSymbols, includePaths,
macroFiles, includeFiles, localIncludePath));
}
protected void putScannerInfo(ILanguage language, Map<String, String> definedSymbols,
List<String> includePaths, List<String> macroFiles, List<String> includeFiles,
List<String> localIncludePath) throws CoreException {
if (scannerInfo == null) {
loadScannerInfo();
}
scannerInfo.putScannerInfo(language, new ToolChainScannerInfo(definedSymbols, includePaths,
macroFiles, includeFiles, localIncludePath));
}
private void loadScannerInfo() {
if (scannerInfo == null) {
scannerInfo = ScannerInfoData.load(this);
}
public IFile getResource(IFolder buildFolder, String commandLine) {
return getResource(buildFolder, splitCommand(commandLine));
}
/**
* Return the scanner info for the given resource.
* Calculate the scanner info from the given command line
*
* @param resource
* @return scanner info for the resource
* @param buildFolder
* @param commandLine
* @return scanner info, or null if can't be calculated
* @throws CoreException
*/
public IScannerInfo getScannerInfo(IResource resource) throws CoreException {
loadScannerInfo();
return scannerInfo.getScannerInfo(resource);
}
public void clearScannerInfo() throws CoreException {
if (scannerInfo == null) {
scannerInfo = new ScannerInfoData();
scannerInfo.queueSave();
} else {
scannerInfo.clear();
}
public ExtendedScannerInfo getScannerInfo(IFolder buildFolder, List<String> commandLine)
throws CoreException {
// default, null
return null;
}
/**
* Return the console parsers to be used when this toolchain is being used
* for a build.
*
* @return console parsers
* @return console parsers, or null if there aren't any
*/
public CConsoleParser[] getConsoleParsers() {
return null;

View file

@ -0,0 +1,127 @@
/*******************************************************************************
* 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;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import org.eclipse.cdt.core.CCorePlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IConfigurationElement;
import org.eclipse.core.runtime.IExtension;
import org.eclipse.core.runtime.IExtensionPoint;
import org.eclipse.core.runtime.IExtensionRegistry;
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.jobs.Job;
import org.eclipse.core.runtime.preferences.ConfigurationScope;
import org.osgi.service.prefs.BackingStoreException;
import org.osgi.service.prefs.Preferences;
/**
* Manager that manages the list of toolchains available.
*
* @since 5.12
*/
public class CToolChainManager {
private static final String TOOLCHAINS = "toolchains"; //$NON-NLS-1$
public static final CToolChainManager instance = new CToolChainManager();
private Map<String, IConfigurationElement> toolChainFamilies = new HashMap<>();
private Map<String, CToolChain> toolChains = new HashMap<>();
private CToolChainManager() {
new Job("Load toolchains") {
@Override
protected IStatus run(IProgressMonitor monitor) {
try {
// Load up the families
IExtensionRegistry registry = Platform.getExtensionRegistry();
IExtensionPoint point = registry
.getExtensionPoint("org.eclipse.cdt.core.ToolChainFactory"); //$NON-NLS-1$
for (IExtension extension : point.getExtensions()) {
for (IConfigurationElement element : extension.getConfigurationElements()) {
String family = element.getAttribute(CToolChain.FAMILY);
if (family != null) {
toolChainFamilies.put(family, element);
}
}
}
// Load up the toolchains
Preferences toolChainsPref = getToolChainSettings();
for (String toolChainId : toolChainsPref.childrenNames()) {
Preferences toolChainPref = toolChainsPref.node(toolChainId);
String family = toolChainPref.get(CToolChain.FAMILY, ""); //$NON-NLS-1$
if (!family.isEmpty()) {
IConfigurationElement element = toolChainFamilies.get(family);
if (element != null) {
IToolChainFactory factory = (IToolChainFactory) element
.createExecutableExtension("class"); //$NON-NLS-1$
CToolChain toolChain = factory.createToolChain(toolChainId, toolChainPref);
toolChains.put(toolChain.getName(), toolChain);
}
}
}
return Status.OK_STATUS;
} catch (BackingStoreException e) {
return new Status(IStatus.ERROR, CCorePlugin.PLUGIN_ID, "loading toolchains", e);
} catch (CoreException e) {
return e.getStatus();
}
}
}.schedule();
}
private Preferences getToolChainSettings() {
return ConfigurationScope.INSTANCE.getNode(CCorePlugin.PLUGIN_ID).node(TOOLCHAINS);
}
Preferences getSettings(String id) {
return getToolChainSettings().node(id);
}
public Collection<CToolChain> getToolChains() {
return toolChains.values();
}
public void addToolChain(CToolChain toolChain) throws CoreException {
// First find an open id for the toolchain
String id = null;
for (int i = 0; i < toolChains.size(); ++i) {
String istr = String.valueOf(i);
if (toolChains.containsKey(istr)) {
id = istr;
break;
}
}
if (id == null) {
id = String.valueOf(toolChains.size());
}
toolChain.setId(id);
toolChains.put(id, toolChain);
// save
try {
Preferences toolChainsPref = getToolChainSettings();
toolChain.save(toolChainsPref.node(id));
toolChainsPref.flush();
} catch (BackingStoreException e) {
throw new CoreException(
new Status(IStatus.ERROR, CCorePlugin.PLUGIN_ID, "saving toolchain " + id, e));
}
}
}

View file

@ -0,0 +1,22 @@
/*******************************************************************************
* 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;
import org.osgi.service.prefs.Preferences;
/**
* @since 5.12
*/
public interface IToolChainFactory {
CToolChain createToolChain(String id, Preferences settings);
default void discover() {
}
}

View file

@ -5,7 +5,7 @@
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*******************************************************************************/
package org.eclipse.cdt.core.build;
package org.eclipse.cdt.core.build.gcc;
import java.io.BufferedReader;
import java.io.File;
@ -22,19 +22,17 @@ import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.eclipse.cdt.core.CCorePlugin;
import org.eclipse.cdt.core.build.CConsoleParser;
import org.eclipse.cdt.core.build.CToolChain;
import org.eclipse.cdt.core.model.CoreModel;
import org.eclipse.cdt.core.model.ILanguage;
import org.eclipse.cdt.core.model.LanguageManager;
import org.eclipse.cdt.core.parser.ExtendedScannerInfo;
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.runtime.CoreException;
import org.eclipse.core.runtime.IAdapterFactory;
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.osgi.service.prefs.Preferences;
/**
* The GCC toolchain. Placing it in cdt.core for now.
@ -45,68 +43,60 @@ import org.eclipse.core.runtime.content.IContentType;
*/
public class GCCToolChain extends CToolChain {
public static final String ID = "org.eclipse.cdt.core.gcc"; //$NON-NLS-1$
public GCCToolChain(CBuildConfiguration config) {
super(config);
public GCCToolChain(String id, Preferences settings) {
super(id, settings);
}
private static Map<CBuildConfiguration, GCCToolChain> cache = new HashMap<>();
public static class Factory implements IAdapterFactory {
@SuppressWarnings("unchecked")
@Override
public <T> T getAdapter(Object adaptableObject, Class<T> adapterType) {
if (adapterType.equals(GCCToolChain.class) && adaptableObject instanceof CBuildConfiguration) {
CBuildConfiguration config = (CBuildConfiguration) adaptableObject;
GCCToolChain toolChain = cache.get(config);
if (toolChain == null) {
toolChain = new GCCToolChain(config);
cache.put(config, toolChain);
}
return (T) toolChain;
}
return null;
}
@Override
public Class<?>[] getAdapterList() {
return new Class<?>[] { GCCToolChain.class };
}
public GCCToolChain(String name) {
super(name);
}
@Override
public void scanBuildOutput(IFolder buildFolder, String commandLine, boolean perProject)
throws CoreException {
try {
if (Platform.getOS().equals(Platform.OS_WIN32)) {
// Need to flip over the slashes on Windows
commandLine = commandLine.replace('\\', '/');
public String getFamily() {
return "GCC"; //$NON-NLS-1$
}
@Override
public IFile getResource(IFolder buildFolder, String[] commandLine) {
for (String arg : commandLine) {
if (!arg.startsWith("-")) { //$NON-NLS-1$
// TODO optimize by dealing with multi arg options like -o
IFile file = buildFolder.getFile(arg);
if (file.exists() && CoreModel.isTranslationUnit(file)) {
return file;
}
}
String[] command = splitCommand(commandLine);
}
return null;
}
@Override
public ExtendedScannerInfo getScannerInfo(IFolder buildFolder, List<String> cmd) throws CoreException {
try {
String[] commandLine = cmd.toArray(new String[cmd.size()]);
// Change output to stdout
for (int i = 0; i < command.length - 1; ++i) {
if (command[i].equals("-o")) { //$NON-NLS-1$
command[i + 1] = "-"; //$NON-NLS-1$
for (int i = 0; i < commandLine.length - 1; ++i) {
if (commandLine[i].equals("-o")) { //$NON-NLS-1$
commandLine[i + 1] = "-"; //$NON-NLS-1$
break;
}
}
// Change source file to a tmp file (needs to be empty)
Path tmpFile = null;
IFile file = null;
for (int i = 1; i < command.length; ++i) {
if (!command[i].startsWith("-")) { //$NON-NLS-1$
for (int i = 1; i < commandLine.length; ++i) {
if (!commandLine[i].startsWith("-")) { //$NON-NLS-1$
// TODO optimize by dealing with multi arg options like -o
IFile f = buildFolder.getFile(command[i]);
if (f.exists() && CoreModel.isTranslationUnit(f)) {
IFile file = buildFolder.getFile(commandLine[i]);
if (file.exists() && CoreModel.isTranslationUnit(file)) {
// replace it with a temp file
Path parentPath = new File(((IFolder) f.getParent()).getLocationURI()).toPath();
Path parentPath = new File(((IFolder) file.getParent()).getLocationURI()).toPath();
int n = 0;
while (true) {
tmpFile = parentPath.resolve(".sc" + n + "." + f.getFileExtension()); //$NON-NLS-1$ //$NON-NLS-2$
command[i] = tmpFile.toString();
tmpFile = parentPath.resolve(".sc" + n + "." + file.getFileExtension()); //$NON-NLS-1$ //$NON-NLS-2$
commandLine[i] = tmpFile.toString();
try {
Files.createFile(tmpFile);
break;
@ -115,26 +105,20 @@ public class GCCToolChain extends CToolChain {
++n;
}
}
file = f;
break;
}
}
}
if (file == null) {
// can't do much without the source file
CCorePlugin.log("No source file for scanner discovery"); //$NON-NLS-1$
return;
}
// Add in the magic potion: -E -P -v -dD
String[] fullCmd = new String[command.length + 4];
fullCmd[0] = command[0];
String[] fullCmd = new String[commandLine.length + 4];
fullCmd[0] = commandLine[0];
fullCmd[1] = "-E"; //$NON-NLS-1$
fullCmd[2] = "-P"; //$NON-NLS-1$
fullCmd[3] = "-v"; //$NON-NLS-1$
fullCmd[4] = "-dD"; //$NON-NLS-1$
System.arraycopy(command, 1, fullCmd, 5, command.length - 1);
System.arraycopy(commandLine, 1, fullCmd, 5, commandLine.length - 1);
fixPaths(fullCmd);
File buildDir = new File(buildFolder.getLocationURI());
Files.createDirectories(buildDir.toPath());
@ -170,23 +154,9 @@ public class GCCToolChain extends CToolChain {
}
}
if (perProject) {
IProject project = buildFolder.getProject();
IContentType contentType = CCorePlugin.getContentType(project, file.getName());
if (contentType != null) {
ILanguage language = LanguageManager.getInstance().getLanguage(contentType, project);
putScannerInfo(language, symbols, includePath, null, null, null);
}
} else {
putScannerInfo(file, symbols, includePath, null, null, null);
}
if (tmpFile != null) {
Files.delete(tmpFile);
}
return new ExtendedScannerInfo(symbols, includePath.toArray(new String[includePath.size()]));
} catch (IOException e) {
throw new CoreException(
new Status(IStatus.ERROR, CCorePlugin.PLUGIN_ID, "Scanning build output", e)); //$NON-NLS-1$
throw new CoreException(new Status(IStatus.ERROR, CCorePlugin.PLUGIN_ID, "scanner info", e)); //$NON-NLS-1$
}
}

View file

@ -0,0 +1,121 @@
/*******************************************************************************
* 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.gcc;
import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.eclipse.cdt.core.build.CToolChain;
import org.eclipse.cdt.core.build.IToolChainFactory;
import org.osgi.service.prefs.Preferences;
/**
* @since 5.12
*/
public class GCCToolChainFactory implements IToolChainFactory {
private static Pattern gccPattern = Pattern.compile("(.*-)?(gcc|g\\+\\+|clang|clang\\+\\+)(-[0-9].*)?"); //$NON-NLS-1$
/**
* Discover gcc installs that exist on the path.
*/
@Override
public void discover() {
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);
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()) {
System.out.println(entry.getKey());
for (String command : entry.getValue()) {
System.out.println("\t" + command);
}
}
}
}
private static Pattern versionPattern = Pattern.compile(".*(gcc|LLVM) version .*"); //$NON-NLS-1$
private static Pattern targetPattern = Pattern.compile("Target: (.*)"); //$NON-NLS-1$
private String getVersion(String command) {
try {
Process proc = new ProcessBuilder(new String[] { command, "-v" }).redirectErrorStream(true) //$NON-NLS-1$
.start();
String version = null;
String target = null;
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;
}
}
}
if (version != null) {
if (target != null) {
return version + " " + target; // $NON-NLS-1$
} else {
return version;
}
} else {
return null;
}
} catch (IOException e) {
return null;
}
}
@Override
public CToolChain createToolChain(String id, Preferences settings) {
return new GCCToolChain(id, settings);
}
}

View file

@ -21,9 +21,9 @@ import java.util.Set;
import org.eclipse.cdt.core.CCorePlugin;
import org.eclipse.cdt.core.build.CBuildConfiguration;
import org.eclipse.cdt.core.build.CToolChain;
import org.eclipse.cdt.core.model.ILanguage;
import org.eclipse.cdt.core.model.LanguageManager;
import org.eclipse.cdt.core.parser.ExtendedScannerInfo;
import org.eclipse.cdt.core.parser.IScannerInfo;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
@ -33,6 +33,10 @@ import org.eclipse.core.runtime.content.IContentType;
import com.google.gson.Gson;
/**
* Class representing scanner info data for a project as stored in the metadata
* area.
*/
public class ScannerInfoData {
private Set<ToolChainScannerInfo> perResourceInfo;
@ -117,17 +121,16 @@ public class ScannerInfoData {
queueSave();
}
public void putScannerInfo(ILanguage language, ToolChainScannerInfo info) {
public void putScannerInfo(ILanguage language, ExtendedScannerInfo info) {
if (perLanguageInfo == null) {
perLanguageInfo = new HashMap<>();
}
perLanguageInfo.put(language.getId(), info);
perLanguageInfo.put(language.getId(), new ToolChainScannerInfo(info));
queueSave();
}
public static ScannerInfoData load(CToolChain toolChain) {
public static ScannerInfoData load(CBuildConfiguration config) {
IPath stateLoc = Platform.getStateLocation(CCorePlugin.getDefault().getBundle());
CBuildConfiguration config = toolChain.getBuildConfiguration();
IPath scannerInfoPath = stateLoc.append(config.getProject().getName())
.append(config.getName() + ".scInfo"); //$NON-NLS-1$
File scannerInfoFile = scannerInfoPath.toFile();

View file

@ -10,7 +10,6 @@ package org.eclipse.cdt.internal.core.build;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
@ -20,31 +19,27 @@ import org.eclipse.core.resources.IResource;
public class ToolChainScannerInfo {
private Map<String, String> definedSymbols;
private List<String> includePaths;
private List<String> macroFiles;
private List<String> includeFiles;
private List<String> localIncludePath;
private String[] includePaths;
private String[] macroFiles;
private String[] includeFiles;
private String[] localIncludePath;
private Set<String> resourcePaths;
private transient IScannerInfo scannerInfo;
public ToolChainScannerInfo(Map<String, String> definedSymbols, List<String> includePaths,
List<String> macroFiles, List<String> includeFiles, List<String> localIncludePath) {
this.definedSymbols = definedSymbols;
this.includePaths = includePaths;
this.macroFiles = macroFiles;
this.includeFiles = includeFiles;
this.localIncludePath = localIncludePath;
public ToolChainScannerInfo(ExtendedScannerInfo scannerInfo) {
this.scannerInfo = scannerInfo;
this.definedSymbols = scannerInfo.getDefinedSymbols();
this.includePaths = scannerInfo.getIncludePaths();
this.macroFiles = scannerInfo.getMacroFiles();
this.includeFiles = scannerInfo.getIncludeFiles();
this.localIncludePath = scannerInfo.getLocalIncludePath();
}
public IScannerInfo getScannerInfo() {
if (scannerInfo == null) {
scannerInfo = new ExtendedScannerInfo(definedSymbols,
includePaths != null ? includePaths.toArray(new String[includePaths.size()]) : null,
macroFiles != null ? macroFiles.toArray(new String[includePaths.size()]) : null,
includeFiles != null ? includeFiles.toArray(new String[includePaths.size()]) : null,
localIncludePath != null ? localIncludePath.toArray(new String[includePaths.size()])
: null);
scannerInfo = new ExtendedScannerInfo(definedSymbols, includePaths, macroFiles, includeFiles,
localIncludePath);
}
return scannerInfo;
}

View file

@ -1,8 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry exported="true" kind="lib" path="libs/freemarker-2.3.22.jar"/>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.7"/>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8"/>
<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
<classpathentry kind="src" path="src"/>
<classpathentry exported="true" kind="lib" path="libs/freemarker-2.3.22.jar"/>
<classpathentry kind="output" path="bin"/>
</classpath>

View file

@ -1,7 +1,7 @@
eclipse.preferences.version=1
org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.7
org.eclipse.jdt.core.compiler.compliance=1.7
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8
org.eclipse.jdt.core.compiler.compliance=1.8
org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
org.eclipse.jdt.core.compiler.source=1.7
org.eclipse.jdt.core.compiler.source=1.8

View file

@ -11,8 +11,12 @@ Require-Bundle: org.eclipse.core.runtime,
org.eclipse.cdt.core,
org.eclipse.cdt.codan.core,
org.eclipse.cdt.codan.core.cxx,
org.eclipse.core.filesystem
Bundle-RequiredExecutionEnvironment: JavaSE-1.7
org.eclipse.core.filesystem,
org.eclipse.launchbar.core;bundle-version="1.0.1",
org.eclipse.remote.core;bundle-version="2.0.0",
org.eclipse.debug.core;bundle-version="3.10.0",
org.eclipse.cdt.debug.core
Bundle-RequiredExecutionEnvironment: JavaSE-1.8
Bundle-ActivationPolicy: lazy
Bundle-Localization: plugin
Export-Package: org.eclipse.cdt.internal.qt.core;x-friends:="org.eclipse.cdt.qt.ui,org.eclipse.cdt.qt.tests",

View file

@ -5,7 +5,6 @@ bin.includes = META-INF/,\
plugin.xml,\
templates/,\
about.html,\
plugin.properties,\
libs/freemarker-2.3.22.jar
plugin.properties
src.includes = about.html,\
schema/

View file

@ -134,4 +134,54 @@
class="org.eclipse.cdt.internal.qt.core.build.QtBuilder">
</run></builder>
</extension>
<extension
point="org.eclipse.launchbar.core.launchBarContributions">
<descriptorType
class="org.eclipse.cdt.internal.qt.core.launch.QtLaunchDescriptorType"
id="org.eclipse.cdt.qt.core.launchDescriptorType"
priority="10">
<enablement>
<instanceof
value="org.eclipse.core.resources.IProject">
</instanceof>
<test
forcePluginActivation="true"
property="org.eclipse.core.resources.projectNature"
value="org.eclipse.cdt.qt.core.qtNature">
</test>
</enablement>
</descriptorType>
<configProvider
class="org.eclipse.cdt.internal.qt.core.launch.QtLocalLaunchConfigProvider"
descriptorType="org.eclipse.cdt.qt.core.launchDescriptorType"
priority="10">
</configProvider>
</extension>
<extension
point="org.eclipse.cdt.core.ScannerInfoProvider2">
<provider
builder="org.eclipse.cdt.qt.core.qtBuilder"
class="org.eclipse.cdt.internal.qt.core.build.QtScannerInfoProvider">
</provider>
</extension>
<extension
point="org.eclipse.debug.core.launchConfigurationTypes">
<launchConfigurationType
delegate="org.eclipse.cdt.internal.qt.core.launch.QtLocalRunLaunchConfigDelegate"
id="org.eclipse.cdt.qt.core.launchConfigurationType"
modes="run"
name="Qt Local Application"
public="true">
</launchConfigurationType>
</extension>
<extension
point="org.eclipse.core.runtime.adapters">
<factory
adaptableType="org.eclipse.core.resources.IBuildConfiguration"
class="org.eclipse.cdt.internal.qt.core.build.QtBuildConfiguration$Factory">
<adapter
type="org.eclipse.cdt.internal.qt.core.build.QtBuildConfiguration">
</adapter>
</factory>
</extension>
</plugin>

View file

@ -7,15 +7,40 @@
*******************************************************************************/
package org.eclipse.cdt.internal.qt.core.build;
import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.eclipse.cdt.core.CCorePlugin;
import org.eclipse.cdt.core.build.CBuildConfiguration;
import org.eclipse.cdt.core.model.ILanguage;
import org.eclipse.cdt.core.model.LanguageManager;
import org.eclipse.cdt.core.parser.IScannerInfo;
import org.eclipse.cdt.internal.qt.core.QtPlugin;
import org.eclipse.core.resources.IBuildConfiguration;
import org.eclipse.core.resources.IFolder;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IProjectDescription;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IAdapterFactory;
import org.eclipse.core.runtime.IProgressMonitor;
public class QtBuildConfiguration extends CBuildConfiguration {
private QtInstall qtInstall;
private String launchMode;
private Map<String, String> properties;
public QtBuildConfiguration(IBuildConfiguration config) {
super(config);
}
@ -46,4 +71,157 @@ public class QtBuildConfiguration extends CBuildConfiguration {
}
}
public static QtBuildConfiguration getConfig(IProject project, String os, String arch, String launchMode,
IProgressMonitor monitor) throws CoreException {
// return it if it exists already
for (IBuildConfiguration config : project.getBuildConfigs()) {
QtBuildConfiguration qtConfig = config.getAdapter(QtBuildConfiguration.class);
QtInstall qtInstall = qtConfig.getQtInstall();
if (qtInstall != null && qtInstall.supports(os, arch) && launchMode.equals(qtConfig.getLaunchMode())) {
return qtConfig;
}
}
// Nope, create it
for (QtInstall qtInstall : QtInstallManager.instance.getInstalls()) {
if (qtInstall.supports(os, arch)) {
Set<String> configNames = new HashSet<>();
for (IBuildConfiguration config : project.getBuildConfigs()) {
configNames.add(config.getName());
}
String baseName = qtInstall.getSpec() + ":" + launchMode; //$NON-NLS-1$
String newName = baseName;
int n = 0;
while (configNames.contains(newName)) {
newName = baseName + (++n);
}
configNames.add(newName);
IProjectDescription projectDesc = project.getDescription();
projectDesc.setBuildConfigs(configNames.toArray(new String[configNames.size()]));
project.setDescription(projectDesc, monitor);
QtBuildConfiguration qtConfig = project.getBuildConfig(newName).getAdapter(QtBuildConfiguration.class);
qtConfig.setup(qtInstall, launchMode);
return qtConfig;
}
}
return null;
}
public QtInstall getQtInstall() {
if (qtInstall == null) {
// TODO set based on settings
}
return qtInstall;
}
private String getLaunchMode() {
if (launchMode != null) {
// TODO set based on settings
}
return launchMode;
}
private void setup(QtInstall qtInstall, String launchMode) {
this.qtInstall = qtInstall;
this.launchMode = launchMode;
// TODO save settings
}
public String getQmakeCommand() {
return qtInstall.getQmakePath().toString();
}
public String getQmakeConfig() {
switch (launchMode) {
case "run": //$NON-NLS-1$
return "CONFIG+=release"; //$NON-NLS-1$
case "debug": //$NON-NLS-1$
return "CONFIG+=debug"; //$NON-NLS-1$
default:
// TODO probably need an extension point for guidance
return null;
}
}
public Path getProjectFile() {
File projectDir = getProject().getLocation().toFile();
File[] proFiles = projectDir.listFiles((dir, name) -> name.endsWith(".pro")); //$NON-NLS-1$
if (proFiles.length > 0) {
// TODO what if there are more than one.
return proFiles[0].toPath();
} else {
return null;
}
}
public IFolder getBuildFolder() {
return getProject().getFolder("build").getFolder(getBuildConfiguration().getName()); //$NON-NLS-1$
}
public Path getBuildDirectory() {
return getBuildFolder().getLocation().toFile().toPath();
}
public String getProperty(String key) {
if (properties == null) {
List<String> cmd = new ArrayList<>();
cmd.add(getQmakeCommand());
cmd.add("-E"); //$NON-NLS-1$
String config = getQmakeConfig();
if (config != null) {
cmd.add(config);
}
cmd.add(getProjectFile().toString());
try {
Process proc = new ProcessBuilder(cmd).directory(getBuildDirectory().toFile()).start();
try (BufferedReader reader = new BufferedReader(new InputStreamReader(proc.getInputStream()))) {
properties = new HashMap<>();
for (String line = reader.readLine(); line != null; line = reader.readLine()) {
if (line.contains("=")) { //$NON-NLS-1$
String[] parts = line.split("="); //$NON-NLS-1$
if (parts.length == 2) {
properties.put(parts[0].trim(), parts[1].trim());
}
}
}
}
} catch (IOException e) {
QtPlugin.log(e);
}
}
return properties != null ? properties.get(key) : null;
}
@Override
public IScannerInfo getScannerInfo(IResource resource) throws CoreException {
IScannerInfo info = super.getScannerInfo(resource);
if (info == null) {
List<String> cmd = new ArrayList<>();
cmd.add(getProperty("QMAKE_CXX")); //$NON-NLS-1$
cmd.addAll(Arrays.asList(getProperty("QMAKE_CXXFLAGS").split(" "))); //$NON-NLS-1$ //$NON-NLS-2$
for (String include : getProperty("INCLUDEPATH").split(" ")) { //$NON-NLS-1$ //$NON-NLS-2$
cmd.add("-I"); //$NON-NLS-1$
cmd.add(include);
}
cmd.add("-o"); //$NON-NLS-1$
cmd.add("-"); //$NON-NLS-1$
// TODO need to make sure this path is valid
// The gcc toolchain uses IFile to make sure it exists
cmd.add(resource.getFullPath().toPortableString());
ILanguage language = LanguageManager.getInstance()
.getLanguage(CCorePlugin.getContentType(getProject(), resource.getName()), getProject()); // $NON-NLS-1$
putScannerInfo(language, getToolChain().getScannerInfo(getBuildFolder(), cmd));
}
return info;
}
}

View file

@ -9,10 +9,13 @@ package org.eclipse.cdt.internal.qt.core.build;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import org.eclipse.cdt.core.build.IConsoleService;
import org.eclipse.cdt.internal.qt.core.QtPlugin;
import org.eclipse.core.resources.IContainer;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IFolder;
import org.eclipse.core.resources.IProject;
@ -27,23 +30,30 @@ public class QtBuilder extends IncrementalProjectBuilder {
public static final String ID = QtPlugin.ID + ".qtBuilder"; //$NON-NLS-1$
private static final String qmake = "/Users/dschaefer/Qt/5.5/clang_64/bin/qmake"; //$NON-NLS-1$
@Override
protected IProject[] build(int kind, Map<String, String> args, IProgressMonitor monitor) throws CoreException {
IProject project = getProject();
try {
IConsoleService console = QtPlugin.getService(IConsoleService.class);
QtBuildConfiguration qtConfig = getBuildConfig().getAdapter(QtBuildConfiguration.class);
IFolder buildFolder = project.getFolder("build"); //$NON-NLS-1$
if (!buildFolder.exists()) {
buildFolder.create(IResource.FORCE | IResource.DERIVED, true, monitor);
}
IFolder buildFolder = qtConfig.getBuildFolder();
createFolder(buildFolder, monitor);
IFile makeFile = buildFolder.getFile("Makefile"); //$NON-NLS-1$
if (!makeFile.exists()) {
// Need to run qmake
String[] command = new String[] { qmake, "../main.pro", "CONFIG+=debug" }; //$NON-NLS-1$ //$NON-NLS-2$
List<String> command = new ArrayList<>();
command.add(qtConfig.getQmakeCommand());
String config = qtConfig.getQmakeConfig();
if (config != null) {
command.add(config);
}
IFile projectFile = qtConfig.getProject().getFile("main.pro");
command.add(projectFile.getLocation().toOSString());
Process process = new ProcessBuilder(command).directory(new File(buildFolder.getLocationURI())).start();
StringBuffer msg = new StringBuffer();
for (String arg : command) {
@ -56,6 +66,7 @@ public class QtBuilder extends IncrementalProjectBuilder {
// run make
Process process = new ProcessBuilder("make").directory(new File(buildFolder.getLocationURI())).start(); //$NON-NLS-1$
console.writeOutput("make\n"); //$NON-NLS-1$
console.monitor(process, null, buildFolder);
buildFolder.refreshLocal(IResource.DEPTH_INFINITE, monitor);
@ -65,4 +76,13 @@ public class QtBuilder extends IncrementalProjectBuilder {
}
}
private void createFolder(IFolder folder, IProgressMonitor monitor) throws CoreException {
IContainer parent = folder.getParent();
if (!parent.exists()) {
createFolder((IFolder) parent, monitor);
}
if (!folder.exists()) {
folder.create(IResource.FORCE | IResource.DERIVED, true, monitor);
}
}
}

View file

@ -0,0 +1,60 @@
/*******************************************************************************
* 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.internal.qt.core.build;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.nio.file.Path;
import org.eclipse.cdt.internal.qt.core.QtPlugin;
import org.eclipse.core.runtime.Platform;
public class QtInstall {
private final Path qmakePath;
private String spec;
public QtInstall(Path qmakePath) {
this.qmakePath = qmakePath;
}
public Path getQmakePath() {
return qmakePath;
}
public Path getLibPath() {
return qmakePath.resolve("../lib"); //$NON-NLS-1$
}
public boolean supports(String os, String arch) {
switch (getSpec()) {
case "macx-clang": //$NON-NLS-1$
return Platform.OS_MACOSX.equals(os) && Platform.ARCH_X86_64.equals(arch);
}
return false;
}
public String getSpec() {
if (spec == null) {
try {
Process proc = new ProcessBuilder(getQmakePath().toString(), "-query", "QMAKE_XSPEC").start(); //$NON-NLS-1$ //$NON-NLS-2$
try (BufferedReader reader = new BufferedReader(new InputStreamReader(proc.getInputStream()))) {
String line = reader.readLine();
if (line != null) {
spec = line.trim();
}
}
} catch (IOException e) {
QtPlugin.log(e);
}
}
return spec;
}
}

View file

@ -0,0 +1,39 @@
/*******************************************************************************
* 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.internal.qt.core.build;
import java.io.File;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.List;
public class QtInstallManager {
public static final QtInstallManager instance = new QtInstallManager();
private List<QtInstall> installs;
public List<QtInstall> getInstalls() {
if (installs == null) {
installs = new ArrayList<>();
// TODO hack to get going
File qtDir = new File(System.getProperty("user.home"), "Qt/5.5");
if (qtDir.isDirectory()) {
for (File dir : qtDir.listFiles()) {
Path qmakePath = dir.toPath().resolve("bin/qmake");
if (qmakePath.toFile().canExecute()) {
installs.add(new QtInstall(qmakePath));
}
}
}
}
return installs;
}
}

View file

@ -0,0 +1,42 @@
/*******************************************************************************
* 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.internal.qt.core.build;
import org.eclipse.cdt.core.parser.IScannerInfo;
import org.eclipse.cdt.core.parser.IScannerInfoChangeListener;
import org.eclipse.cdt.core.parser.IScannerInfoProvider;
import org.eclipse.cdt.internal.qt.core.QtPlugin;
import org.eclipse.core.resources.IBuildConfiguration;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.CoreException;
public class QtScannerInfoProvider implements IScannerInfoProvider {
@Override
public IScannerInfo getScannerInformation(IResource resource) {
try {
IProject project = resource.getProject();
IBuildConfiguration config = project.getActiveBuildConfig();
QtBuildConfiguration qtConfig = config.getAdapter(QtBuildConfiguration.class);
return qtConfig.getScannerInfo(resource);
} catch (CoreException e) {
QtPlugin.log(e);
return null;
}
}
@Override
public void subscribe(IResource resource, IScannerInfoChangeListener listener) {
}
@Override
public void unsubscribe(IResource resource, IScannerInfoChangeListener listener) {
}
}

View file

@ -0,0 +1,49 @@
/*******************************************************************************
* 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.internal.qt.core.launch;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.runtime.PlatformObject;
import org.eclipse.launchbar.core.ILaunchDescriptor;
import org.eclipse.launchbar.core.ILaunchDescriptorType;
public class QtLaunchDescriptor extends PlatformObject implements ILaunchDescriptor {
private final QtLaunchDescriptorType type;
private final IProject project;
public QtLaunchDescriptor(QtLaunchDescriptorType type, IProject project) {
this.type = type;
this.project = project;
}
@Override
public String getName() {
return project.getName();
}
@Override
public ILaunchDescriptorType getType() {
return type;
}
public IProject getProject() {
return project;
}
@SuppressWarnings("unchecked")
@Override
public <T> T getAdapter(Class<T> adapter) {
if (adapter.equals(IProject.class)) {
return (T) project;
} else {
return super.getAdapter(adapter);
}
}
}

View file

@ -0,0 +1,41 @@
/*******************************************************************************
* 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.internal.qt.core.launch;
import java.util.HashMap;
import java.util.Map;
import org.eclipse.cdt.internal.qt.core.QtNature;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.launchbar.core.ILaunchDescriptor;
import org.eclipse.launchbar.core.ILaunchDescriptorType;
public class QtLaunchDescriptorType implements ILaunchDescriptorType {
private Map<IProject, QtLaunchDescriptor> descriptors = new HashMap<>();
@Override
public ILaunchDescriptor getDescriptor(Object launchObject) throws CoreException {
// TODO also check to make sure it's an application project and not a library.
// qmake -E will give the TEMPLATE variable
if (launchObject instanceof IProject) {
IProject project = (IProject) launchObject;
if (QtNature.hasNature(project)) {
QtLaunchDescriptor desc = descriptors.get(project);
if (desc == null) {
desc = new QtLaunchDescriptor(this, project);
descriptors.put(project, desc);
}
return desc;
}
}
return null;
}
}

View file

@ -0,0 +1,106 @@
/*******************************************************************************
* 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.internal.qt.core.launch;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.debug.core.DebugPlugin;
import org.eclipse.debug.core.ILaunchConfiguration;
import org.eclipse.debug.core.ILaunchConfigurationType;
import org.eclipse.debug.core.ILaunchConfigurationWorkingCopy;
import org.eclipse.launchbar.core.AbstractLaunchConfigProvider;
import org.eclipse.launchbar.core.ILaunchDescriptor;
import org.eclipse.remote.core.IRemoteConnection;
/**
* Launch config provider for Qt projects running on the Local connection. Simply uses the C++ Application launch config
* type.
*/
public class QtLocalLaunchConfigProvider extends AbstractLaunchConfigProvider {
private static final String localConnectionTypeId = "org.eclipse.remote.LocalServices"; //$NON-NLS-1$
private Map<IProject, ILaunchConfiguration> configs = new HashMap<>();
@Override
public boolean supports(ILaunchDescriptor descriptor, IRemoteConnection target) throws CoreException {
return localConnectionTypeId.equals(target.getConnectionType().getId());
}
@Override
public ILaunchConfigurationType getLaunchConfigurationType(ILaunchDescriptor descriptor, IRemoteConnection target)
throws CoreException {
return DebugPlugin.getDefault().getLaunchManager()
.getLaunchConfigurationType(QtLocalRunLaunchConfigDelegate.TYPE_ID);
}
@Override
public ILaunchConfiguration getLaunchConfiguration(ILaunchDescriptor descriptor, IRemoteConnection target)
throws CoreException {
ILaunchConfiguration config = configs.get(descriptor);
if (config == null) {
config = createLaunchConfiguration(descriptor, target);
configs.put(descriptor.getAdapter(IProject.class), config);
}
return config;
}
@Override
protected void populateLaunchConfiguration(ILaunchDescriptor descriptor, IRemoteConnection target,
ILaunchConfigurationWorkingCopy workingCopy) throws CoreException {
super.populateLaunchConfiguration(descriptor, target, workingCopy);
// Set the project and the connection
QtLaunchDescriptor qtDesc = (QtLaunchDescriptor) descriptor;
workingCopy.setMappedResources(new IResource[] { qtDesc.getProject() });
}
@Override
public boolean launchConfigurationAdded(ILaunchConfiguration configuration) throws CoreException {
if (ownsLaunchConfiguration(configuration)) {
}
return false;
}
@Override
public boolean launchConfigurationRemoved(ILaunchConfiguration configuration) throws CoreException {
for (Entry<IProject, ILaunchConfiguration> entry : configs.entrySet()) {
if (configuration.equals(entry.getValue())) {
configs.remove(entry.getKey());
return true;
}
}
return false;
}
@Override
public boolean launchConfigurationChanged(ILaunchConfiguration configuration) throws CoreException {
// TODO not sure I care
return false;
}
@Override
public void launchDescriptorRemoved(ILaunchDescriptor descriptor) throws CoreException {
IProject project = descriptor.getAdapter(IProject.class);
if (project != null) {
configs.remove(project);
}
}
@Override
public void launchTargetRemoved(IRemoteConnection target) throws CoreException {
// nothing to do since the Local connection can't be removed
}
}

View file

@ -0,0 +1,112 @@
/*******************************************************************************
* 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.internal.qt.core.launch;
import java.io.File;
import java.io.IOException;
import java.nio.file.Path;
import java.util.Map;
import org.eclipse.cdt.internal.qt.core.QtPlugin;
import org.eclipse.cdt.internal.qt.core.build.QtBuildConfiguration;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IFolder;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IProjectDescription;
import org.eclipse.core.runtime.CoreException;
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.jobs.Job;
import org.eclipse.debug.core.DebugPlugin;
import org.eclipse.debug.core.ILaunch;
import org.eclipse.debug.core.ILaunchConfiguration;
import org.eclipse.debug.core.model.LaunchConfigurationDelegate;
public class QtLocalRunLaunchConfigDelegate extends LaunchConfigurationDelegate {
public static final String TYPE_ID = QtPlugin.ID + ".launchConfigurationType"; //$NON-NLS-1$
@Override
public void launch(ILaunchConfiguration configuration, String mode, ILaunch launch, IProgressMonitor monitor)
throws CoreException {
new Job("Running Qt App") {
@Override
protected IStatus run(IProgressMonitor monitor) {
try {
QtBuildConfiguration qtBuildConfig = getQtBuildConfiguration(configuration, mode, monitor);
// get the executable
IFolder buildFolder = qtBuildConfig.getBuildFolder();
// TODO this is mac local specific and really should be in the config
// TODO also need to pull the app name out of the pro file name
IFolder appFolder = buildFolder.getFolder("main.app");
IFolder contentsFolder = appFolder.getFolder("Contents");
IFolder macosFolder = contentsFolder.getFolder("MacOS");
IFile exeFile = macosFolder.getFile("main");
ProcessBuilder builder = new ProcessBuilder(exeFile.getLocation().toFile().getAbsolutePath())
.directory(qtBuildConfig.getProject().getLocation().toFile());
// need to add the Qt libraries to the env
Map<String, String> env = builder.environment();
String libPathEnv = env.get("DYLD_LIBRARY_PATH");
Path libPath = qtBuildConfig.getQtInstall().getLibPath();
if (libPathEnv == null) {
libPathEnv = libPath.toString();
} else {
libPathEnv = libPath.toString() + File.pathSeparator + libPathEnv;
}
env.put("DYLD_LIBRARY_PATH", libPathEnv);
Process process = builder.start();
DebugPlugin.newProcess(launch, process, "main.app");
} catch (IOException e) {
return new Status(IStatus.ERROR, QtPlugin.ID, "running", e);
} catch (CoreException e) {
return e.getStatus();
}
return Status.OK_STATUS;
}
}.schedule();
}
@Override
public boolean buildForLaunch(ILaunchConfiguration configuration, String mode, IProgressMonitor monitor)
throws CoreException {
QtBuildConfiguration qtBuildConfig = getQtBuildConfiguration(configuration, mode, monitor);
// Set it as active
IProject project = qtBuildConfig.getProject();
IProjectDescription desc = project.getDescription();
desc.setActiveBuildConfig(qtBuildConfig.getBuildConfiguration().getName());
project.setDescription(desc, monitor);
// And build
return super.buildForLaunch(configuration, mode, monitor);
}
@Override
protected IProject[] getBuildOrder(ILaunchConfiguration configuration, String mode) throws CoreException {
// 1. Extract project from configuration
// TODO dependencies too.
IProject project = configuration.getMappedResources()[0].getProject();
return new IProject[] { project };
}
private QtBuildConfiguration getQtBuildConfiguration(ILaunchConfiguration configuration, String mode,
IProgressMonitor monitor) throws CoreException {
// Find the Qt build config
IProject project = configuration.getMappedResources()[0].getProject();
String os = Platform.getOS();
String arch = Platform.getOSArch();
return QtBuildConfiguration.getConfig(project, os, arch, mode, monitor);
}
}

View file

@ -108,4 +108,11 @@
</adapter>
</factory>
</extension>
<extension
point="org.eclipse.cdt.core.ToolChainFactory">
<factory
class="org.eclipse.cdt.arduino.core.internal.build.ArduinoGCCToolChain$ArduinoFactory"
family="Arduino GCC">
</factory>
</extension>
</plugin>

View file

@ -208,6 +208,23 @@ public class ArduinoManager {
return null;
}
public ArduinoTool getLatestTool(String packageName, String toolName) {
for (PackageIndex index : packageIndices) {
ArduinoPackage pkg = index.getPackage(packageName);
if (pkg != null) {
ArduinoTool latestTool = null;
for (ArduinoTool tool : pkg.getTools()) {
if (tool.getName().equals(toolName)) {
if (latestTool == null || compareVersions(latestTool.getVersion(), tool.getVersion()) > 1) {
latestTool = tool;
}
}
}
}
}
return null;
}
private static final String LIBRARIES = "libraries"; //$NON-NLS-1$
private IEclipsePreferences getSettings(IProject project) {
@ -378,4 +395,49 @@ public class ArduinoManager {
return perms;
}
public static int compareVersions(String version1, String version2) {
if (version1 == null) {
return version2 == null ? 0 : -1;
}
if (version2 == null) {
return 1;
}
String[] v1 = version1.split("\\."); //$NON-NLS-1$
String[] v2 = version2.split("\\."); //$NON-NLS-1$
for (int i = 0; i < Math.max(v1.length, v2.length); ++i) {
if (v1.length <= i) {
return v2.length < i ? 0 : -1;
}
if (v2.length <= i) {
return 1;
}
try {
int vi1 = Integer.parseInt(v1[i]);
int vi2 = Integer.parseInt(v2[i]);
if (vi1 < vi2) {
return -1;
}
if (vi1 > vi2) {
return 1;
}
} catch (NumberFormatException e) {
// not numbers, do string compares
int c = v1[i].compareTo(v2[i]);
if (c < 0) {
return -1;
}
if (c > 0) {
return 1;
}
}
}
return 0;
}
}

View file

@ -72,7 +72,7 @@ public class ArduinoPackage {
Map<String, ArduinoPlatform> platformMap = new HashMap<>();
for (ArduinoPlatform platform : platforms) {
ArduinoPlatform p = platformMap.get(platform.getName());
if (p == null || compareVersions(platform.getVersion(), p.getVersion()) > 0) {
if (p == null || ArduinoManager.compareVersions(platform.getVersion(), p.getVersion()) > 0) {
platformMap.put(platform.getName(), platform);
}
}
@ -84,7 +84,7 @@ public class ArduinoPackage {
for (ArduinoPlatform platform : platforms) {
if (platform.isInstalled()) {
ArduinoPlatform p = platformMap.get(platform.getName());
if (p == null || compareVersions(platform.getVersion(), p.getVersion()) > 0) {
if (p == null || ArduinoManager.compareVersions(platform.getVersion(), p.getVersion()) > 0) {
platformMap.put(platform.getName(), platform);
}
}
@ -92,52 +92,6 @@ public class ArduinoPackage {
return Collections.unmodifiableCollection(platformMap.values());
}
// TODO move somewhere.
public static int compareVersions(String version1, String version2) {
if (version1 == null) {
return version2 == null ? 0 : -1;
}
if (version2 == null) {
return 1;
}
String[] v1 = version1.split("\\."); //$NON-NLS-1$
String[] v2 = version2.split("\\."); //$NON-NLS-1$
for (int i = 0; i < Math.max(v1.length, v2.length); ++i) {
if (v1.length <= i) {
return v2.length < i ? 0 : -1;
}
if (v2.length <= i) {
return 1;
}
try {
int vi1 = Integer.parseInt(v1[i]);
int vi2 = Integer.parseInt(v2[i]);
if (vi1 < vi2) {
return -1;
}
if (vi1 > vi2) {
return 1;
}
} catch (NumberFormatException e) {
// not numbers, do string compares
int c = v1[i].compareTo(v2[i]);
if (c < 0) {
return -1;
}
if (c > 0) {
return 1;
}
}
}
return 0;
}
public ArduinoPlatform getPlatform(String name) {
ArduinoPlatform foundPlatform = null;
for (ArduinoPlatform platform : platforms) {
@ -146,7 +100,7 @@ public class ArduinoPackage {
foundPlatform = platform;
} else {
if (platform.isInstalled()
&& compareVersions(platform.getVersion(), foundPlatform.getVersion()) > 0) {
&& ArduinoManager.compareVersions(platform.getVersion(), foundPlatform.getVersion()) > 0) {
foundPlatform = platform;
}
}
@ -168,6 +122,19 @@ public class ArduinoPackage {
return null;
}
public ArduinoTool getLatestTool(String toolName) {
ArduinoTool latestTool = null;
for (ArduinoTool tool : tools) {
if (tool.getName().equals(toolName)) {
if (latestTool == null
|| ArduinoManager.compareVersions(tool.getVersion(), latestTool.getVersion()) > 0) {
latestTool = tool;
}
}
}
return latestTool;
}
@Override
public boolean equals(Object obj) {
if (obj instanceof ArduinoPackage) {

View file

@ -36,7 +36,7 @@ public class LibraryIndex {
ArduinoLibrary current = latestLibs.get(name);
if (current != null) {
if (ArduinoPackage.compareVersions(library.getVersion(), current.getVersion()) > 0) {
if (ArduinoManager.compareVersions(library.getVersion(), current.getVersion()) > 0) {
latestLibs.put(name, library);
}
} else {

View file

@ -10,7 +10,9 @@ package org.eclipse.cdt.arduino.core.internal.build;
import java.io.File;
import java.io.FilenameFilter;
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;
@ -32,7 +34,7 @@ import org.eclipse.cdt.arduino.core.internal.board.ToolDependency;
import org.eclipse.cdt.core.CCorePlugin;
import org.eclipse.cdt.core.build.CBuildConfiguration;
import org.eclipse.cdt.core.build.CToolChain;
import org.eclipse.cdt.core.build.GCCToolChain;
import org.eclipse.cdt.core.build.CToolChainManager;
import org.eclipse.cdt.core.model.CoreModel;
import org.eclipse.cdt.core.model.ICProject;
import org.eclipse.cdt.core.model.IOutputEntry;
@ -69,16 +71,6 @@ public class ArduinoBuildConfiguration extends CBuildConfiguration {
private ArduinoBuildConfiguration(IBuildConfiguration config) {
super(config);
try {
if (getToolChain() == null) {
// For now, assume GCC is the toolchain,
// not sure it's ever not.
setToolChain(GCCToolChain.ID);
}
} catch (CoreException e) {
Activator.log(e);
}
}
private static Map<IBuildConfiguration, ArduinoBuildConfiguration> cache = new HashMap<>();
@ -438,6 +430,41 @@ public class ArduinoBuildConfiguration extends CBuildConfiguration {
}
}
@Override
public CToolChain getToolChain() throws CoreException {
CToolChain toolChain = super.getToolChain();
if (toolChain == null) {
// figure out which one it is
ArduinoPlatform platform = board.getPlatform();
String compilerPath = resolveProperty("compiler.path", platform.getPlatformProperties()); //$NON-NLS-1$
if (compilerPath != null) {
// TODO what if it is null?
Path path = Paths.get(compilerPath);
for (ToolDependency toolDep : platform.getToolsDependencies()) {
ArduinoTool tool = toolDep.getTool();
if (path.startsWith(tool.getInstallPath())) {
// this is it, find the matching
for (CToolChain tc : CToolChainManager.instance.getToolChains()) {
if (tc instanceof ArduinoGCCToolChain) {
if (((ArduinoGCCToolChain) tc).getTool().equals(tool)) {
setToolChain(tc);
toolChain = tc;
break;
}
}
}
// not found, create
toolChain = new ArduinoGCCToolChain(tool);
CToolChainManager.instance.addToolChain(toolChain);
setToolChain(toolChain);
break;
}
}
}
}
return toolChain;
}
public IScannerInfo getScannerInfo(IResource resource) throws CoreException {
IScannerInfo info = super.getScannerInfo(resource);
if (info == null) {
@ -473,8 +500,8 @@ public class ArduinoBuildConfiguration extends CBuildConfiguration {
}
properties.put("includes", includes); //$NON-NLS-1$
getToolChain().scanBuildOutput(getBuildFolder(), resolveProperty(recipe, properties), true);
info = super.getScannerInfo(resource);
List<String> cmd = Arrays.asList(resolveProperty(recipe, properties).split(" ")); //$NON-NLS-1$
info = getToolChain().getScannerInfo(getBuildFolder(), cmd);
}
return info;
}

View file

@ -0,0 +1,64 @@
/*******************************************************************************
* 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 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.ArduinoTool;
import org.eclipse.cdt.core.build.CToolChain;
import org.eclipse.cdt.core.build.IToolChainFactory;
import org.eclipse.cdt.core.build.gcc.GCCToolChain;
import org.osgi.service.prefs.Preferences;
public class ArduinoGCCToolChain extends GCCToolChain {
private static final String PACKAGE = "arduinoPackage"; //$NON-NLS-1$
private static final String TOOL = "arduinoTool"; //$NON-NLS-1$
private final ArduinoTool tool;
public ArduinoGCCToolChain(String id, Preferences settings) {
super(id, settings);
ArduinoPackage pkg = ArduinoManager.instance.getPackage(settings.get(PACKAGE, "")); //$NON-NLS-1$
if (pkg != null) {
this.tool = pkg.getLatestTool(settings.get(TOOL, "")); //$NON-NLS-1$
} else {
// TODO where did it go?
this.tool = null;
}
}
public ArduinoGCCToolChain(ArduinoTool tool) {
super(tool.getName());
this.tool = tool;
}
public static class ArduinoFactory implements IToolChainFactory {
@Override
public CToolChain createToolChain(String id, Preferences settings) {
return new ArduinoGCCToolChain(id, settings);
}
}
@Override
public String getFamily() {
return "Arduino GCC"; //$NON-NLS-1$
}
public ArduinoTool getTool() {
return tool;
}
@Override
public void save(Preferences settings) {
super.save(settings);
settings.put(TOOL, tool.getName());
settings.put(PACKAGE, tool.getPackage().getName());
}
}