diff --git a/build/org.eclipse.cdt.build.gcc.core/src/org/eclipse/cdt/build/gcc/core/GCCToolChain.java b/build/org.eclipse.cdt.build.gcc.core/src/org/eclipse/cdt/build/gcc/core/GCCToolChain.java index f2117a113f8..9ffdc420673 100644 --- a/build/org.eclipse.cdt.build.gcc.core/src/org/eclipse/cdt/build/gcc/core/GCCToolChain.java +++ b/build/org.eclipse.cdt.build.gcc.core/src/org/eclipse/cdt/build/gcc/core/GCCToolChain.java @@ -55,6 +55,7 @@ public class GCCToolChain extends PlatformObject implements IToolChain { private final String prefix; private final IEnvironmentVariable pathVar; private final IEnvironmentVariable[] envVars; + private final Map properties = new HashMap<>(); protected String[] compileCommands; @@ -113,16 +114,27 @@ public class GCCToolChain extends PlatformObject implements IToolChain { @Override public String getProperty(String key) { - // this class represents a local toolchain + String value = properties.get(key); + if (value != null) { + return value; + } + + // By default, we're a local GCC switch (key) { case ATTR_OS: return Platform.getOS(); case ATTR_ARCH: return Platform.getOSArch(); } + return null; } + @Override + public void setProperty(String key, String value) { + properties.put(key, value); + } + @Override public String getBinaryParserId() { // Assume local builds diff --git a/build/org.eclipse.cdt.build.gcc.core/src/org/eclipse/cdt/build/gcc/core/internal/GCCPathToolChainProvider.java b/build/org.eclipse.cdt.build.gcc.core/src/org/eclipse/cdt/build/gcc/core/internal/GCCPathToolChainProvider.java index 28905b02c97..61a0b69f307 100644 --- a/build/org.eclipse.cdt.build.gcc.core/src/org/eclipse/cdt/build/gcc/core/internal/GCCPathToolChainProvider.java +++ b/build/org.eclipse.cdt.build.gcc.core/src/org/eclipse/cdt/build/gcc/core/internal/GCCPathToolChainProvider.java @@ -18,8 +18,10 @@ import java.util.regex.Matcher; import java.util.regex.Pattern; import org.eclipse.cdt.build.gcc.core.GCCToolChain; +import org.eclipse.cdt.core.build.IToolChain; import org.eclipse.cdt.core.build.IToolChainManager; import org.eclipse.cdt.core.build.IToolChainProvider; +import org.eclipse.core.runtime.Platform; /** * Finds gcc and clang on the path. @@ -74,8 +76,32 @@ public class GCCPathToolChainProvider implements IToolChainProvider { String name = target + " - " + version; //$NON-NLS-1$ if (!names.contains(name)) { names.add(name); - manager.addToolChain(new GCCToolChain(this, target, version, - new Path[] { dir.toPath() }, prefix)); + GCCToolChain toolChain = new GCCToolChain(this, target, version, + new Path[] { dir.toPath() }, prefix); + String[] tuple = target.split("-"); //$NON-NLS-1$ + if (tuple.length > 2) { + // Arch + if ("x86_64".equals(tuple[0])) { + toolChain.setProperty(IToolChain.ATTR_ARCH, tuple[0]); + } else { + toolChain.setProperty(IToolChain.ATTR_ARCH, "x86"); // default + } + + // OS + switch (tuple[1]) { + case "w64": + toolChain.setProperty(IToolChain.ATTR_OS, Platform.OS_WIN32); + break; + case "linux": + toolChain.setProperty(IToolChain.ATTR_OS, Platform.OS_LINUX); + break; + case "apple": + toolChain.setProperty(IToolChain.ATTR_OS, Platform.OS_MACOSX); + break; + } + } + toolChain.setProperty(IToolChain.ATTR_PACKAGE, "system"); + manager.addToolChain(toolChain); } } } catch (IOException e) { diff --git a/build/org.eclipse.cdt.build.gcc.core/src/org/eclipse/cdt/build/gcc/core/internal/Msys2ToolChainProvider.java b/build/org.eclipse.cdt.build.gcc.core/src/org/eclipse/cdt/build/gcc/core/internal/Msys2ToolChainProvider.java index aa22cd01409..7e62455a92a 100644 --- a/build/org.eclipse.cdt.build.gcc.core/src/org/eclipse/cdt/build/gcc/core/internal/Msys2ToolChainProvider.java +++ b/build/org.eclipse.cdt.build.gcc.core/src/org/eclipse/cdt/build/gcc/core/internal/Msys2ToolChainProvider.java @@ -11,6 +11,7 @@ import java.nio.file.Path; import java.nio.file.Paths; import org.eclipse.cdt.build.gcc.core.GCCToolChain; +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.utils.WindowsRegistry; @@ -65,8 +66,10 @@ public class Msys2ToolChainProvider implements IToolChainProvider { Path msysPath = Paths.get(installLocation); Path gccPath = msysPath.resolve("mingw64\\bin\\gcc.exe"); //$NON-NLS-1$ if (Files.exists(gccPath)) { - manager.addToolChain(new GCCToolChain(this, "x86_64-w64-mingw32", "msys2.x86_64", new Path[] { //$NON-NLS-1$ //$NON-NLS-2$ - gccPath.getParent(), msysPath.resolve("bin"), msysPath.resolve("usr\\bin") })); //$NON-NLS-1$ //$NON-NLS-2$ + GCCToolChain toolChain = new GCCToolChain(this, "x86_64-w64-mingw32", "msys2.x86_64", new Path[] { //$NON-NLS-1$ //$NON-NLS-2$ + gccPath.getParent(), msysPath.resolve("bin"), msysPath.resolve("usr\\bin") }); //$NON-NLS-1$ //$NON-NLS-2$ + toolChain.setProperty(IToolChain.ATTR_PACKAGE, "msys2"); //$NON-NLS-1$ + manager.addToolChain(toolChain); return true; } else { return addToolChain32(manager, registry, key); @@ -78,8 +81,10 @@ public class Msys2ToolChainProvider implements IToolChainProvider { Path msysPath = Paths.get(installLocation); Path gccPath = msysPath.resolve("mingw32\\bin\\gcc.exe"); //$NON-NLS-1$ if (Files.exists(gccPath)) { - manager.addToolChain(new GCCToolChain(this, "i686-w64-mingw32", "msys2.i686", new Path[] { //$NON-NLS-1$ //$NON-NLS-2$ - gccPath.getParent(), msysPath.resolve("bin"), msysPath.resolve("usr\\bin") })); //$NON-NLS-1$ //$NON-NLS-2$ + GCCToolChain toolChain = new GCCToolChain(this, "i686-w64-mingw32", "msys2.i686", new Path[] { //$NON-NLS-1$ //$NON-NLS-2$ + gccPath.getParent(), msysPath.resolve("bin"), msysPath.resolve("usr\\bin") }); //$NON-NLS-1$ //$NON-NLS-2$ + toolChain.setProperty(IToolChain.ATTR_PACKAGE, "msys2"); //$NON-NLS-1$ + manager.addToolChain(toolChain); return true; } else { return false; diff --git a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/CModelManager.java b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/CModelManager.java index b9e110c6499..e3c90e9cfa4 100644 --- a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/CModelManager.java +++ b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/CModelManager.java @@ -611,11 +611,9 @@ public class CModelManager implements IResourceChangeListener, IContentTypeChang // Check for new style build configs first Set parserIds = new HashSet<>(); for (IBuildConfiguration config : project.getBuildConfigs()) { - if (!IBuildConfiguration.DEFAULT_CONFIG_NAME.equals(config.getName())) { - ICBuildConfiguration cconfig = config.getAdapter(ICBuildConfiguration.class); - if (cconfig != null) { - parserIds.add(cconfig.getBinaryParserId()); - } + ICBuildConfiguration cconfig = config.getAdapter(ICBuildConfiguration.class); + if (cconfig != null) { + parserIds.add(cconfig.getBinaryParserId()); } } if (!parserIds.isEmpty()) { diff --git a/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/CCorePlugin.java b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/CCorePlugin.java index 1078303db97..5bde7057c72 100644 --- a/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/CCorePlugin.java +++ b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/CCorePlugin.java @@ -1147,10 +1147,7 @@ public class CCorePlugin extends Plugin { // If we are new style build configurations, get the provider there IBuildConfiguration activeConfig = project.getActiveBuildConfig(); - ICBuildConfiguration cconfig = buildConfigManager.getBuildConfiguration(activeConfig); - if (cconfig == null) { - cconfig = buildConfigManager.getDefaultBuildConfiguration(project); - } + ICBuildConfiguration cconfig = activeConfig.getAdapter(ICBuildConfiguration.class); if (cconfig != null) { return cconfig; } diff --git a/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/build/CBuildConfiguration.java b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/build/CBuildConfiguration.java index e4b644edd3a..a8b89aa6112 100644 --- a/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/build/CBuildConfiguration.java +++ b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/build/CBuildConfiguration.java @@ -101,8 +101,8 @@ public abstract class CBuildConfiguration extends PlatformObject toolChain = tc; } - - public CBuildConfiguration(IBuildConfiguration config, String name, IToolChain toolChain) { + + protected CBuildConfiguration(IBuildConfiguration config, String name, IToolChain toolChain) { this.config = config; this.name = name; this.toolChain = toolChain; @@ -118,6 +118,10 @@ public abstract class CBuildConfiguration extends PlatformObject } } + protected CBuildConfiguration(IBuildConfiguration config, IToolChain toolChain) { + this(config, DEFAULT_NAME, toolChain); + } + @Override public IBuildConfiguration getBuildConfiguration() { return config; diff --git a/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/build/ICBuildConfiguration.java b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/build/ICBuildConfiguration.java index 2b4c46e4097..59b8a8731f0 100644 --- a/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/build/ICBuildConfiguration.java +++ b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/build/ICBuildConfiguration.java @@ -28,6 +28,12 @@ import org.eclipse.core.runtime.IProgressMonitor; */ public interface ICBuildConfiguration extends IAdaptable, IScannerInfoProvider { + /** + * CDT doesn't like that the Platform default config name is an empty string. + * It needs a real name for the name of the build directory, for example. + */ + public static String DEFAULT_NAME = "default"; + /** * Returns the resources build configuration that this CDT build * configuration is associated with. diff --git a/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/build/ICBuildConfigurationManager.java b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/build/ICBuildConfigurationManager.java index b2f1cefffba..b0f5d1d5f52 100644 --- a/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/build/ICBuildConfigurationManager.java +++ b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/build/ICBuildConfigurationManager.java @@ -20,6 +20,12 @@ import org.eclipse.core.runtime.IProgressMonitor; */ public interface ICBuildConfigurationManager { + /** + * Return the build configuration provider with the given id. + * + * @param id + * @return build configuration provider + */ ICBuildConfigurationProvider getProvider(String id); /** @@ -35,8 +41,6 @@ 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. * @@ -56,6 +60,4 @@ public interface ICBuildConfigurationManager { */ ICBuildConfiguration getBuildConfiguration(IBuildConfiguration buildConfig) throws CoreException; - ICBuildConfiguration getDefaultBuildConfiguration(IProject project) throws CoreException; - } diff --git a/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/build/ICBuildConfigurationProvider.java b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/build/ICBuildConfigurationProvider.java index 7885bf0a559..40bf781ee0e 100644 --- a/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/build/ICBuildConfigurationProvider.java +++ b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/build/ICBuildConfigurationProvider.java @@ -8,7 +8,6 @@ package org.eclipse.cdt.core.build; import org.eclipse.core.resources.IBuildConfiguration; -import org.eclipse.core.resources.IProject; import org.eclipse.core.runtime.CoreException; /** @@ -33,12 +32,4 @@ public interface ICBuildConfigurationProvider { */ ICBuildConfiguration getCBuildConfiguration(IBuildConfiguration config, String name) throws CoreException; - /** - * Returns a default C build configuration for a given project if any. - * - * @param project - * @return default C build configuration for the project - */ - ICBuildConfiguration getDefaultCBuildConfiguration(IProject project) throws CoreException; - } diff --git a/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/build/IToolChain.java b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/build/IToolChain.java index 2d341e28866..66dee546127 100644 --- a/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/build/IToolChain.java +++ b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/build/IToolChain.java @@ -27,11 +27,12 @@ public interface IToolChain extends IAdaptable { // Standard attributes static final String ATTR_OS = "os"; //$NON-NLS-1$ static final String ATTR_ARCH = "arch"; //$NON-NLS-1$ + static final String ATTR_PACKAGE = "package"; //$NON-NLS-1$ IToolChainProvider getProvider(); String getId(); - + String getVersion(); String getName(); @@ -47,6 +48,8 @@ public interface IToolChain extends IAdaptable { */ String getProperty(String key); + void setProperty(String key, String value); + IEnvironmentVariable getVariable(String name); IEnvironmentVariable[] getVariables(); @@ -63,5 +66,5 @@ public interface IToolChain extends IAdaptable { IResource[] getResourcesFromCommand(String[] command, URI buildDirectoryURI); String getBinaryParserId(); - + } diff --git a/core/org.eclipse.cdt.core/src/org/eclipse/cdt/internal/core/build/CBuildConfigurationManager.java b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/internal/core/build/CBuildConfigurationManager.java index 065afe9caa1..84991efc3aa 100644 --- a/core/org.eclipse.cdt.core/src/org/eclipse/cdt/internal/core/build/CBuildConfigurationManager.java +++ b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/internal/core/build/CBuildConfigurationManager.java @@ -72,16 +72,19 @@ public class CBuildConfigurationManager implements ICBuildConfigurationManager, public boolean supports(IProject project) { try { - return project.hasNature(natureId); + if (natureId != null) { + return project.hasNature(natureId); + } } catch (CoreException e) { CCorePlugin.log(e.getStatus()); - return false; } + return false; } } private Map providers; private Map configs = new HashMap<>(); + private Set noConfigs = new HashSet<>(); public CBuildConfigurationManager() { ResourcesPlugin.getWorkspace().addResourceChangeListener(this); @@ -105,13 +108,33 @@ public class CBuildConfigurationManager implements ICBuildConfigurationManager, } private Provider getProviderDelegate(String id) { - initProviders(); return providers.get(id); } @Override public ICBuildConfigurationProvider getProvider(String id) { - return getProviderDelegate(id).getProvider(); + initProviders(); + Provider provider = providers.get(id); + return provider != null ? provider.getProvider() : null; + } + + public ICBuildConfigurationProvider getProvider(String id, IProject project) { + initProviders(); + Provider provider = getProviderDelegate(id); + if (provider != null && provider.supports(project)) { + return provider.getProvider(); + } + return null; + } + + public ICBuildConfigurationProvider getProvider(IProject project) throws CoreException { + initProviders(); + for (Provider provider : providers.values()) { + if (provider.supports(project)) { + return provider.getProvider(); + } + } + return null; } @Override @@ -143,47 +166,51 @@ public class CBuildConfigurationManager implements ICBuildConfigurationManager, public ICBuildConfiguration getBuildConfiguration(IBuildConfiguration buildConfig) throws CoreException { initProviders(); synchronized (configs) { - ICBuildConfiguration config = configs.get(buildConfig); - if (config == null) { - String[] segments = buildConfig.getName().split("/"); //$NON-NLS-1$ - if (segments.length == 2) { - String providerId = segments[0]; - String configName = segments[1]; - - Provider provider = getProviderDelegate(providerId); - if (provider != null && provider.supports(buildConfig.getProject())) { - config = provider.getProvider().getCBuildConfiguration(buildConfig, configName); - configs.put(buildConfig, config); - - // Also make sure we reset the binary parser cache for the new config - CModelManager.getDefault().resetBinaryParser(buildConfig.getProject()); - } - } - } - return config; - } - } - - @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(); - for (Provider provider : providers.values()) { - if (provider.supports(project)) { - ICBuildConfiguration config = provider.getProvider().getDefaultCBuildConfiguration(project); + if (noConfigs.contains(buildConfig)) { + return null; + } else { + ICBuildConfiguration config = configs.get(buildConfig); if (config != null) { - configs.put(config.getBuildConfiguration(), config); return config; + } else { + String configName; + ICBuildConfigurationProvider provider; + if (IBuildConfiguration.DEFAULT_CONFIG_NAME.equals(buildConfig.getName())) { + configName = ICBuildConfiguration.DEFAULT_NAME; + provider = getProvider(buildConfig.getProject()); + } else { + String[] segments = buildConfig.getName().split("/"); //$NON-NLS-1$ + if (segments.length == 2) { + String providerId = segments[0]; + configName = segments[1]; + Provider delegate = getProviderDelegate(providerId); + if (delegate != null && delegate.supports(buildConfig.getProject())) { + provider = delegate.getProvider(); + } else { + return null; + } + } else { + // Not ours + return null; + } + } + + if (provider != null) { + config = provider.getCBuildConfiguration(buildConfig, configName); + if (config != null) { + configs.put(buildConfig, config); + + // Also make sure we reset the binary parser cache for the new config + CModelManager.getDefault().resetBinaryParser(buildConfig.getProject()); + return config; + } + } + + noConfigs.add(buildConfig); + return null; } } } - return null; } @Override diff --git a/core/org.eclipse.cdt.core/src/org/eclipse/cdt/internal/core/build/ToolChainManager.java b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/internal/core/build/ToolChainManager.java index ed83798bccf..b6fa1aae781 100644 --- a/core/org.eclipse.cdt.core/src/org/eclipse/cdt/internal/core/build/ToolChainManager.java +++ b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/internal/core/build/ToolChainManager.java @@ -133,6 +133,15 @@ public class ToolChainManager implements IToolChainManager { tcs.add(toolChain); } } + + // Allow 32-bit compilers on 64-bit machines + // TODO is there a cleaner way to do this? + if ("x86_64".equals(properties.get(IToolChain.ATTR_ARCH))) { //$NON-NLS-1$ + Map properties32 = new HashMap<>(properties); + properties32.put(IToolChain.ATTR_ARCH, "x86"); //$NON-NLS-1$ + tcs.addAll(getToolChainsMatching(properties32)); + } + return tcs; } diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/launching/GdbLaunch.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/launching/GdbLaunch.java index 721546dd345..a76718afb93 100644 --- a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/launching/GdbLaunch.java +++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/launching/GdbLaunch.java @@ -32,6 +32,7 @@ import java.util.concurrent.RejectedExecutionException; import org.eclipse.cdt.core.CCorePlugin; import org.eclipse.cdt.core.cdtvariables.CdtVariableException; import org.eclipse.cdt.core.cdtvariables.ICdtVariable; +import org.eclipse.cdt.core.cdtvariables.ICdtVariableManager; import org.eclipse.cdt.core.envvar.IEnvironmentVariable; import org.eclipse.cdt.core.model.CoreModel; import org.eclipse.cdt.core.model.ICProject; @@ -660,19 +661,17 @@ public class GdbLaunch extends DsfLaunch implements ITerminate, IDisconnect, ITr } // Add variables from build info - ICdtVariable[] buildVars = CCorePlugin.getDefault().getCdtVariableManager().getVariables(cfg); + ICdtVariableManager manager = CCorePlugin.getDefault().getCdtVariableManager(); + ICdtVariable[] buildVars = manager.getVariables(cfg); for (ICdtVariable var : buildVars) { try { // The project_classpath variable contributed by JDT is - // useless - // for running C/C++ - // binaries, but it can be lethal if it has a very large - // value - // that exceeds shell - // limit. See + // useless for running C/C++ binaries, but it can be lethal + // if it has a very large value that exceeds shell limit. See // http://bugs.eclipse.org/bugs/show_bug.cgi?id=408522 if (!"project_classpath".equals(var.getName())) {//$NON-NLS-1$ - envMap.put(var.getName(), var.getStringValue()); + String value = manager.resolveValue(var.getStringValue(), "", File.pathSeparator, cfg); //$NON-NLS-1$ + envMap.put(var.getName(), value); } } catch (CdtVariableException e) { // Some Eclipse dynamic variables can't be resolved diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/launching/GdbLaunchDelegate.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/launching/GdbLaunchDelegate.java index 7534f18c347..12b987b8326 100644 --- a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/launching/GdbLaunchDelegate.java +++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/launching/GdbLaunchDelegate.java @@ -139,7 +139,7 @@ public class GdbLaunchDelegate extends AbstractCLaunchDelegate2 monitor.worked(1); - String gdbVersion = getGDBVersion(config); + String gdbVersion = launch.getGDBVersion(); // First make sure non-stop is supported, if the user want to use this mode if (LaunchUtils.getIsNonStopMode(config) && !isNonStopSupportedInGdbVersion(gdbVersion)) { diff --git a/launch/org.eclipse.cdt.launch/src/org/eclipse/cdt/launch/internal/LocalRunLaunchDelegate.java b/launch/org.eclipse.cdt.launch/src/org/eclipse/cdt/launch/internal/LocalRunLaunchDelegate.java index 7b85457202e..e0e48bc56a0 100644 --- a/launch/org.eclipse.cdt.launch/src/org/eclipse/cdt/launch/internal/LocalRunLaunchDelegate.java +++ b/launch/org.eclipse.cdt.launch/src/org/eclipse/cdt/launch/internal/LocalRunLaunchDelegate.java @@ -18,9 +18,19 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.Date; import java.util.HashMap; +import java.util.List; import java.util.Map; +import java.util.Map.Entry; +import org.eclipse.cdt.core.CCorePlugin; +import org.eclipse.cdt.core.cdtvariables.CdtVariableException; +import org.eclipse.cdt.core.cdtvariables.ICdtVariable; +import org.eclipse.cdt.core.cdtvariables.ICdtVariableManager; +import org.eclipse.cdt.core.envvar.IEnvironmentVariable; +import org.eclipse.cdt.core.model.CoreModel; import org.eclipse.cdt.core.model.ICProject; +import org.eclipse.cdt.core.settings.model.ICConfigurationDescription; +import org.eclipse.cdt.core.settings.model.ICProjectDescription; import org.eclipse.cdt.debug.core.ICDTLaunchConfigurationConstants; import org.eclipse.cdt.launch.AbstractCLaunchDelegate2; import org.eclipse.cdt.launch.internal.ui.LaunchMessages; @@ -28,6 +38,9 @@ import org.eclipse.cdt.launch.internal.ui.LaunchUIPlugin; import org.eclipse.cdt.utils.CommandLineUtil; import org.eclipse.cdt.utils.pty.PTY; import org.eclipse.cdt.utils.spawner.ProcessFactory; +import org.eclipse.core.resources.IProject; +import org.eclipse.core.resources.IResource; +import org.eclipse.core.resources.ResourcesPlugin; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.IProgressMonitor; @@ -44,28 +57,29 @@ import com.ibm.icu.text.DateFormat; /** * The launch delegate for Run mode. */ -public class LocalRunLaunchDelegate extends AbstractCLaunchDelegate2 -{ +public class LocalRunLaunchDelegate extends AbstractCLaunchDelegate2 { public LocalRunLaunchDelegate() { // We support project-less run super(false); } - + @Override - public void launch( ILaunchConfiguration config, String mode, ILaunch launch, IProgressMonitor monitor ) throws CoreException { + public void launch(ILaunchConfiguration config, String mode, ILaunch launch, IProgressMonitor monitor) + throws CoreException { // This delegate is only for Run mode assert mode.equals(ILaunchManager.RUN_MODE); - - if ( monitor == null ) { + + if (monitor == null) { monitor = new NullProgressMonitor(); } - if ( mode.equals(ILaunchManager.RUN_MODE ) ) { - runLocalApplication( config, launch, monitor ); + if (mode.equals(ILaunchManager.RUN_MODE)) { + runLocalApplication(config, launch, monitor); } } - private void runLocalApplication(ILaunchConfiguration config, ILaunch launch, IProgressMonitor monitor) throws CoreException { - monitor.beginTask(LaunchMessages.LocalCDILaunchDelegate_0, 10); + private void runLocalApplication(ILaunchConfiguration config, ILaunch launch, IProgressMonitor monitor) + throws CoreException { + monitor.beginTask(LaunchMessages.LocalCDILaunchDelegate_0, 10); if (monitor.isCanceled()) { return; } @@ -77,50 +91,173 @@ public class LocalRunLaunchDelegate extends AbstractCLaunchDelegate2 if (wd == null) { wd = new File(System.getProperty("user.home", ".")); //$NON-NLS-1$ //$NON-NLS-2$ } - + String args = config.getAttribute(ICDTLaunchConfigurationConstants.ATTR_PROGRAM_ARGUMENTS, ""); //$NON-NLS-1$ if (args.length() != 0) { args = VariablesPlugin.getDefault().getStringVariableManager().performStringSubstitution(args); } - + String[] arguments = CommandLineUtil.argumentsToArray(args); ArrayList command = new ArrayList<>(1 + arguments.length); command.add(exePath.toOSString()); command.addAll(Arrays.asList(arguments)); monitor.worked(2); - + String[] commandArray = command.toArray(new String[command.size()]); - String[] environment = DebugPlugin.getDefault().getLaunchManager().getEnvironment(config); + String[] environment = getLaunchEnvironment(config); Process process = exec(commandArray, environment, wd); monitor.worked(6); String timestamp = DateFormat.getInstance().format(new Date(System.currentTimeMillis())); String processLabel = String.format("%s (%s)", commandArray[0], timestamp); //$NON-NLS-1$ - + DebugPlugin.newProcess(launch, process, processLabel, createProcessAttributes()); } finally { monitor.done(); - } + } + } + + /** + * Gets the CDT environment from the CDT project's configuration referenced + * by the launch + */ + protected String[] getLaunchEnvironment(ILaunchConfiguration config) throws CoreException { + // Get the project + String projectName = config.getAttribute(ICDTLaunchConfigurationConstants.ATTR_PROJECT_NAME, (String) null); + IProject project = null; + if (projectName == null) { + IResource[] resources = config.getMappedResources(); + if (resources != null && resources.length > 0 && resources[0] instanceof IProject) { + project = (IProject) resources[0]; + } + } else { + projectName = projectName.trim(); + if (projectName.length() == 0) { + return null; + } + project = ResourcesPlugin.getWorkspace().getRoot().getProject(projectName); + } + + HashMap envMap = new HashMap(); + + // Add in from the config + String[] debugEnv = DebugPlugin.getDefault().getLaunchManager().getEnvironment(config); + if (debugEnv != null) { + for (String env : debugEnv) { + String[] parts = env.split("=", 2); //$NON-NLS-1$ + if (parts.length == 2) { + envMap.put(parts[0], parts[1]); + } + } + } + + if (project != null && project.isAccessible()) { + ICProjectDescription projDesc = CoreModel.getDefault().getProjectDescription(project, false); + if (projDesc != null) { + String buildConfigID = config + .getAttribute(ICDTLaunchConfigurationConstants.ATTR_PROJECT_BUILD_CONFIG_ID, ""); //$NON-NLS-1$ + ICConfigurationDescription cfg = null; + if (buildConfigID.length() != 0) { + cfg = projDesc.getConfigurationById(buildConfigID); + } + + // if configuration is null fall-back to active + if (cfg == null) { + cfg = projDesc.getActiveConfiguration(); + } + + // Environment variables and inherited vars + IEnvironmentVariable[] vars = CCorePlugin.getDefault().getBuildEnvironmentManager().getVariables(cfg, + true); + for (IEnvironmentVariable var : vars) { + String value; + switch (var.getOperation()) { + case IEnvironmentVariable.ENVVAR_REPLACE: + value = var.getValue(); + break; + case IEnvironmentVariable.ENVVAR_APPEND: + value = envMap.get(var.getName()); + if (value != null) { + value += var.getDelimiter() + var.getValue(); + } else { + value = var.getValue(); + } + break; + case IEnvironmentVariable.ENVVAR_PREPEND: + value = envMap.get(var.getName()); + if (value != null) { + value = var.getValue() + var.getDelimiter() + value; + } else { + value = var.getValue(); + } + break; + case IEnvironmentVariable.ENVVAR_REMOVE: + envMap.remove(var.getName()); + value = null; + break; + default: + value = null; + } + + if (value != null) { + envMap.put(var.getName(), value); + } + } + + // Add variables from build info + ICdtVariableManager manager = CCorePlugin.getDefault().getCdtVariableManager(); + ICdtVariable[] buildVars = manager.getVariables(cfg); + for (ICdtVariable var : buildVars) { + try { + // The project_classpath variable contributed by JDT is + // useless for running C/C++ binaries, but it can be + // lethal if it has a very large value that exceeds + // shell limit. See + // http://bugs.eclipse.org/bugs/show_bug.cgi?id=408522 + if (!"project_classpath".equals(var.getName())) {//$NON-NLS-1$ + String value = manager.resolveValue(var.getStringValue(), "", File.pathSeparator, cfg); //$NON-NLS-1$ + envMap.put(var.getName(), value); + } + } catch (CdtVariableException e) { + // Some Eclipse dynamic variables can't be resolved + // dynamically... we don't care. + } + } + } + } + + // Turn it into an envp format + List strings = new ArrayList(envMap.size()); + for (Entry entry : envMap.entrySet()) { + StringBuilder buffer = new StringBuilder(entry.getKey()); + buffer.append('=').append(entry.getValue()); + strings.add(buffer.toString()); + } + + return strings.toArray(new String[strings.size()]); } protected Map createProcessAttributes() { Map attributes = new HashMap<>(); - - // Specify that the process factory (GdbProcessFactory) should use InferiorRuntimeProcess to wrap + + // Specify that the process factory (GdbProcessFactory) should use + // InferiorRuntimeProcess to wrap // the process that we are about to run. - // Note that GdbProcessFactory is only used for launches created using DSF-GDB not CDI - attributes.put("org.eclipse.cdt.dsf.gdb.createProcessType" /* IGdbDebugConstants.PROCESS_TYPE_CREATION_ATTR */, //$NON-NLS-1$ - "org.eclipse.cdt.dsf.gdb.inferiorProcess" /* IGdbDebugConstants.INFERIOR_PROCESS_CREATION_VALUE */); //$NON-NLS-1$ - - // Show the exit code of the process in the console title once it has terminated - attributes.put("org.eclipse.cdt.dsf.gdb.inferiorExited" /* IGdbDebugConstants.INFERIOR_EXITED_ATTR */, //$NON-NLS-1$ - ""); //$NON-NLS-1$ + // Note that GdbProcessFactory is only used for launches created using + // DSF-GDB not CDI + attributes.put("org.eclipse.cdt.dsf.gdb.createProcessType" /* IGdbDebugConstants.PROCESS_TYPE_CREATION_ATTR */, //$NON-NLS-1$ + "org.eclipse.cdt.dsf.gdb.inferiorProcess" /* IGdbDebugConstants.INFERIOR_PROCESS_CREATION_VALUE */); //$NON-NLS-1$ + + // Show the exit code of the process in the console title once it has + // terminated + attributes.put("org.eclipse.cdt.dsf.gdb.inferiorExited" /* IGdbDebugConstants.INFERIOR_EXITED_ATTR */, //$NON-NLS-1$ + ""); //$NON-NLS-1$ return attributes; } /** - * Method used to check that the project and program are correct. - * Can be overridden to avoid checking certain things. + * Method used to check that the project and program are correct. Can be + * overridden to avoid checking certain things. */ protected IPath checkBinaryDetails(final ILaunchConfiguration config) throws CoreException { // First verify we are dealing with a proper project. @@ -139,7 +276,8 @@ public class LocalRunLaunchDelegate extends AbstractCLaunchDelegate2 * @param environ * @param workingDirectory * the working directory, or null - * @return the resulting process or null if the exec is cancelled + * @return the resulting process or null if the exec is + * cancelled * @see Runtime * @since 4.7 */ @@ -151,38 +289,40 @@ public class LocalRunLaunchDelegate extends AbstractCLaunchDelegate2 return ProcessFactory.getFactory().exec(cmdLine, environ, workingDirectory); } } catch (IOException e) { - abort(LaunchMessages.LocalCDILaunchDelegate_8, e, ICDTLaunchConfigurationConstants.ERR_INTERNAL_ERROR); + abort(LaunchMessages.LocalCDILaunchDelegate_8, e, ICDTLaunchConfigurationConstants.ERR_INTERNAL_ERROR); } return null; } - @Override - public boolean preLaunchCheck(ILaunchConfiguration config, String mode, IProgressMonitor monitor) throws CoreException { - // Setup default Process Factory + public boolean preLaunchCheck(ILaunchConfiguration config, String mode, IProgressMonitor monitor) + throws CoreException { + // Setup default Process Factory setDefaultProcessFactory(config); return super.preLaunchCheck(config, mode, monitor); } - /** - * Modify the ILaunchConfiguration to set the DebugPlugin.ATTR_PROCESS_FACTORY_ID attribute, - * so as to specify the process factory to use. - * - * This attribute should only be set if it is not part of the configuration already, to allow - * other code to set it to something else. + /** + * Modify the ILaunchConfiguration to set the + * DebugPlugin.ATTR_PROCESS_FACTORY_ID attribute, so as to specify the + * process factory to use. + * + * This attribute should only be set if it is not part of the configuration + * already, to allow other code to set it to something else. */ - protected void setDefaultProcessFactory(ILaunchConfiguration config) throws CoreException { - if (!config.hasAttribute(DebugPlugin.ATTR_PROCESS_FACTORY_ID)) { - ILaunchConfigurationWorkingCopy wc = config.getWorkingCopy(); - // Use the debug process factory as it provides extra features for the program - // that is being debugged or in this case run. - // Effectively, we want to use InferiorRuntimeProcess when doing this Run launch. - wc.setAttribute(DebugPlugin.ATTR_PROCESS_FACTORY_ID, - "org.eclipse.cdt.dsf.gdb.GdbProcessFactory"); //$NON-NLS-1$ - wc.doSave(); - } - } + protected void setDefaultProcessFactory(ILaunchConfiguration config) throws CoreException { + if (!config.hasAttribute(DebugPlugin.ATTR_PROCESS_FACTORY_ID)) { + ILaunchConfigurationWorkingCopy wc = config.getWorkingCopy(); + // Use the debug process factory as it provides extra features for + // the program + // that is being debugged or in this case run. + // Effectively, we want to use InferiorRuntimeProcess when doing + // this Run launch. + wc.setAttribute(DebugPlugin.ATTR_PROCESS_FACTORY_ID, "org.eclipse.cdt.dsf.gdb.GdbProcessFactory"); //$NON-NLS-1$ + wc.doSave(); + } + } @Override protected String getPluginID() { diff --git a/qt/org.eclipse.cdt.qt-feature/feature.xml b/qt/org.eclipse.cdt.qt-feature/feature.xml index 1840a9db6c6..5883efeb130 100644 --- a/qt/org.eclipse.cdt.qt-feature/feature.xml +++ b/qt/org.eclipse.cdt.qt-feature/feature.xml @@ -1,36 +1,40 @@ - - - - - %description - - - - %copyright - - - - %license - - - - - - - + + + + + %description + + + + %copyright + + + + %license + + + + + + + + + + + diff --git a/qt/org.eclipse.cdt.qt.core/plugin.xml b/qt/org.eclipse.cdt.qt.core/plugin.xml index 56757c60dc8..56a4eb9ca0c 100644 --- a/qt/org.eclipse.cdt.qt.core/plugin.xml +++ b/qt/org.eclipse.cdt.qt.core/plugin.xml @@ -185,6 +185,9 @@ + + @@ -210,5 +213,16 @@ value="x86_64"> + + + + + + diff --git a/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/internal/qt/core/QtInstall.java b/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/internal/qt/core/QtInstall.java index c3e8c423761..47ab4d44a06 100644 --- a/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/internal/qt/core/QtInstall.java +++ b/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/internal/qt/core/QtInstall.java @@ -10,7 +10,11 @@ package org.eclipse.cdt.internal.qt.core; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; +import java.nio.file.Files; import java.nio.file.Path; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; import org.eclipse.cdt.qt.core.IQtInstall; @@ -18,6 +22,7 @@ public class QtInstall implements IQtInstall { private final Path qmakePath; private String spec; + private Map properties = new HashMap<>(); public QtInstall(Path qmakePath) { this.qmakePath = qmakePath; @@ -38,14 +43,16 @@ public class QtInstall implements IQtInstall { return qmakePath.resolve("../../qml"); //$NON-NLS-1$ } - public static String getSpec(String qmakePath) throws IOException { - Process proc = new ProcessBuilder(qmakePath, "-query", "QMAKE_XSPEC").start(); //$NON-NLS-1$ //$NON-NLS-2$ + public static String getSpec(Path qmakePath) throws IOException { + if (Files.exists(qmakePath)) { + Process proc = new ProcessBuilder(qmakePath.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) { return line.trim(); } } + } return null; } @@ -53,7 +60,7 @@ public class QtInstall implements IQtInstall { public String getSpec() { if (spec == null) { try { - spec = getSpec(getQmakePath().toString()); + spec = getSpec(getQmakePath()); } catch (IOException e) { Activator.log(e); } @@ -61,4 +68,14 @@ public class QtInstall implements IQtInstall { return spec; } + @Override + public void setProperty(String key, String value) { + properties.put(key, value); + } + + @Override + public Map getProperties() { + return Collections.unmodifiableMap(properties); + } + } diff --git a/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/internal/qt/core/QtInstallManager.java b/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/internal/qt/core/QtInstallManager.java index ce8e6cb230c..2e9e11fce9c 100644 --- a/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/internal/qt/core/QtInstallManager.java +++ b/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/internal/qt/core/QtInstallManager.java @@ -13,6 +13,7 @@ import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.Map; +import java.util.Map.Entry; import org.eclipse.cdt.core.build.IToolChain; import org.eclipse.cdt.qt.core.IQtInstall; @@ -78,7 +79,7 @@ public class QtInstallManager implements IQtInstallManager { for (Path path : installs.keySet()) { String key = path.toString(); if (prefs.get(key, null) == null) { - prefs.put(key, installs.get(key).getQmakePath().toString()); + prefs.put(key, installs.get(path).getQmakePath().toString()); } } @@ -135,6 +136,13 @@ public class QtInstallManager implements IQtInstallManager { return false; } } + + for (Entry property : install.getProperties().entrySet()) { + if (!property.getValue().equals(toolChain.getProperty(property.getKey()))) { + return false; + } + } + return true; } else { // Don't know so returning false diff --git a/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/internal/qt/core/build/QtBuildConfiguration.java b/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/internal/qt/core/build/QtBuildConfiguration.java index 571a76d10f8..f66e451b6f1 100644 --- a/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/internal/qt/core/build/QtBuildConfiguration.java +++ b/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/internal/qt/core/build/QtBuildConfiguration.java @@ -68,19 +68,20 @@ public class QtBuildConfiguration extends CBuildConfiguration implements ICBuild qtInstall = null; } - launchMode = settings.get(LAUNCH_MODE, ""); //$NON-NLS-1$ + launchMode = settings.get(LAUNCH_MODE, null); // $NON-NLS-1$ } QtBuildConfiguration(IBuildConfiguration config, String name, IToolChain toolChain, IQtInstall qtInstall, - String launchMode) - throws CoreException { + String launchMode) throws CoreException { super(config, name, toolChain); this.qtInstall = qtInstall; this.launchMode = launchMode; Preferences settings = getSettings(); settings.put(QTINSTALL_NAME, qtInstall.getQmakePath().toString()); - settings.put(LAUNCH_MODE, launchMode); + if (launchMode != null) { + settings.put(LAUNCH_MODE, launchMode); + } try { settings.flush(); } catch (BackingStoreException e) { @@ -108,16 +109,18 @@ public class QtBuildConfiguration extends CBuildConfiguration implements ICBuild } @Override - 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 String[] getQmakeConfig() { + if (launchMode != null) { + switch (launchMode) { + case "run": //$NON-NLS-1$ + return new String[] { "CONFIG-=debug_and_release", "CONFIG+=release" }; //$NON-NLS-1$ //$NON-NLS-2$ + case "debug": //$NON-NLS-1$ + return new String[] { "CONFIG-=debug_and_release", "CONFIG+=debug" }; //$NON-NLS-1$ //$NON-NLS-2$ + default: + return new String[] { "CONFIG-=debug_and_release", "CONFIG+=launch_mode_" + launchMode }; //$NON-NLS-1$ //$NON-NLS-2$ + } } + return new String[] { "CONFIG+=debug_and_release", "CONFIG+=launch_modeall" }; //$NON-NLS-1$ //$NON-NLS-2$ } public Path getProjectFile() { @@ -133,21 +136,18 @@ public class QtBuildConfiguration extends CBuildConfiguration implements ICBuild @Override public Path getProgramPath() throws CoreException { + // TODO get the app name from the .pro file. String projectName = getProject().getName(); switch (Platform.getOS()) { case Platform.OS_MACOSX: - // 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 Path appFolder = getBuildDirectory().resolve(projectName + ".app"); //$NON-NLS-1$ Path contentsFolder = appFolder.resolve("Contents"); //$NON-NLS-1$ Path macosFolder = contentsFolder.resolve("MacOS"); //$NON-NLS-1$ return macosFolder.resolve(projectName); - case Platform.OS_WIN32: { - String subdir = "run".equals(launchMode) ? "release" : "debug"; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ - return getBuildDirectory().resolve(subdir).resolve(projectName + ".exe"); //$NON-NLS-1$ - } + case Platform.OS_WIN32: + return getBuildDirectory().resolve(projectName + ".exe"); //$NON-NLS-1$ + case Platform.OS_LINUX: + return getBuildDirectory().resolve(projectName); //$NON-NLS-1$ default: Path releaseFolder = getBuildDirectory().resolve("release"); //$NON-NLS-1$ return releaseFolder.resolve(projectName); @@ -160,9 +160,11 @@ public class QtBuildConfiguration extends CBuildConfiguration implements ICBuild cmd.add(getQmakeCommand().toString()); cmd.add("-E"); //$NON-NLS-1$ - String config = getQmakeConfig(); + String[] config = getQmakeConfig(); if (config != null) { - cmd.add(config); + for (String str : config) { + cmd.add(str); + } } cmd.add(getProjectFile().toString()); @@ -280,16 +282,17 @@ public class QtBuildConfiguration extends CBuildConfiguration implements ICBuild List command = new ArrayList<>(); command.add(getQmakeCommand().toString()); - String config = getQmakeConfig(); + String[] config = getQmakeConfig(); if (config != null) { - command.add(config); + for (String str : config) { + command.add(str); + } } IFile projectFile = project.getFile(project.getName() + ".pro"); //$NON-NLS-1$ command.add(projectFile.getLocation().toOSString()); - ProcessBuilder processBuilder = new ProcessBuilder(command) - .directory(getBuildDirectory().toFile()); + ProcessBuilder processBuilder = new ProcessBuilder(command).directory(getBuildDirectory().toFile()); setBuildEnvironment(processBuilder.environment()); Process process = processBuilder.start(); @@ -305,7 +308,7 @@ public class QtBuildConfiguration extends CBuildConfiguration implements ICBuild } // run make - ProcessBuilder processBuilder = new ProcessBuilder(makeCommand.toString()).directory(buildDir.toFile()); + ProcessBuilder processBuilder = new ProcessBuilder(makeCommand.toString(), "all").directory(buildDir.toFile()); setBuildEnvironment(processBuilder.environment()); Process process = processBuilder.start(); outStream.write(makeCommand.toString() + '\n'); diff --git a/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/internal/qt/core/build/QtBuildConfigurationProvider.java b/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/internal/qt/core/build/QtBuildConfigurationProvider.java index ae3c784efd2..019c1c29eb5 100644 --- a/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/internal/qt/core/build/QtBuildConfigurationProvider.java +++ b/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/internal/qt/core/build/QtBuildConfigurationProvider.java @@ -7,6 +7,7 @@ *******************************************************************************/ package org.eclipse.cdt.internal.qt.core.build; +import java.util.Collection; import java.util.HashMap; import java.util.Map; @@ -16,15 +17,14 @@ import org.eclipse.cdt.core.build.ICBuildConfigurationProvider; import org.eclipse.cdt.core.build.IToolChain; import org.eclipse.cdt.core.build.IToolChainManager; import org.eclipse.cdt.internal.qt.core.Activator; -import org.eclipse.cdt.internal.qt.core.QtNature; import org.eclipse.cdt.qt.core.IQtBuildConfiguration; import org.eclipse.cdt.qt.core.IQtInstall; import org.eclipse.cdt.qt.core.IQtInstallManager; +import org.eclipse.cdt.qt.core.QtMinGWToolChainProvider; import org.eclipse.core.resources.IBuildConfiguration; import org.eclipse.core.resources.IProject; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IProgressMonitor; -import org.eclipse.core.runtime.NullProgressMonitor; import org.eclipse.core.runtime.Platform; public class QtBuildConfigurationProvider implements ICBuildConfigurationProvider { @@ -43,83 +43,71 @@ public class QtBuildConfigurationProvider implements ICBuildConfigurationProvide @Override public ICBuildConfiguration getCBuildConfiguration(IBuildConfiguration config, String name) { try { - // Double check to make sure this config is ours - if (!config.getProject().hasNature(QtNature.ID)) { - return null; - } + if (config.getName().equals(IBuildConfiguration.DEFAULT_CONFIG_NAME)) { + // try the toolchain for the local target + Map properties = new HashMap<>(); + properties.put(IToolChain.ATTR_OS, Platform.getOS()); + properties.put(IToolChain.ATTR_ARCH, Platform.getOSArch()); + for (IToolChain toolChain : toolChainManager.getToolChainsMatching(properties)) { + for (IQtInstall qtInstall : qtInstallManager.getInstalls()) { + if (qtInstallManager.supports(qtInstall, toolChain)) { + return new QtBuildConfiguration(config, name, toolChain, qtInstall, null); + } + } + } - return new QtBuildConfiguration(config, name); + // local didn't work, try and find one that does + for (IToolChain toolChain : toolChainManager.getToolChainsMatching(new HashMap<>())) { + for (IQtInstall qtInstall : qtInstallManager.getInstalls()) { + if (qtInstallManager.supports(qtInstall, toolChain)) { + return new QtBuildConfiguration(config, name, toolChain, qtInstall, null); + } + } + } + + // No valid combinations + return null; + } else { + return new QtBuildConfiguration(config, name); + } } catch (CoreException e) { - // Failed to create the build config. Return null so it gets recreated. + // Failed to create the build config. Return null so it gets + // recreated. Activator.log(e); return null; } } - @Override - public ICBuildConfiguration getDefaultCBuildConfiguration(IProject project) { - try { - if (!project.hasNature(QtNature.ID)) { - return null; - } - - // try the local target as the default - Map properties = new HashMap<>(); - properties.put(IToolChain.ATTR_OS, Platform.getOS()); - properties.put(IToolChain.ATTR_ARCH, Platform.getOSArch()); - for (IToolChain toolChain : toolChainManager.getToolChainsMatching(properties)) { - IQtBuildConfiguration qtConfig = getConfiguration(project, toolChain, "run", new NullProgressMonitor()); //$NON-NLS-1$ - if (qtConfig == null) { - qtConfig = createConfiguration(project, toolChain, "run", new NullProgressMonitor()); //$NON-NLS-1$ - if (qtConfig != null) { - return qtConfig; - } - } - } - - // local didn't work, try and find one that does - for (IToolChain toolChain : toolChainManager.getToolChainsMatching(new HashMap<>())) { - IQtBuildConfiguration qtConfig = getConfiguration(project, toolChain, "run", new NullProgressMonitor()); //$NON-NLS-1$ - if (qtConfig == null) { - qtConfig = createConfiguration(project, toolChain, "run", new NullProgressMonitor()); //$NON-NLS-1$ - if (qtConfig != null) { - return qtConfig; - } - } - } - } catch (CoreException e) { - Activator.log(e); - } - return null; - } - - public IQtBuildConfiguration getConfiguration(IProject project, IToolChain toolChain, String launchMode, + public IQtBuildConfiguration getConfiguration(IProject project, Map properties, String launchMode, IProgressMonitor monitor) throws CoreException { + Collection toolChains = toolChainManager.getToolChainsMatching(properties); for (IBuildConfiguration config : project.getBuildConfigs()) { ICBuildConfiguration cconfig = config.getAdapter(ICBuildConfiguration.class); if (cconfig != null) { IQtBuildConfiguration qtConfig = cconfig.getAdapter(IQtBuildConfiguration.class); - if (qtConfig != null && qtConfig.getLaunchMode().equals(launchMode) - && qtConfig.getToolChain().equals(toolChain)) { - return qtConfig; + if (qtConfig != null && launchMode.equals(qtConfig.getLaunchMode())) { + for (IToolChain toolChain : toolChains) { + if (qtConfig.getToolChain().equals(toolChain)) { + return qtConfig; + } + } } } } - return null; - } - public QtBuildConfiguration createConfiguration(IProject project, IToolChain toolChain, String launchMode, - IProgressMonitor monitor) throws CoreException { - for (IQtInstall qtInstall : qtInstallManager.getInstalls()) { - if (qtInstallManager.supports(qtInstall, toolChain)) { - // TODO what if multiple matches - String configName = "qt." + qtInstall.getSpec() + "." + launchMode; //$NON-NLS-1$ //$NON-NLS-2$ - IBuildConfiguration config = configManager.createBuildConfiguration(this, project, configName, - monitor); - QtBuildConfiguration qtConfig = new QtBuildConfiguration(config, configName, toolChain, qtInstall, - launchMode); - configManager.addBuildConfiguration(config, qtConfig); - return qtConfig; + // Not found, create one + for (IToolChain toolChain : toolChains) { + for (IQtInstall qtInstall : qtInstallManager.getInstalls()) { + if (qtInstallManager.supports(qtInstall, toolChain)) { + // TODO what if multiple matches, this returns first match + String configName = "qt." + qtInstall.getSpec() + "." + launchMode; //$NON-NLS-1$ //$NON-NLS-2$ + IBuildConfiguration config = configManager.createBuildConfiguration(this, project, configName, + monitor); + QtBuildConfiguration qtConfig = new QtBuildConfiguration(config, configName, toolChain, qtInstall, + launchMode); + configManager.addBuildConfiguration(config, qtConfig); + return qtConfig; + } } } diff --git a/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/internal/qt/core/provider/LinuxQtInstallProvider.java b/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/internal/qt/core/provider/LinuxQtInstallProvider.java new file mode 100644 index 00000000000..afd6a546eb4 --- /dev/null +++ b/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/internal/qt/core/provider/LinuxQtInstallProvider.java @@ -0,0 +1,41 @@ +/******************************************************************************* + * 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.core.provider; + +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; + +import org.eclipse.cdt.core.build.IToolChain; +import org.eclipse.cdt.internal.qt.core.QtInstall; +import org.eclipse.cdt.qt.core.IQtInstall; +import org.eclipse.cdt.qt.core.IQtInstallProvider; +import org.eclipse.core.runtime.Platform; + +/** + * Qt install provider that looks for qmake on /usr/bin + */ +public class LinuxQtInstallProvider implements IQtInstallProvider { + + @Override + public Collection getInstalls() { + if (Platform.getOS().equals(Platform.OS_LINUX)) { + Path qmakePath = Paths.get("/usr/bin/qmake"); //$NON-NLS-1$ + if (Files.exists(qmakePath)) { + QtInstall install = new QtInstall(qmakePath); + install.setProperty(IToolChain.ATTR_PACKAGE, "system"); + return Arrays.asList(install); + } + } + return Collections.emptyList(); + } + +} diff --git a/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/internal/qt/core/provider/Msys2QtInstallProvider.java b/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/internal/qt/core/provider/Msys2QtInstallProvider.java index 7f0b1a5b037..d3270a25907 100644 --- a/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/internal/qt/core/provider/Msys2QtInstallProvider.java +++ b/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/internal/qt/core/provider/Msys2QtInstallProvider.java @@ -14,6 +14,7 @@ import java.util.Collection; import java.util.Collections; import java.util.List; +import org.eclipse.cdt.core.build.IToolChain; import org.eclipse.cdt.internal.qt.core.QtInstall; import org.eclipse.cdt.qt.core.IQtInstall; import org.eclipse.cdt.qt.core.IQtInstallProvider; @@ -40,7 +41,9 @@ public class Msys2QtInstallProvider implements IQtInstallProvider { if ("MSYS2 64bit".equals(displayName)) { //$NON-NLS-1$ String installLocation = registry.getCurrentUserValue(compKey, "InstallLocation"); //$NON-NLS-1$ Path qmakePath = Paths.get(installLocation + "\\mingw64\\bin\\qmake.exe"); //$NON-NLS-1$ - installs.add(new QtInstall(qmakePath)); + QtInstall install = new QtInstall(qmakePath); + install.setProperty(IToolChain.ATTR_PACKAGE, "msys2"); //$NON-NLS-1$ + installs.add(install); } } return installs; diff --git a/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/internal/qt/core/provider/QtInstallProvider.java b/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/internal/qt/core/provider/QtInstallProvider.java index 1ebfe465d0e..144eb8959dc 100644 --- a/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/internal/qt/core/provider/QtInstallProvider.java +++ b/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/internal/qt/core/provider/QtInstallProvider.java @@ -16,6 +16,7 @@ import java.util.Collections; import java.util.stream.Collectors; import org.eclipse.cdt.codan.core.cxx.Activator; +import org.eclipse.cdt.core.build.IToolChain; import org.eclipse.cdt.internal.qt.core.QtInstall; import org.eclipse.cdt.qt.core.IQtInstall; import org.eclipse.cdt.qt.core.IQtInstallProvider; @@ -27,14 +28,22 @@ import org.eclipse.core.runtime.Platform; */ public class QtInstallProvider implements IQtInstallProvider { + private static boolean isWin32 = Platform.getOS().equals(Platform.OS_WIN32); + @Override public Collection getInstalls() { Path root = getQtRoot(); - Path qmake = Paths.get(Platform.getOS().equals(Platform.OS_WIN32) ? "bin/qmake.exe" : "bin/qmake"); //$NON-NLS-1$ //$NON-NLS-2$ - if (root != null) { + Path qmake = Paths.get(isWin32 ? "bin/qmake.exe" : "bin/qmake"); //$NON-NLS-1$ //$NON-NLS-2$ + if (root != null && Files.exists(root)) { try { return Files.walk(root, 2).filter((path) -> Files.exists(path.resolve(qmake))) - .map((path) -> new QtInstall(path.resolve(qmake))).collect(Collectors.toList()); + .map((path) -> { + QtInstall install = new QtInstall(path.resolve(qmake)); + if (isWin32 && "win32-g++".equals(install.getSpec())) { //$NON-NLS-1$ + install.setProperty(IToolChain.ATTR_PACKAGE, "qt"); //$NON-NLS-1$ //$NON-NLS-2$ + } + return install; + }).collect(Collectors.toList()); } catch (IOException e) { Activator.log(e); } @@ -43,14 +52,13 @@ public class QtInstallProvider implements IQtInstallProvider { } private Path getQtRoot() { - if (Platform.getOS().equals(Platform.OS_WIN32)) { + if (isWin32) { WindowsRegistry registry = WindowsRegistry.getRegistry(); String uninstallKey = "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall"; //$NON-NLS-1$ String subkey; for (int i = 0; (subkey = registry.getCurrentUserKeyName(uninstallKey, i)) != null; i++) { String compKey = uninstallKey + '\\' + subkey; String displayName = registry.getCurrentUserValue(compKey, "DisplayName"); //$NON-NLS-1$ - // On Windows, look for MSYS2, MinGW 64/32 locations if ("Qt".equals(displayName)) { //$NON-NLS-1$ String installLocation = registry.getCurrentUserValue(compKey, "InstallLocation"); //$NON-NLS-1$ return Paths.get(installLocation); diff --git a/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/qt/core/IQtBuildConfiguration.java b/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/qt/core/IQtBuildConfiguration.java index 1e8dcf10e73..ee55522304f 100644 --- a/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/qt/core/IQtBuildConfiguration.java +++ b/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/qt/core/IQtBuildConfiguration.java @@ -18,7 +18,7 @@ public interface IQtBuildConfiguration extends ICBuildConfiguration { Path getQmakeCommand(); - String getQmakeConfig(); + String[] getQmakeConfig(); Path getProgramPath() throws CoreException; diff --git a/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/qt/core/IQtInstall.java b/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/qt/core/IQtInstall.java index c55fd1a5f02..03cefb83c01 100644 --- a/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/qt/core/IQtInstall.java +++ b/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/qt/core/IQtInstall.java @@ -8,6 +8,7 @@ package org.eclipse.cdt.qt.core; import java.nio.file.Path; +import java.util.Map; /** * Represents an installation of the Qt SDK. Qt installs are defined by the path @@ -25,4 +26,8 @@ public interface IQtInstall { Path getQmlPath(); + void setProperty(String key, String value); + + Map getProperties(); + } diff --git a/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/qt/core/QtLaunchConfigurationDelegate.java b/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/qt/core/QtLaunchConfigurationDelegate.java index d3e952c2740..998546284d7 100644 --- a/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/qt/core/QtLaunchConfigurationDelegate.java +++ b/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/qt/core/QtLaunchConfigurationDelegate.java @@ -12,7 +12,6 @@ import java.util.Map; import org.eclipse.cdt.core.build.ICBuildConfigurationManager; import org.eclipse.cdt.core.build.IToolChain; -import org.eclipse.cdt.core.build.IToolChainManager; import org.eclipse.cdt.internal.qt.core.Activator; import org.eclipse.cdt.internal.qt.core.build.QtBuildConfigurationProvider; import org.eclipse.core.resources.IProject; @@ -71,19 +70,12 @@ public abstract class QtLaunchConfigurationDelegate extends LaunchConfigurationT .getProvider(QtBuildConfigurationProvider.ID); IProject project = configuration.getMappedResources()[0].getProject(); - // Find the toolchains that support this target Map properties = new HashMap<>(); populateToolChainProperties(target, properties); - IToolChainManager toolChainManager = Activator.getService(IToolChainManager.class); - for (IToolChain toolChain : toolChainManager.getToolChainsMatching(properties)) { - IQtBuildConfiguration qtConfig = provider.getConfiguration(project, toolChain, mode, monitor); - if (qtConfig == null) { - qtConfig = provider.createConfiguration(project, toolChain, mode, monitor); - } - if (qtConfig != null) { - return qtConfig; - } + IQtBuildConfiguration qtConfig = provider.getConfiguration(project, properties, mode, monitor); + if (qtConfig != null) { + return qtConfig; } // Couldn't find any diff --git a/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/qt/core/QtMinGWToolChainProvider.java b/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/qt/core/QtMinGWToolChainProvider.java index d6918cccde7..c50572f41dd 100644 --- a/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/qt/core/QtMinGWToolChainProvider.java +++ b/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/qt/core/QtMinGWToolChainProvider.java @@ -13,6 +13,7 @@ import java.nio.file.Path; import java.nio.file.Paths; import org.eclipse.cdt.build.gcc.core.GCCToolChain; +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.internal.qt.core.Activator; @@ -22,7 +23,8 @@ 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$ + public static final String ID = "org.eclipse.cdt.qt.core.qtMinGWProvider"; //$NON-NLS-1$ + public static final String TOOLCHAIN_ID = "qt.mingw"; //$NON-NLS-1$ @Override public String getId() { @@ -39,15 +41,20 @@ public class QtMinGWToolChainProvider implements IToolChainProvider { String compKey = uninstallKey + '\\' + subkey; String displayName = registry.getCurrentUserValue(compKey, "DisplayName"); //$NON-NLS-1$ if ("Qt".equals(displayName)) { //$NON-NLS-1$ - String installLocation = registry.getCurrentUserValue(compKey, "InstallLocation"); //$NON-NLS-1$ - Path gcc = Paths.get("\\bin\\gcc.exe"); //$NON-NLS-1$ - try { - Files.walk(Paths.get(installLocation).resolve("Tools"), 1) //$NON-NLS-1$ - .filter((path) -> Files.exists(path.resolve(gcc))) - .map((path) -> new GCCToolChain(this, "qt.mingw", "", new Path[] { path.resolve("bin") })) //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ - .forEach(toolChain -> manager.addToolChain(toolChain)); - } catch (IOException e) { - Activator.log(e); + Path installLocation = Paths.get(registry.getCurrentUserValue(compKey, "InstallLocation")); //$NON-NLS-1$ + if (Files.exists(installLocation)) { + Path gcc = Paths.get("bin\\gcc.exe"); //$NON-NLS-1$ + try { + Files.walk(installLocation.resolve("Tools"), 1) //$NON-NLS-1$ + .filter(path -> Files.exists(path.resolve(gcc))).map(path -> { + GCCToolChain toolChain = new GCCToolChain(this, TOOLCHAIN_ID, "", //$NON-NLS-1$ + new Path[] { path.resolve("bin") }); //$NON-NLS-1$ + toolChain.setProperty(IToolChain.ATTR_PACKAGE, "qt"); //$NON-NLS-1$ + return toolChain; + }).forEach(toolChain -> manager.addToolChain(toolChain)); + } catch (IOException e) { + Activator.log(e); + } } } } diff --git a/qt/org.eclipse.cdt.qt.core/templates/project2/appProject/main.pro b/qt/org.eclipse.cdt.qt.core/templates/project2/appProject/main.pro index 96847694ccd..f80ccb38ca4 100644 --- a/qt/org.eclipse.cdt.qt.core/templates/project2/appProject/main.pro +++ b/qt/org.eclipse.cdt.qt.core/templates/project2/appProject/main.pro @@ -6,3 +6,11 @@ CONFIG += c++11 RESOURCES += ${projectName}.qrc qml.files = src/${projectName}.qml + +launch_modeall { + CONFIG(debug, debug|release) { + DESTDIR = debug + } else { + DESTDIR = release + } +} diff --git a/qt/org.eclipse.cdt.qt.ui/src/org/eclipse/cdt/internal/qt/ui/preferences/NewQtInstallWizardPage.java b/qt/org.eclipse.cdt.qt.ui/src/org/eclipse/cdt/internal/qt/ui/preferences/NewQtInstallWizardPage.java index a870cafddeb..10965837736 100644 --- a/qt/org.eclipse.cdt.qt.ui/src/org/eclipse/cdt/internal/qt/ui/preferences/NewQtInstallWizardPage.java +++ b/qt/org.eclipse.cdt.qt.ui/src/org/eclipse/cdt/internal/qt/ui/preferences/NewQtInstallWizardPage.java @@ -81,7 +81,7 @@ public class NewQtInstallWizardPage extends WizardPage { @Override protected IStatus run(IProgressMonitor monitor) { try { - String spec = QtInstall.getSpec(selected); + String spec = QtInstall.getSpec(Paths.get(selected)); getControl().getDisplay().asyncExec(() -> { specText.setText(spec); }); diff --git a/toolchains/arduino/org.eclipse.cdt.arduino-feature/feature.xml b/toolchains/arduino/org.eclipse.cdt.arduino-feature/feature.xml index cd655da1e4f..a01625ef990 100644 --- a/toolchains/arduino/org.eclipse.cdt.arduino-feature/feature.xml +++ b/toolchains/arduino/org.eclipse.cdt.arduino-feature/feature.xml @@ -1,46 +1,46 @@ - - - - - %description - - - - %copyright - - - - %license - - - - - - - - - - - - - - - - + + + + + %description + + + + %copyright + + + + %license + + + + + + + + + + + + + + + + diff --git a/toolchains/arduino/org.eclipse.cdt.arduino.core.tests/src/org/eclipse/cdt/arduino/core/tests/FullIntegration.java b/toolchains/arduino/org.eclipse.cdt.arduino.core.tests/src/org/eclipse/cdt/arduino/core/tests/FullIntegration.java new file mode 100644 index 00000000000..f70e5bdae4a --- /dev/null +++ b/toolchains/arduino/org.eclipse.cdt.arduino.core.tests/src/org/eclipse/cdt/arduino/core/tests/FullIntegration.java @@ -0,0 +1,205 @@ +/******************************************************************************* + * 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 + *******************************************************************************/ +package org.eclipse.cdt.arduino.core.tests; + +import java.net.URL; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.Collection; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Set; + +import org.eclipse.cdt.arduino.core.internal.Activator; +import org.eclipse.cdt.arduino.core.internal.ArduinoPreferences; +import org.eclipse.cdt.arduino.core.internal.ArduinoProjectGenerator; +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.board.ArduinoPlatform; +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.resources.IWorkspaceRoot; +import org.eclipse.core.resources.ResourcesPlugin; +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.remote.core.IRemoteConnection; +import org.eclipse.remote.core.IRemoteConnectionType; +import org.eclipse.remote.core.IRemoteConnectionWorkingCopy; +import org.eclipse.remote.core.IRemoteServicesManager; +import org.junit.Test; + +@SuppressWarnings("nls") +public class FullIntegration { + + private static final ArduinoManager arduinoManager = Activator.getService(ArduinoManager.class); + private static final IRemoteServicesManager remoteManager = Activator.getService(IRemoteServicesManager.class); + private static final ICBuildConfigurationManager buildConfigManager = Activator + .getService(ICBuildConfigurationManager.class); + + private void setBoardUrls() throws Exception { + URL[] urls = new URL[] { new URL("http://downloads.arduino.cc/packages/package_index.json"), + new URL("https://adafruit.github.io/arduino-board-index/package_adafruit_index.json") }; + ArduinoPreferences.setBoardUrlList(urls); + } + + private Set getSkipBuild() throws Exception { + Set boards = new HashSet<>(); + + // Fails in arduino too + boards.add(arduinoManager.getBoard("arduino", "avr", "robotControl")); + boards.add(arduinoManager.getBoard("arduino", "avr", "robotMotor")); + boards.add(arduinoManager.getBoard("adafruit", "avr", "adafruit32u4")); + + // TODO Need to add support for menu specific build properties + boards.add(arduinoManager.getBoard("arduino", "avr", "mini")); + boards.add(arduinoManager.getBoard("arduino", "avr", "lilypad")); + boards.add(arduinoManager.getBoard("arduino", "avr", "diecimila")); + boards.add(arduinoManager.getBoard("arduino", "avr", "pro")); + boards.add(arduinoManager.getBoard("arduino", "avr", "atmegang")); + boards.add(arduinoManager.getBoard("arduino", "avr", "bt")); + boards.add(arduinoManager.getBoard("arduino", "avr", "mega")); + boards.add(arduinoManager.getBoard("arduino", "avr", "nano")); + boards.add(arduinoManager.getBoard("TeeOnArdu", "avr", "CirPlayTeensyCore")); + boards.add(arduinoManager.getBoard("TeeOnArdu", "avr", "FloraTeensyCore")); + boards.add(arduinoManager.getBoard("TeeOnArdu", "avr", "TeeOnArdu")); + + // TODO build.system.path missing + boards.add(arduinoManager.getBoard("arduino", "sam", "arduino_due_x")); + boards.add(arduinoManager.getBoard("arduino", "sam", "arduino_due_x_dbg")); + boards.add(arduinoManager.getBoard("Intel", "arc32", "arduino_101")); + + if (Platform.getOS().equals(Platform.OS_WIN32)) { + // i586/i686 link missing + boards.add(arduinoManager.getBoard("Intel", "i586", "izmir_fd")); + boards.add(arduinoManager.getBoard("Intel", "i586", "izmir_fg")); + boards.add(arduinoManager.getBoard("Intel", "i686", "izmir_ec")); + } + return boards; + } + + private Set getSkipUpload() throws Exception { + Set boards = new HashSet<>(); + + // missing upload.protocol + boards.add(arduinoManager.getBoard("arduino", "avr", "gemma")); + boards.add(arduinoManager.getBoard("adafruit", "avr", "gemma")); + boards.add(arduinoManager.getBoard("adafruit", "avr", "trinket5")); + boards.add(arduinoManager.getBoard("adafruit", "avr", "trinket3")); + + // usbtiny missing + boards.add(arduinoManager.getBoard("adafruit", "avr", "protrinket3")); + boards.add(arduinoManager.getBoard("adafruit", "avr", "protrinket5")); + + return boards; + } + + @Test + public void runTest() throws Exception { + IProgressMonitor monitor = new SysoutProgressMonitor(); + + setArduinoHome(); + setBoardUrls(); + loadPlatforms(monitor); + + Set skipBuild = getSkipBuild(); + Set skipUpload = getSkipUpload(); + IProject project = createProject(monitor); + for (ArduinoBoard board : arduinoManager.getInstalledBoards()) { + if (!skipBuild.contains(board)) { + buildBoard(project, board, !skipUpload.contains(board), monitor); + } + } + } + + private void setArduinoHome() throws Exception { + Path workspace = Paths.get(ResourcesPlugin.getWorkspace().getRoot().getLocationURI()); + ArduinoPreferences.setArduinoHome(workspace.resolve(".arduinocdt")); + } + + private void loadPlatforms(IProgressMonitor monitor) throws Exception { + Collection plats = arduinoManager.getAvailablePlatforms(monitor); + arduinoManager.installPlatforms(plats, monitor); + } + + private IProject createProject(IProgressMonitor monitor) throws Exception { + IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot(); + String projectName = "ArduinoTest"; + ArduinoProjectGenerator generator = new ArduinoProjectGenerator("templates/cppsketch/manifest.xml"); //$NON-NLS-1$ + + Job job = new Job("Create") { + @Override + protected IStatus run(IProgressMonitor monitor) { + try { + IProject project = root.getProject(projectName); + if (project.exists()) { + project.delete(true, monitor); + } + + generator.setProjectName(projectName); + generator.generate(new HashMap(), monitor); + return Status.OK_STATUS; + } catch (CoreException e) { + return e.getStatus(); + } + } + }; + job.setRule(root); + job.schedule(); + job.join(); + + return generator.getProject(); + } + + private void buildBoard(IProject project, ArduinoBoard board, boolean upload, IProgressMonitor monitor) throws Exception { + ArduinoRemoteConnection arduinoTarget = createTarget(board); + ArduinoBuildConfigurationProvider provider = (ArduinoBuildConfigurationProvider) buildConfigManager + .getProvider(ArduinoBuildConfigurationProvider.ID); + ArduinoBuildConfiguration config = provider.createConfiguration(project, arduinoTarget, "run", monitor); + + System.out.println(String.format("Building board: %s\n %s - %s", board.getName(), board.getId(), + board.getPlatform().getInstallPath())); + + config.generateMakeFile(monitor); + ProcessBuilder processBuilder = new ProcessBuilder().command(config.getBuildCommand()) + .directory(config.getBuildDirectory().toFile()).inheritIO(); + config.setBuildEnvironment(processBuilder.environment()); + Process process = processBuilder.start(); + int rc = process.waitFor(); + if (rc != 0) { + throw new Exception("Build failed"); + } + + // Test to make sure we can get the upload command cleanly + if (upload) { + System.out.println(String.join(" ", config.getUploadCommand("port1"))); + } + } + + private ArduinoRemoteConnection createTarget(ArduinoBoard board) throws Exception { + IRemoteConnectionType type = remoteManager.getConnectionType(ArduinoRemoteConnection.TYPE_ID); + IRemoteConnection connection = type.getConnection(board.getName()); + if (connection != null) { + type.removeConnection(connection); + } + + IRemoteConnectionWorkingCopy workingCopy = type.newConnection(board.getName()); + ArduinoRemoteConnection.setBoardId(workingCopy, board); + ArduinoRemoteConnection.setPortName(workingCopy, "port1"); + connection = workingCopy.save(); + + return connection.getService(ArduinoRemoteConnection.class); + } + +} diff --git a/toolchains/arduino/org.eclipse.cdt.arduino.core.tests/src/org/eclipse/cdt/arduino/core/tests/SysoutProgressMonitor.java b/toolchains/arduino/org.eclipse.cdt.arduino.core.tests/src/org/eclipse/cdt/arduino/core/tests/SysoutProgressMonitor.java new file mode 100644 index 00000000000..deb16eba55b --- /dev/null +++ b/toolchains/arduino/org.eclipse.cdt.arduino.core.tests/src/org/eclipse/cdt/arduino/core/tests/SysoutProgressMonitor.java @@ -0,0 +1,38 @@ +/******************************************************************************* + * 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 + *******************************************************************************/ +package org.eclipse.cdt.arduino.core.tests; + +import org.eclipse.core.runtime.NullProgressMonitor; + +public class SysoutProgressMonitor extends NullProgressMonitor { + + @Override + public void beginTask(String name, int totalWork) { + if (name.length() > 0) { + System.out.println(name); + System.out.flush(); + } + } + + @Override + public void subTask(String name) { + if (name.length() > 0) { + System.out.println(name); + System.out.flush(); + } + } + + @Override + public void setTaskName(String name) { + if (name.length() > 0) { + System.out.println(name); + System.out.flush(); + } + } + +} diff --git a/toolchains/arduino/org.eclipse.cdt.arduino.core/src/org/eclipse/cdt/arduino/core/internal/ArduinoPreferences.java b/toolchains/arduino/org.eclipse.cdt.arduino.core/src/org/eclipse/cdt/arduino/core/internal/ArduinoPreferences.java index c8ac61c5258..988ef26d933 100644 --- a/toolchains/arduino/org.eclipse.cdt.arduino.core/src/org/eclipse/cdt/arduino/core/internal/ArduinoPreferences.java +++ b/toolchains/arduino/org.eclipse.cdt.arduino.core/src/org/eclipse/cdt/arduino/core/internal/ArduinoPreferences.java @@ -38,11 +38,15 @@ public class ArduinoPreferences { return Paths.get(getPrefs().get(ARDUINO_HOME, defaultHome)); } + public static void setArduinoHome(Path home) { + getPrefs().put(ARDUINO_HOME, home.toString()); + } + public static String getBoardUrls() { return getPrefs().get(BOARD_URLS, defaultBoardUrls); } - public static Collection getBoardUrlList() throws CoreException { + public static URL[] getBoardUrlList() throws CoreException { List urlList = new ArrayList<>(); for (String url : getBoardUrls().split("\n")) { //$NON-NLS-1$ try { @@ -51,7 +55,7 @@ public class ArduinoPreferences { throw Activator.coreException(e); } } - return urlList; + return urlList.toArray(new URL[urlList.size()]); } public static void setBoardUrls(String boardUrls) { @@ -64,6 +68,22 @@ public class ArduinoPreferences { } } + public static void setBoardUrlList(URL[] urls) { + StringBuilder str = new StringBuilder(); + for (int i = 0; i < urls.length - 1; ++i) { + str.append(urls[i].toString()); + str.append('\n'); + } + if (urls.length > 0) { + str.append(urls[urls.length - 1].toString()); + } + setBoardUrls(str.toString()); + } + + public static String getDefaultArduinoHome() { + return defaultHome; + } + public static String getDefaultBoardUrls() { return defaultBoardUrls; } diff --git a/toolchains/arduino/org.eclipse.cdt.arduino.core/src/org/eclipse/cdt/arduino/core/internal/board/ArduinoBoard.java b/toolchains/arduino/org.eclipse.cdt.arduino.core/src/org/eclipse/cdt/arduino/core/internal/board/ArduinoBoard.java index bad4694bc65..0bb2b8d667d 100644 --- a/toolchains/arduino/org.eclipse.cdt.arduino.core/src/org/eclipse/cdt/arduino/core/internal/board/ArduinoBoard.java +++ b/toolchains/arduino/org.eclipse.cdt.arduino.core/src/org/eclipse/cdt/arduino/core/internal/board/ArduinoBoard.java @@ -13,8 +13,6 @@ import org.eclipse.cdt.arduino.core.internal.HierarchicalProperties; public class ArduinoBoard { - public static final String MENU_QUALIFIER = "menu_"; //$NON-NLS-1$ - private String name; private String id; diff --git a/toolchains/arduino/org.eclipse.cdt.arduino.core/src/org/eclipse/cdt/arduino/core/internal/board/ArduinoManager.java b/toolchains/arduino/org.eclipse.cdt.arduino.core/src/org/eclipse/cdt/arduino/core/internal/board/ArduinoManager.java index 556c80082ce..d894855033b 100644 --- a/toolchains/arduino/org.eclipse.cdt.arduino.core/src/org/eclipse/cdt/arduino/core/internal/board/ArduinoManager.java +++ b/toolchains/arduino/org.eclipse.cdt.arduino.core/src/org/eclipse/cdt/arduino/core/internal/board/ArduinoManager.java @@ -90,7 +90,7 @@ public class ArduinoManager { return ArduinoPreferences.getArduinoHome().resolve(".version"); //$NON-NLS-1$ } - private void init() throws CoreException { + private synchronized void init() throws CoreException { if (props == null) { if (!Files.exists(ArduinoPreferences.getArduinoHome())) { try { @@ -219,12 +219,12 @@ public class ArduinoManager { return pkg != null ? pkg.getInstalledPlatform(architecture) : null; } - public Collection getAvailablePlatforms(IProgressMonitor monitor) throws CoreException { + public synchronized Collection getAvailablePlatforms(IProgressMonitor monitor) throws CoreException { List platforms = new ArrayList<>(); - Collection urls = ArduinoPreferences.getBoardUrlList(); - SubMonitor sub = SubMonitor.convert(monitor, urls.size() + 1); + URL[] urls = ArduinoPreferences.getBoardUrlList(); + SubMonitor sub = SubMonitor.convert(monitor, urls.length + 1); - sub.beginTask("Downloading package descriptions", urls.size()); //$NON-NLS-1$ + sub.beginTask("Downloading package descriptions", urls.length); //$NON-NLS-1$ for (URL url : urls) { Path packagePath = ArduinoPreferences.getArduinoHome() .resolve(Paths.get(url.getPath()).getFileName()); @@ -252,7 +252,7 @@ public class ArduinoManager { public void installPlatforms(Collection platforms, IProgressMonitor monitor) throws CoreException { SubMonitor sub = SubMonitor.convert(monitor, platforms.size()); for (ArduinoPlatform platform : platforms) { - sub.setTaskName(String.format("Installing %s", platform.getName())); //$NON-NLS-1$ + sub.setTaskName(String.format("Installing %s %s", platform.getName(), platform.getVersion())); //$NON-NLS-1$ platform.install(sub); sub.worked(1); } @@ -292,7 +292,7 @@ public class ArduinoManager { return result; } - private void initPackages() throws CoreException { + private synchronized void initPackages() throws CoreException { if (packages == null) { init(); packages = new HashMap<>(); @@ -326,7 +326,7 @@ public class ArduinoManager { packages = null; } - private ArduinoPackage getPackage(String packageName) throws CoreException { + public ArduinoPackage getPackage(String packageName) throws CoreException { if (packageName == null) { return null; } else { diff --git a/toolchains/arduino/org.eclipse.cdt.arduino.core/src/org/eclipse/cdt/arduino/core/internal/board/ArduinoPackage.java b/toolchains/arduino/org.eclipse.cdt.arduino.core/src/org/eclipse/cdt/arduino/core/internal/board/ArduinoPackage.java index 3aba4a82eda..19a9fffa1b9 100644 --- a/toolchains/arduino/org.eclipse.cdt.arduino.core/src/org/eclipse/cdt/arduino/core/internal/board/ArduinoPackage.java +++ b/toolchains/arduino/org.eclipse.cdt.arduino.core/src/org/eclipse/cdt/arduino/core/internal/board/ArduinoPackage.java @@ -92,24 +92,27 @@ public class ArduinoPackage { if (Files.isDirectory(getInstallPath())) { Path platformTxt = Paths.get("platform.txt"); //$NON-NLS-1$ try { - Files.find(getInstallPath().resolve("hardware"), 2, //$NON-NLS-1$ - (path, attrs) -> path.getFileName().equals(platformTxt)) - .forEach(path -> { - try (FileReader reader = new FileReader(path.toFile())) { - Properties platformProperties = new Properties(); - platformProperties.load(reader); - String arch = path.getName(path.getNameCount() - 2).toString(); - String version = platformProperties.getProperty("version"); //$NON-NLS-1$ + Path hardware = getInstallPath().resolve("hardware"); + if (Files.exists(hardware)) { + Files.find(hardware, 2, // $NON-NLS-1$ + (path, attrs) -> path.getFileName().equals(platformTxt)).forEach(path -> { + try (FileReader reader = new FileReader(path.toFile())) { + Properties platformProperties = new Properties(); + platformProperties.load(reader); + String arch = path.getName(path.getNameCount() - 2).toString(); + String version = platformProperties.getProperty("version"); //$NON-NLS-1$ - ArduinoPlatform platform = getPlatform(arch, version); - if (platform != null) { - platform.setPlatformProperties(platformProperties); - installedPlatforms.put(arch, platform); - } // TODO manually add it if was removed from index - } catch (IOException e) { - throw new RuntimeException(e); - } - }); + ArduinoPlatform platform = getPlatform(arch, version); + if (platform != null) { + platform.setPlatformProperties(platformProperties); + installedPlatforms.put(arch, platform); + } // TODO manually add it if was removed + // from index + } catch (IOException e) { + throw new RuntimeException(e); + } + }); + } } catch (IOException e) { throw Activator.coreException(e); } @@ -166,6 +169,18 @@ public class ArduinoPackage { return null; } + public ArduinoTool getLatestTool(String toolName) { + ArduinoTool latest = null; + for (ArduinoTool tool : tools) { + if (tool.getName().equals(toolName) && tool.isInstalled()) { + if (latest == null || ArduinoManager.compareVersions(tool.getVersion(), latest.getVersion()) > 0) { + latest = tool; + } + } + } + return latest; + } + @Override public boolean equals(Object obj) { if (obj instanceof ArduinoPackage) { diff --git a/toolchains/arduino/org.eclipse.cdt.arduino.core/src/org/eclipse/cdt/arduino/core/internal/board/ArduinoPlatform.java b/toolchains/arduino/org.eclipse.cdt.arduino.core/src/org/eclipse/cdt/arduino/core/internal/board/ArduinoPlatform.java index 3e85fa1b87a..26110ac91c0 100644 --- a/toolchains/arduino/org.eclipse.cdt.arduino.core/src/org/eclipse/cdt/arduino/core/internal/board/ArduinoPlatform.java +++ b/toolchains/arduino/org.eclipse.cdt.arduino.core/src/org/eclipse/cdt/arduino/core/internal/board/ArduinoPlatform.java @@ -20,7 +20,6 @@ import java.net.URL; import java.nio.file.Files; import java.nio.file.Path; import java.util.ArrayList; -import java.util.Arrays; import java.util.Collection; import java.util.HashMap; import java.util.List; @@ -31,7 +30,6 @@ import org.eclipse.cdt.arduino.core.internal.Activator; import org.eclipse.cdt.arduino.core.internal.ArduinoPreferences; import org.eclipse.cdt.arduino.core.internal.HierarchicalProperties; import org.eclipse.cdt.arduino.core.internal.Messages; -import org.eclipse.cdt.arduino.core.internal.build.ArduinoBuildConfiguration; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IStatus; @@ -209,39 +207,6 @@ public class ArduinoPlatform { return getPackage().getInstallPath().resolve("hardware").resolve(architecture); //$NON-NLS-1$ } - public List getIncludePath() { - Path installPath = getInstallPath(); - return Arrays.asList(installPath.resolve("cores/{build.core}"), //$NON-NLS-1$ - installPath.resolve("variants/{build.variant}")); //$NON-NLS-1$ - } - - private void getSources(Collection sources, Path dir, boolean recurse) { - for (File file : dir.toFile().listFiles()) { - if (file.isDirectory()) { - if (recurse) { - getSources(sources, file.toPath(), recurse); - } - } else { - if (ArduinoBuildConfiguration.isSource(file.getName())) { - sources.add(ArduinoBuildConfiguration.pathString(file.toPath())); - } - } - } - } - - public Collection getSources(String core, String variant) { - List sources = new ArrayList<>(); - Path srcPath = getInstallPath().resolve("cores").resolve(core); //$NON-NLS-1$ - if (srcPath.toFile().isDirectory()) { - getSources(sources, srcPath, true); - } - Path variantPath = getInstallPath().resolve("variants").resolve(variant); //$NON-NLS-1$ - if (variantPath.toFile().isDirectory()) { - getSources(sources, variantPath, true); - } - return sources; - } - private void initLibraries() throws CoreException { if (libraries == null) { libraries = new HashMap<>(); diff --git a/toolchains/arduino/org.eclipse.cdt.arduino.core/src/org/eclipse/cdt/arduino/core/internal/board/ArduinoTool.java b/toolchains/arduino/org.eclipse.cdt.arduino.core/src/org/eclipse/cdt/arduino/core/internal/board/ArduinoTool.java index c3a9bf42af2..2561cbcc2bd 100644 --- a/toolchains/arduino/org.eclipse.cdt.arduino.core/src/org/eclipse/cdt/arduino/core/internal/board/ArduinoTool.java +++ b/toolchains/arduino/org.eclipse.cdt.arduino.core/src/org/eclipse/cdt/arduino/core/internal/board/ArduinoTool.java @@ -87,6 +87,7 @@ public class ArduinoTool { for (ArduinoToolSystem system : systems) { if (system.isApplicable()) { system.install(monitor); + return; } } diff --git a/toolchains/arduino/org.eclipse.cdt.arduino.core/src/org/eclipse/cdt/arduino/core/internal/build/ArduinoBuildConfiguration.java b/toolchains/arduino/org.eclipse.cdt.arduino.core/src/org/eclipse/cdt/arduino/core/internal/build/ArduinoBuildConfiguration.java index 39af24d8fd0..877be21da5c 100644 --- a/toolchains/arduino/org.eclipse.cdt.arduino.core/src/org/eclipse/cdt/arduino/core/internal/build/ArduinoBuildConfiguration.java +++ b/toolchains/arduino/org.eclipse.cdt.arduino.core/src/org/eclipse/cdt/arduino/core/internal/build/ArduinoBuildConfiguration.java @@ -23,8 +23,10 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.HashMap; +import java.util.Iterator; import java.util.List; import java.util.Map; +import java.util.Map.Entry; import java.util.Properties; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -38,6 +40,7 @@ import org.eclipse.cdt.arduino.core.internal.board.ArduinoLibrary; 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.ArduinoTool; import org.eclipse.cdt.arduino.core.internal.board.ToolDependency; import org.eclipse.cdt.arduino.core.internal.remote.ArduinoRemoteConnection; import org.eclipse.cdt.core.CCorePlugin; @@ -79,6 +82,7 @@ public class ArduinoBuildConfiguration extends CBuildConfiguration implements Te 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 static final String MENU_QUALIFIER = "menu_"; //$NON-NLS-1$ private static ArduinoManager manager = Activator.getService(ArduinoManager.class); @@ -117,8 +121,7 @@ public class ArduinoBuildConfiguration extends CBuildConfiguration implements Te } ArduinoBuildConfiguration(IBuildConfiguration config, String name, ArduinoBoard board, String launchMode, - IToolChain toolChain) - throws CoreException { + IToolChain toolChain) throws CoreException { super(config, name, toolChain); this.board = board; this.launchMode = launchMode; @@ -148,10 +151,9 @@ public class ArduinoBuildConfiguration extends CBuildConfiguration implements Te if (menus != null) { Preferences settings = getSettings(); for (String id : menus.getChildren().keySet()) { - String key = ArduinoBoard.MENU_QUALIFIER + id; - String value = target.getRemoteConnection().getAttribute(key); + String value = target.getMenuValue(id); if (value != null) { - settings.put(key, value); + settings.put(MENU_QUALIFIER + id, value); } } @@ -164,7 +166,9 @@ public class ArduinoBuildConfiguration extends CBuildConfiguration implements Te } static String generateName(ArduinoBoard board, String launchMode) { - return "arduino." + board.getId() + '.' + launchMode; //$NON-NLS-1$ + ArduinoPlatform platform = board.getPlatform(); + ArduinoPackage pkg = platform.getPackage(); + return pkg.getName() + '.' + platform.getArchitecture() + '.' + board.getId() + '.' + launchMode; } @SuppressWarnings("unchecked") @@ -190,8 +194,7 @@ public class ArduinoBuildConfiguration extends CBuildConfiguration implements Te HierarchicalProperties menus = board.getMenus(); if (menus != null) { for (String id : menus.getChildren().keySet()) { - String key = ArduinoBoard.MENU_QUALIFIER + id; - if (!settings.get(key, "").equals(target.getRemoteConnection().getAttribute(key))) { //$NON-NLS-1$ + if (!settings.get(MENU_QUALIFIER + id, "").equals(target.getMenuValue(id))) { //$NON-NLS-1$ return false; } } @@ -211,19 +214,43 @@ public class ArduinoBuildConfiguration extends CBuildConfiguration implements Te // IDE generated properties properties = new Properties(); properties.put("runtime.platform.path", platform.getInstallPath().toString()); //$NON-NLS-1$ - properties.put("runtime.ide.version", "10607"); //$NON-NLS-1$ //$NON-NLS-2$ + properties.put("runtime.ide.version", "10608"); //$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 = getBuildConfiguration().getName(); if (configName.equals(IBuildConfiguration.DEFAULT_CONFIG_NAME)) { configName = "default"; //$NON-NLS-1$ } - properties.put("build.path", configName); //$NON-NLS-1$ + properties.put("build.path", "."); //$NON-NLS-1$ //$NON-NLS-2$ properties.put("build.variant.path", //$NON-NLS-1$ platform.getInstallPath().resolve("variants").resolve("{build.variant}").toString()); //$NON-NLS-1$ //$NON-NLS-2$ + // Everyone seems to want to use the avr-gcc and avrdude tools + ArduinoPackage arduinoPackage = manager.getPackage("arduino"); //$NON-NLS-1$ + ArduinoTool avrgcc = arduinoPackage.getLatestTool("avr-gcc"); //$NON-NLS-1$ + if (avrgcc != null) { + properties.put("runtime.tools.avr-gcc.path", avrgcc.getInstallPath().toString()); //$NON-NLS-1$ + } + ArduinoTool avrdude = arduinoPackage.getLatestTool("avrdude"); //$NON-NLS-1$ + if (avrdude != null) { + properties.put("runtime.tools.avrdude.path", avrdude.getInstallPath().toString()); //$NON-NLS-1$ + } + + // Super Platform + String core = board.getBoardProperties().getProperty("build.core"); //$NON-NLS-1$ + if (core.contains(":")) { //$NON-NLS-1$ + String[] segments = core.split(":"); //$NON-NLS-1$ + if (segments.length == 2) { + ArduinoPlatform superPlatform = manager.getInstalledPlatform(segments[0], + platform.getArchitecture()); + if (superPlatform != null) { + properties.putAll(superPlatform.getPlatformProperties()); + } + } + } + // Platform - properties.putAll(board.getPlatform().getPlatformProperties()); + properties.putAll(platform.getPlatformProperties()); // Tools for (ToolDependency toolDep : platform.getToolsDependencies()) { @@ -238,10 +265,18 @@ public class ArduinoBuildConfiguration extends CBuildConfiguration implements Te Preferences settings = getSettings(); HierarchicalProperties menus = board.getMenus(); if (menus != null) { - for (String menuId : menus.getChildren().keySet()) { - String value = settings.get(ArduinoBoard.MENU_QUALIFIER + menuId, ""); //$NON-NLS-1$ + for (Entry menuEntry : menus.getChildren().entrySet()) { + String key = menuEntry.getKey(); + String defaultValue; + Iterator i = menuEntry.getValue().getChildren().values().iterator(); + if (i.hasNext()) { + defaultValue = i.next().getValue(); + } else { + defaultValue = ""; //$NON-NLS-1$ + } + String value = settings.get(MENU_QUALIFIER + key, defaultValue); if (!value.isEmpty()) { - properties.putAll(board.getMenuProperties(menuId, value)); + properties.putAll(board.getMenuProperties(key, value)); } } } @@ -252,13 +287,6 @@ public class ArduinoBuildConfiguration extends CBuildConfiguration implements Te return properties; } - public IFile getMakeFile() throws CoreException { - IFolder buildFolder = (IFolder) getBuildContainer(); - ArduinoBoard board = getBoard(); - String makeFileName = board.getId() + ".mk"; //$NON-NLS-1$ - return buildFolder.getFile(makeFileName); - } - public Map getBuildModel() throws CoreException { IProject project = getProject(); ArduinoBoard board = getBoard(); @@ -301,7 +329,7 @@ public class ArduinoBuildConfiguration extends CBuildConfiguration implements Te buildModel.put("project_name", project.getName()); //$NON-NLS-1$ String includes = null; - for (Path include : platform.getIncludePath()) { + for (Path include : getIncludePath(platform, properties)) { if (includes == null) { includes = "-I"; //$NON-NLS-1$ } else { @@ -316,10 +344,35 @@ public class ArduinoBuildConfiguration extends CBuildConfiguration implements Te } properties.put("includes", includes); //$NON-NLS-1$ - Path platformPath = platform.getInstallPath(); - buildModel.put("platform_path", pathString(platformPath).replace("+", "\\+")); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ - buildModel.put("platform_srcs", //$NON-NLS-1$ - platform.getSources(properties.getProperty("build.core"), properties.getProperty("build.variant"))); //$NON-NLS-1$ //$NON-NLS-2$ + ArduinoPlatform corePlatform = platform; + String core = properties.getProperty("build.core"); //$NON-NLS-1$ + if (core.contains(":")) { //$NON-NLS-1$ + String[] segments = core.split(":"); //$NON-NLS-1$ + if (segments.length == 2) { + corePlatform = manager.getInstalledPlatform(segments[0], platform.getArchitecture()); + core = segments[1]; + } + } + Path corePath = corePlatform.getInstallPath().resolve("cores").resolve(core); //$NON-NLS-1$ + buildModel.put("platform_core_path", pathString(corePath)); //$NON-NLS-1$ + List coreSources = new ArrayList<>(); + getSources(coreSources, corePath, true); + buildModel.put("platform_core_srcs", coreSources); //$NON-NLS-1$ + + ArduinoPlatform variantPlatform = platform; + String variant = properties.getProperty("build.variant"); //$NON-NLS-1$ + if (variant.contains(":")) { //$NON-NLS-1$ + String[] segments = variant.split(":"); //$NON-NLS-1$ + if (segments.length == 2) { + variantPlatform = manager.getInstalledPlatform(segments[0], platform.getArchitecture()); + variant = segments[1]; + } + } + Path variantPath = variantPlatform.getInstallPath().resolve("variants").resolve(variant); //$NON-NLS-1$ + buildModel.put("platform_variant_path", pathString(variantPath)); //$NON-NLS-1$ + List variantSources = new ArrayList<>(); + getSources(variantSources, variantPath, true); + buildModel.put("platform_variant_srcs", variantSources); //$NON-NLS-1$ properties.put("object_file", "$@"); //$NON-NLS-1$ //$NON-NLS-2$ properties.put("source_file", "$<"); //$NON-NLS-1$ //$NON-NLS-2$ @@ -340,13 +393,27 @@ public class ArduinoBuildConfiguration extends CBuildConfiguration implements Te return buildModel; } + private static void getSources(Collection sources, Path dir, boolean recurse) { + for (File file : dir.toFile().listFiles()) { + if (file.isDirectory()) { + if (recurse) { + getSources(sources, file.toPath(), recurse); + } + } else { + if (ArduinoBuildConfiguration.isSource(file.getName())) { + sources.add(ArduinoBuildConfiguration.pathString(file.toPath())); + } + } + } + } + public IFile generateMakeFile(IProgressMonitor monitor) throws CoreException { IFolder buildFolder = (IFolder) getBuildContainer(); if (!buildFolder.exists()) { buildFolder.create(true, true, monitor); } - IFile makefile = getMakeFile(); + IFile makefile = buildFolder.getFile("Makefile"); //$NON-NLS-1$ Map buildModel = getBuildModel(); @@ -402,28 +469,35 @@ public class ArduinoBuildConfiguration extends CBuildConfiguration implements Te } } - private String resolvePropertyValue(String value, Properties dict) { + private String resolvePropertyValue(String value, Properties dict) throws CoreException { String last; do { last = value; for (int i = value.indexOf('{'); i >= 0; i = value.indexOf('{', i)) { i++; + if (value.charAt(i) == '{') { + i++; + continue; + } + int n = value.indexOf('}', i); if (n >= 0) { String p2 = value.substring(i, n); String r2 = dict.getProperty(p2); if (r2 != null) { value = value.replace('{' + p2 + '}', r2); + } else { + throw Activator.coreException(String.format("Undefined key %s", p2), null); } } i = n; } } while (!value.equals(last)); - return value; + return value.replace("}}", "}").replace("{{", "{"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ } - private String resolveProperty(String property, Properties dict) { + private String resolveProperty(String property, Properties dict) throws CoreException { String value = dict.getProperty(property); return value != null ? resolvePropertyValue(value, dict) : null; } @@ -433,17 +507,17 @@ public class ArduinoBuildConfiguration extends CBuildConfiguration implements Te } public String[] getBuildCommand() throws CoreException { - return new String[] { getMakeCommand(), "-f", getMakeFile().getName() }; //$NON-NLS-1$ + return new String[] { getMakeCommand() }; } public String[] getCleanCommand() throws CoreException { - return new String[] { getMakeCommand(), "-f", getMakeFile().getName(), "clean" }; //$NON-NLS-1$ //$NON-NLS-2$ + return new String[] { getMakeCommand(), "clean" }; //$NON-NLS-1$ } public String[] getSizeCommand() throws CoreException { // TODO this shouldn't be in the makefile // should be like the upload command - return new String[] { getMakeCommand(), "-f", getMakeFile().getName(), "size" }; //$NON-NLS-1$ //$NON-NLS-2$ + return new String[] { getMakeCommand(), "size" }; //$NON-NLS-1$ } public String getCodeSizeRegex() throws CoreException { @@ -466,8 +540,21 @@ public class ArduinoBuildConfiguration extends CBuildConfiguration implements Te public String[] getUploadCommand(String serialPort) throws CoreException { String toolName = getProperties().getProperty("upload.tool"); //$NON-NLS-1$ + ArduinoPlatform platform = getBoard().getPlatform(); + if (toolName.contains(":")) { //$NON-NLS-1$ + String[] segments = toolName.split(":"); //$NON-NLS-1$ + if (segments.length == 2) { + platform = manager.getInstalledPlatform(segments[0], platform.getArchitecture()); + toolName = segments[1]; + } + } Properties properties = getProperties(); + + ArduinoTool uploadTool = platform.getPackage().getLatestTool(toolName); + if (uploadTool != null) { + properties.putAll(uploadTool.getToolProperties()); + } properties.put("serial.port", serialPort); //$NON-NLS-1$ // Little bit of weirdness needed for the bossac tool @@ -482,7 +569,7 @@ public class ArduinoBuildConfiguration extends CBuildConfiguration implements Te properties.put("config.path", "{tools." + toolName + ".config.path}"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ // properties for the tool flattened - HierarchicalProperties toolsProps = new HierarchicalProperties(getBoard().getPlatform().getPlatformProperties()) + HierarchicalProperties toolsProps = new HierarchicalProperties(platform.getPlatformProperties()) .getChild("tools"); //$NON-NLS-1$ if (toolsProps != null) { HierarchicalProperties toolProps = toolsProps.getChild(toolName); @@ -493,13 +580,14 @@ public class ArduinoBuildConfiguration extends CBuildConfiguration implements Te // TODO make this a preference properties.put("upload.verbose", properties.getProperty("upload.params.verbose", "")); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ + properties.put("upload.verify", properties.getProperty("upload.params.verify", "")); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ // TODO needed this for esptool properties.put("upload.resetmethod", "ck"); //$NON-NLS-1$ //$NON-NLS-2$ String command = resolveProperty("upload.pattern", properties); //$NON-NLS-1$ if (command == null) { - return new String[] { "command not specified" }; //$NON-NLS-1$ + throw Activator.coreException("Upload command not specified", null); } if (isWindows) { return splitCommand(command); @@ -508,6 +596,31 @@ public class ArduinoBuildConfiguration extends CBuildConfiguration implements Te } } + private Collection getIncludePath(ArduinoPlatform platform, Properties properties) throws CoreException { + ArduinoPlatform corePlatform = platform; + String core = properties.getProperty("build.core"); //$NON-NLS-1$ + if (core.contains(":")) { //$NON-NLS-1$ + String[] segments = core.split(":"); //$NON-NLS-1$ + if (segments.length == 2) { + corePlatform = manager.getInstalledPlatform(segments[0], platform.getArchitecture()); + core = segments[1]; + } + } + + ArduinoPlatform variantPlatform = platform; + String variant = properties.getProperty("build.variant"); //$NON-NLS-1$ + if (variant.contains(":")) { //$NON-NLS-1$ + String[] segments = variant.split(":"); //$NON-NLS-1$ + if (segments.length == 2) { + variantPlatform = manager.getInstalledPlatform(segments[0], platform.getArchitecture()); + variant = segments[1]; + } + } + + return Arrays.asList(corePlatform.getInstallPath().resolve("cores").resolve(core), //$NON-NLS-1$ + variantPlatform.getInstallPath().resolve("variants").resolve(variant)); //$NON-NLS-1$ + } + // Scanner Info Cache private String[] cachedIncludePath; private String cachedInfoCommand; @@ -537,14 +650,27 @@ public class ArduinoBuildConfiguration extends CBuildConfiguration implements Te String commandString = resolveProperty(recipe, properties); List includePath = new ArrayList<>(); - includePath.addAll(platform.getIncludePath()); + includePath.addAll(getIncludePath(platform, properties)); Collection libs = manager.getLibraries(getProject()); for (ArduinoLibrary lib : libs) { includePath.addAll(lib.getIncludePath()); } - String[] includes = includePath.stream() - .map(path -> resolvePropertyValue(path.toString(), properties)).collect(Collectors.toList()) - .toArray(new String[includePath.size()]); + String[] includes = null; + try { + includes = includePath.stream().map(path -> { + try { + return resolvePropertyValue(path.toString(), properties); + } catch (CoreException e) { + throw new RuntimeException(e); + } + }).collect(Collectors.toList()).toArray(new String[includePath.size()]); + } catch (RuntimeException e) { + if (e.getCause() != null && e.getCause() instanceof CoreException) { + throw (CoreException) e.getCause(); + } else { + throw e; + } + } // Use cache if we can if (cachedScannerInfo != null && cachedInfoCommand.equals(commandString) diff --git a/toolchains/arduino/org.eclipse.cdt.arduino.core/src/org/eclipse/cdt/arduino/core/internal/build/ArduinoBuildConfigurationProvider.java b/toolchains/arduino/org.eclipse.cdt.arduino.core/src/org/eclipse/cdt/arduino/core/internal/build/ArduinoBuildConfigurationProvider.java index 0dfda4599c2..7b4f6adbe5d 100644 --- a/toolchains/arduino/org.eclipse.cdt.arduino.core/src/org/eclipse/cdt/arduino/core/internal/build/ArduinoBuildConfigurationProvider.java +++ b/toolchains/arduino/org.eclipse.cdt.arduino.core/src/org/eclipse/cdt/arduino/core/internal/build/ArduinoBuildConfigurationProvider.java @@ -39,49 +39,28 @@ public class ArduinoBuildConfigurationProvider implements ICBuildConfigurationPr @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", "avr", "Arduino/Genuino Uno"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ - if (board == null) { - Collection boards = arduinoManager.getInstalledBoards(); - if (!boards.isEmpty()) { - board = boards.iterator().next(); - } - } - 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; - } + if (config.getName().equals(IBuildConfiguration.DEFAULT_CONFIG_NAME)) { + // Use the good ol' Uno as the default + ArduinoBoard board = arduinoManager.getBoard("arduino", "avr", "uno"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ + if (board == null) { + Collection boards = arduinoManager.getInstalledBoards(); + if (!boards.isEmpty()) { + board = boards.iterator().next(); } } + if (board != null) { + // Create the toolChain + IToolChainManager toolChainManager = Activator.getService(IToolChainManager.class); + IToolChainProvider provider = toolChainManager.getProvider(ArduinoToolChainProvider.ID); + IToolChain toolChain = new ArduinoToolChain(provider, config); + toolChainManager.addToolChain(toolChain); - // not found, create one - String configName = ArduinoBuildConfiguration.generateName(board, launchMode); - IBuildConfiguration config = configManager.createBuildConfiguration(this, project, configName, - null); - - // Create the toolChain - IToolChainManager toolChainManager = Activator.getService(IToolChainManager.class); - IToolChainProvider provider = toolChainManager.getProvider(ArduinoToolChainProvider.ID); - IToolChain toolChain = new ArduinoToolChain(provider, config); - toolChainManager.addToolChain(toolChain); - - ArduinoBuildConfiguration arduinoConfig = new ArduinoBuildConfiguration(config, configName, board, - launchMode, toolChain); - arduinoConfig.setActive(null); - configManager.addBuildConfiguration(config, arduinoConfig); - return arduinoConfig; + return new ArduinoBuildConfiguration(config, name, board, "run", toolChain); //$NON-NLS-1$ + } + return null; + } else { + return new ArduinoBuildConfiguration(config, name); } - return null; } public ArduinoBuildConfiguration getConfiguration(IProject project, ArduinoRemoteConnection target, diff --git a/toolchains/arduino/org.eclipse.cdt.arduino.core/src/org/eclipse/cdt/arduino/core/internal/remote/ArduinoRemoteConnection.java b/toolchains/arduino/org.eclipse.cdt.arduino.core/src/org/eclipse/cdt/arduino/core/internal/remote/ArduinoRemoteConnection.java index 380ec26be88..30d3ca89230 100644 --- a/toolchains/arduino/org.eclipse.cdt.arduino.core/src/org/eclipse/cdt/arduino/core/internal/remote/ArduinoRemoteConnection.java +++ b/toolchains/arduino/org.eclipse.cdt.arduino.core/src/org/eclipse/cdt/arduino/core/internal/remote/ArduinoRemoteConnection.java @@ -17,12 +17,15 @@ import java.util.Map; 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.board.ArduinoPackage; +import org.eclipse.cdt.arduino.core.internal.board.ArduinoPlatform; import org.eclipse.cdt.serial.SerialPort; import org.eclipse.core.runtime.CoreException; import org.eclipse.remote.core.IRemoteCommandShellService; import org.eclipse.remote.core.IRemoteConnection; import org.eclipse.remote.core.IRemoteConnectionChangeListener; import org.eclipse.remote.core.IRemoteConnectionPropertyService; +import org.eclipse.remote.core.IRemoteConnectionWorkingCopy; import org.eclipse.remote.core.IRemoteProcess; import org.eclipse.remote.core.RemoteConnectionChangeEvent; import org.eclipse.remote.serial.core.SerialPortCommandShell; @@ -31,10 +34,12 @@ public class ArduinoRemoteConnection implements IRemoteConnectionPropertyService, IRemoteCommandShellService, IRemoteConnectionChangeListener { public static final String TYPE_ID = "org.eclipse.cdt.arduino.core.connectionType"; //$NON-NLS-1$ - public static final String PORT_NAME = "arduinoPortName"; //$NON-NLS-1$ - public static final String PACKAGE_NAME = "arduinoPackageName"; //$NON-NLS-1$ - public static final String PLATFORM_NAME = "arduinoPlatformName"; //$NON-NLS-1$ - public static final String BOARD_NAME = "arduinoBoardName"; //$NON-NLS-1$ + + private static final String PORT_NAME = "arduinoPortName"; //$NON-NLS-1$ + private static final String PACKAGE_NAME = "arduinoPackageName"; //$NON-NLS-1$ + private static final String PLATFORM_NAME = "arduinoPlatformName"; //$NON-NLS-1$ + private static final String BOARD_NAME = "arduinoBoardName"; //$NON-NLS-1$ + private static final String MENU_QUALIFIER = "menu_"; //$NON-NLS-1$ private final IRemoteConnection remoteConnection; private SerialPort serialPort; @@ -47,6 +52,28 @@ public class ArduinoRemoteConnection remoteConnection.addConnectionChangeListener(this); } + public static void setBoardId(IRemoteConnectionWorkingCopy workingCopy, ArduinoBoard board) { + workingCopy.setAttribute(BOARD_NAME, board.getId()); + + ArduinoPlatform platform = board.getPlatform(); + workingCopy.setAttribute(PLATFORM_NAME, platform.getArchitecture()); + + ArduinoPackage pkg = platform.getPackage(); + workingCopy.setAttribute(PACKAGE_NAME, pkg.getName()); + } + + public static void setPortName(IRemoteConnectionWorkingCopy workingCopy, String portName) { + workingCopy.setAttribute(PORT_NAME, portName); + } + + public static void setMenuValue(IRemoteConnectionWorkingCopy workingCopy, String key, String value) { + workingCopy.setAttribute(MENU_QUALIFIER + key, value); + } + + public String getMenuValue(String key) { + return remoteConnection.getAttribute(MENU_QUALIFIER + key); + } + @Override public void connectionChanged(RemoteConnectionChangeEvent event) { if (event.getType() == RemoteConnectionChangeEvent.CONNECTION_REMOVED) { diff --git a/toolchains/arduino/org.eclipse.cdt.arduino.core/templates/Makefile b/toolchains/arduino/org.eclipse.cdt.arduino.core/templates/Makefile index 48888521aa8..82ec9471ff9 100644 --- a/toolchains/arduino/org.eclipse.cdt.arduino.core/templates/Makefile +++ b/toolchains/arduino/org.eclipse.cdt.arduino.core/templates/Makefile @@ -15,19 +15,35 @@ PROJECT_OBJS = \ -PLATFORM_OBJS = \ -<#list platform_srcs as file> -<#assign cpp = file?matches("${platform_path}/(.*)\\.cpp")> +PLATFORM_CORE_OBJS = \ +<#list platform_core_srcs as file> +<#assign cpp = file?matches("${platform_core_path}/(.*)\\.cpp")> <#if cpp> - ${build_path}/platform/${cpp?groups[1]}.cpp.o \ + ${build_path}/core/${cpp?groups[1]}.cpp.o \ -<#assign c = file?matches("${platform_path}/(.*)\\.c")> +<#assign c = file?matches("${platform_core_path}/(.*)\\.c")> <#if c> - ${build_path}/platform/${c?groups[1]}.c.o \ + ${build_path}/core/${c?groups[1]}.c.o \ -<#assign S = file?matches("${platform_path}/(.*)\\.S")> +<#assign S = file?matches("${platform_core_path}/(.*)\\.S")> <#if S> - ${build_path}/platform/${S?groups[1]}.S.o \ + ${build_path}/core/${S?groups[1]}.S.o \ + + + +PLATFORM_VARIANT_OBJS = \ +<#list platform_variant_srcs as file> +<#assign cpp = file?matches("${platform_variant_path}/(.*)\\.cpp")> +<#if cpp> + ${build_path}/variant/${cpp?groups[1]}.cpp.o \ + +<#assign c = file?matches("${platform_variant_path}/(.*)\\.c")> +<#if c> + ${build_path}/variant/${c?groups[1]}.c.o \ + +<#assign S = file?matches("${platform_variant_path}/(.*)\\.S")> +<#if S> + ${build_path}/variant/${S?groups[1]}.S.o \ @@ -80,7 +96,7 @@ ${build_path}/${project_name}.bin: ${build_path}/${project_name}.elf ${build_path}/${project_name}.elf: $(PROJECT_OBJS) $(LIBRARIES_OBJS) ${build_path}/core.a ${recipe_c_combine_pattern} -${build_path}/core.a: $(PLATFORM_OBJS) +${build_path}/core.a: $(PLATFORM_CORE_OBJS) $(PLATFORM_VARIANT_OBJS) clean: $(RMDIR) ${build_path} @@ -102,34 +118,69 @@ ${build_path}/project/${cpp?groups[1]}.cpp.d: ; -<#list platform_srcs as file> -<#assign cpp = file?matches("${platform_path}/(.*)\\.cpp")> +<#list platform_core_srcs as file> +<#assign cpp = file?matches("${platform_core_path}/(.*)\\.cpp")> <#if cpp> -${build_path}/platform/${cpp?groups[1]}.cpp.o: ${file} ${build_path}/platform/${cpp?groups[1]}.cpp.d +${build_path}/core/${cpp?groups[1]}.cpp.o: ${file} ${build_path}/core/${cpp?groups[1]}.cpp.d @$(call mymkdir,$(dir $@)) ${recipe_cpp_o_pattern} ${recipe_ar_pattern} -${build_path}/platform/${cpp?groups[1]}.cpp.d: ; +${build_path}/core/${cpp?groups[1]}.cpp.d: ; --include ${build_path}/platform/${cpp?groups[1]}.cpp.d +-include ${build_path}/core/${cpp?groups[1]}.cpp.d -<#assign c = file?matches("${platform_path}/(.*)\\.c")> +<#assign c = file?matches("${platform_core_path}/(.*)\\.c")> <#if c> -${build_path}/platform/${c?groups[1]}.c.o: ${file} ${build_path}/platform/${c?groups[1]}.c.d +${build_path}/core/${c?groups[1]}.c.o: ${file} ${build_path}/core/${c?groups[1]}.c.d @$(call mymkdir,$(dir $@)) ${recipe_c_o_pattern} ${recipe_ar_pattern} -${build_path}/platform/${c?groups[1]}.c.d: ; +${build_path}/core/${c?groups[1]}.c.d: ; --include ${build_path}/platform/${c?groups[1]}.c.d +-include ${build_path}/core/${c?groups[1]}.c.d -<#assign S = file?matches("${platform_path}/(.*)\\.S")> +<#assign S = file?matches("${platform_core_path}/(.*)\\.S")> <#if S> -${build_path}/platform/${S?groups[1]}.S.o: ${file} +${build_path}/core/${S?groups[1]}.S.o: ${file} + @$(call mymkdir,$(dir $@)) + ${recipe_S_o_pattern} + ${recipe_ar_pattern} + + + + +<#list platform_variant_srcs as file> +<#assign cpp = file?matches("${platform_variant_path}/(.*)\\.cpp")> +<#if cpp> +${build_path}/variant/${cpp?groups[1]}.cpp.o: ${file} ${build_path}/variant/${cpp?groups[1]}.cpp.d + @$(call mymkdir,$(dir $@)) + ${recipe_cpp_o_pattern} + ${recipe_ar_pattern} + +${build_path}/variant/${cpp?groups[1]}.cpp.d: ; + +-include ${build_path}/variant/${cpp?groups[1]}.cpp.d + + +<#assign c = file?matches("${platform_variant_path}/(.*)\\.c")> +<#if c> +${build_path}/variant/${c?groups[1]}.c.o: ${file} ${build_path}/variant/${c?groups[1]}.c.d + @$(call mymkdir,$(dir $@)) + ${recipe_c_o_pattern} + ${recipe_ar_pattern} + +${build_path}/variant/${c?groups[1]}.c.d: ; + +-include ${build_path}/variant/${c?groups[1]}.c.d + + +<#assign S = file?matches("${platform_variant_path}/(.*)\\.S")> +<#if S> +${build_path}/variant/${S?groups[1]}.S.o: ${file} @$(call mymkdir,$(dir $@)) ${recipe_S_o_pattern} ${recipe_ar_pattern} diff --git a/toolchains/arduino/org.eclipse.cdt.arduino.ui/plugin.xml b/toolchains/arduino/org.eclipse.cdt.arduino.ui/plugin.xml index fa5d081dea3..36d3d0218ac 100644 --- a/toolchains/arduino/org.eclipse.cdt.arduino.ui/plugin.xml +++ b/toolchains/arduino/org.eclipse.cdt.arduino.ui/plugin.xml @@ -86,12 +86,6 @@ id="org.eclipse.cdt.arduino.preference.page" name="%preferencePage.name"> - - diff --git a/toolchains/arduino/org.eclipse.cdt.arduino.ui/src/org/eclipse/cdt/arduino/ui/internal/remote/ArduinoTargetPropertyPage.java b/toolchains/arduino/org.eclipse.cdt.arduino.ui/src/org/eclipse/cdt/arduino/ui/internal/remote/ArduinoTargetPropertyPage.java index 63cdd9dbaaa..a024a3aa821 100644 --- a/toolchains/arduino/org.eclipse.cdt.arduino.ui/src/org/eclipse/cdt/arduino/ui/internal/remote/ArduinoTargetPropertyPage.java +++ b/toolchains/arduino/org.eclipse.cdt.arduino.ui/src/org/eclipse/cdt/arduino/ui/internal/remote/ArduinoTargetPropertyPage.java @@ -96,15 +96,11 @@ public class ArduinoTargetPropertyPage extends PropertyPage implements IWorkbenc IRemoteConnection remoteConnection = getElement().getAdapter(IRemoteConnection.class); IRemoteConnectionWorkingCopy workingCopy = remoteConnection.getWorkingCopy(); - String portName = portSelector.getItem(portSelector.getSelectionIndex()); - workingCopy.setAttribute(ArduinoRemoteConnection.PORT_NAME, portName); - ArduinoBoard board = boards[boardSelector.getSelectionIndex()]; - workingCopy.setAttribute(ArduinoRemoteConnection.BOARD_NAME, board.getId()); - ArduinoPlatform platform = board.getPlatform(); - workingCopy.setAttribute(ArduinoRemoteConnection.PLATFORM_NAME, platform.getArchitecture()); - ArduinoPackage pkg = platform.getPackage(); - workingCopy.setAttribute(ArduinoRemoteConnection.PACKAGE_NAME, pkg.getName()); + ArduinoRemoteConnection.setBoardId(workingCopy, board); + + String portName = portSelector.getItem(portSelector.getSelectionIndex()); + ArduinoRemoteConnection.setPortName(workingCopy, portName); try { workingCopy.save(); diff --git a/toolchains/arduino/org.eclipse.cdt.arduino.ui/src/org/eclipse/cdt/arduino/ui/internal/remote/BoardPropertyControl.java b/toolchains/arduino/org.eclipse.cdt.arduino.ui/src/org/eclipse/cdt/arduino/ui/internal/remote/BoardPropertyControl.java index b0bfacd1808..38362faf463 100644 --- a/toolchains/arduino/org.eclipse.cdt.arduino.ui/src/org/eclipse/cdt/arduino/ui/internal/remote/BoardPropertyControl.java +++ b/toolchains/arduino/org.eclipse.cdt.arduino.ui/src/org/eclipse/cdt/arduino/ui/internal/remote/BoardPropertyControl.java @@ -188,15 +188,8 @@ public class BoardPropertyControl extends Composite { } public void apply(IRemoteConnectionWorkingCopy workingCopy) { - workingCopy.setAttribute(ArduinoRemoteConnection.PORT_NAME, portName); - - workingCopy.setAttribute(ArduinoRemoteConnection.BOARD_NAME, board.getId()); - - ArduinoPlatform platform = board.getPlatform(); - workingCopy.setAttribute(ArduinoRemoteConnection.PLATFORM_NAME, platform.getArchitecture()); - - ArduinoPackage pkg = platform.getPackage(); - workingCopy.setAttribute(ArduinoRemoteConnection.PACKAGE_NAME, pkg.getName()); + ArduinoRemoteConnection.setBoardId(workingCopy, board); + ArduinoRemoteConnection.setPortName(workingCopy, portName); String key = null; for (Control control : menuControls) { @@ -208,7 +201,7 @@ public class BoardPropertyControl extends Composite { String value = ((List) combo.getData()).get(combo.getSelectionIndex()); if (key != null) { - workingCopy.setAttribute(ArduinoBoard.MENU_QUALIFIER + key, value); + ArduinoRemoteConnection.setMenuValue(workingCopy, key, value); } } }