diff options
author | Doug Schaefer | 2016-03-31 15:28:28 +0000 |
---|---|---|
committer | Gerrit Code Review @ Eclipse.org | 2016-04-14 20:19:37 +0000 |
commit | 6e1b9b408de9c7854c9f7434089c920dbad2b9ad (patch) | |
tree | 6e6023f16f3b534bdac1bcc3e90be098c308488f /qt | |
parent | ad0d665a196aa7a389d8a5c54edd0286641ed1ae (diff) | |
download | org.eclipse.cdt-6e1b9b408de9c7854c9f7434089c920dbad2b9ad.tar.gz org.eclipse.cdt-6e1b9b408de9c7854c9f7434089c920dbad2b9ad.tar.xz org.eclipse.cdt-6e1b9b408de9c7854c9f7434089c920dbad2b9ad.zip |
Tighter integration of new build system with cdt.core.
Move the new build system to cdt.core and remove the previous
plugins. Hook the new system into scanner info and environment
variable manager.
Clean up API in preparation for Neon and API lockdown. Hook up
Qt to the new APIs.
Add discovery of MSYS2's toolchain and Qt and Qt's MinGW toolchain.
Change-Id: I85b1a91da4a44e86f0e9da9310f8106c894623e0
Diffstat (limited to 'qt')
29 files changed, 970 insertions, 617 deletions
diff --git a/qt/org.eclipse.cdt.qt.core/META-INF/MANIFEST.MF b/qt/org.eclipse.cdt.qt.core/META-INF/MANIFEST.MF index 1a7116b75d4..82018a33421 100644 --- a/qt/org.eclipse.cdt.qt.core/META-INF/MANIFEST.MF +++ b/qt/org.eclipse.cdt.qt.core/META-INF/MANIFEST.MF @@ -17,11 +17,10 @@ Require-Bundle: org.eclipse.core.runtime, org.eclipse.debug.core;bundle-version="3.10.0", org.eclipse.cdt.debug.core, org.freemarker;bundle-version="2.3.22", - org.eclipse.cdt.build.core;bundle-version="1.0.0", - org.eclipse.cdt.build.gcc.core;bundle-version="1.0.0", org.eclipse.cdt.dsf.gdb;bundle-version="5.0.0", org.eclipse.cdt.dsf;bundle-version="2.6.0", - org.eclipse.tools.templates.freemarker;bundle-version="1.0.0" + org.eclipse.tools.templates.freemarker;bundle-version="1.0.0", + org.eclipse.cdt.build.gcc.core;bundle-version="1.0.0" Bundle-RequiredExecutionEnvironment: JavaSE-1.8 Bundle-ActivationPolicy: lazy Bundle-Localization: plugin diff --git a/qt/org.eclipse.cdt.qt.core/plugin.xml b/qt/org.eclipse.cdt.qt.core/plugin.xml index e7a5bc5ab1a..d6eb6d5449b 100644 --- a/qt/org.eclipse.cdt.qt.core/plugin.xml +++ b/qt/org.eclipse.cdt.qt.core/plugin.xml @@ -1,7 +1,8 @@ <?xml version="1.0" encoding="UTF-8"?> <?eclipse version="3.4"?> <plugin> - <extension-point id="qtInstallTargetMapper" name="Qt Install Target Mapper" schema="schema/qtInstallTargetMapper.exsd"/> + <extension-point id="qtInstallProvider" name="Qt Install Provider" schema="schema/qtInstallProvider.exsd"/> + <extension-point id="qtToolChainMapper" name="Qt ToolChain Mapper" schema="schema/qtToolChainMapper.exsd"/> <extension point="org.eclipse.cdt.core.templates"> @@ -159,30 +160,6 @@ </configProvider> </extension> <extension - point="org.eclipse.cdt.core.ScannerInfoProvider2"> - <provider - builder="org.eclipse.cdt.qt.core.qtBuilder" - class="org.eclipse.cdt.internal.qt.core.build.QtScannerInfoProvider"> - </provider> - </extension> - <extension - point="org.eclipse.core.runtime.adapters"> - <factory - adaptableType="org.eclipse.core.resources.IBuildConfiguration" - class="org.eclipse.cdt.internal.qt.core.build.QtBuildConfigurationFactory"> - <adapter - type="org.eclipse.cdt.qt.core.QtBuildConfiguration"> - </adapter> - </factory> - </extension> - <extension - point="org.eclipse.cdt.qt.core.qtInstallTargetMapper"> - <mapper - class="org.eclipse.cdt.internal.qt.core.LocalQtInstallTargetMapper" - targetTypeId="org.eclipse.launchbar.core.launchTargetType.local"> - </mapper> - </extension> - <extension point="org.eclipse.debug.core.launchConfigurationTypes"> <launchConfigurationType delegate="org.eclipse.cdt.internal.qt.core.launch.QtLocalRunLaunchConfigDelegate" @@ -204,4 +181,44 @@ type="org.eclipse.cdt.qt.core.launchConfigurationType"> </launchDelegate> </extension> + <extension + point="org.eclipse.cdt.core.buildConfigProvider"> + <provider + class="org.eclipse.cdt.internal.qt.core.build.QtBuildConfigurationProvider" + id="org.eclipse.cdt.qt.core.qtBuildConfigProvider" + natureId="org.eclipse.cdt.qt.core.qtNature"> + </provider> + </extension> + <extension + point="org.eclipse.cdt.core.toolChainProvider"> + <provider + class="org.eclipse.cdt.qt.core.QtMinGWToolChainProvider"> + </provider> + </extension> + <extension + point="org.eclipse.cdt.qt.core.qtInstallProvider"> + <provider + class="org.eclipse.cdt.internal.qt.core.provider.Msys2QtInstallProvider"> + </provider> + <provider + class="org.eclipse.cdt.internal.qt.core.provider.HomebrewQtInstallProvider"> + </provider> + <provider + class="org.eclipse.cdt.internal.qt.core.provider.QtInstallProvider"> + </provider> + </extension> + <extension + point="org.eclipse.cdt.qt.core.qtToolChainMapper"> + <mapping + spec="macx-clang"> + <property + key="os" + value="macosx"> + </property> + <property + key="arch" + value="x86_64"> + </property> + </mapping> + </extension> </plugin> diff --git a/qt/org.eclipse.cdt.qt.core/schema/qtInstallTargetMapper.exsd b/qt/org.eclipse.cdt.qt.core/schema/qtInstallProvider.exsd index 4dbb8ca5f7f..e065898df18 100644 --- a/qt/org.eclipse.cdt.qt.core/schema/qtInstallTargetMapper.exsd +++ b/qt/org.eclipse.cdt.qt.core/schema/qtInstallProvider.exsd @@ -3,7 +3,7 @@ <schema targetNamespace="org.eclipse.cdt.qt.core" xmlns="http://www.w3.org/2001/XMLSchema"> <annotation> <appinfo> - <meta.schema plugin="org.eclipse.cdt.qt.core" id="qtInstallTargetMapper" name="Qt Install Target Mapper"/> + <meta.schema plugin="org.eclipse.cdt.qt.core" id="qtInstallProvider" name="Qt Install Provider"/> </appinfo> <documentation> [Enter description of this extension point.] @@ -18,7 +18,7 @@ </annotation> <complexType> <sequence> - <element ref="mapper"/> + <element ref="provider" minOccurs="1" maxOccurs="unbounded"/> </sequence> <attribute name="point" type="string" use="required"> <annotation> @@ -47,25 +47,15 @@ </complexType> </element> - <element name="mapper"> + <element name="provider"> <complexType> - <attribute name="targetTypeId" type="string" use="required"> - <annotation> - <documentation> - - </documentation> - <appinfo> - <meta.attribute kind="identifier" basedOn="org.eclipse.launchbar.core.launchTargetTypes/launchTargetType/@id"/> - </appinfo> - </annotation> - </attribute> <attribute name="class" type="string" use="required"> <annotation> <documentation> </documentation> <appinfo> - <meta.attribute kind="java" basedOn=":org.eclipse.cdt.qt.core.IQtInstallTargetMapper"/> + <meta.attribute kind="java" basedOn=":org.eclipse.cdt.qt.core.IQtInstallProvider"/> </appinfo> </annotation> </attribute> diff --git a/qt/org.eclipse.cdt.qt.core/schema/qtToolChainMapper.exsd b/qt/org.eclipse.cdt.qt.core/schema/qtToolChainMapper.exsd new file mode 100644 index 00000000000..5e0211e0299 --- /dev/null +++ b/qt/org.eclipse.cdt.qt.core/schema/qtToolChainMapper.exsd @@ -0,0 +1,121 @@ +<?xml version='1.0' encoding='UTF-8'?> +<!-- Schema file written by PDE --> +<schema targetNamespace="org.eclipse.cdt.qt.core" xmlns="http://www.w3.org/2001/XMLSchema"> +<annotation> + <appinfo> + <meta.schema plugin="org.eclipse.cdt.qt.core" id="qtToolChainMapper" name="Qt ToolChain Mapper"/> + </appinfo> + <documentation> + [Enter description of this extension point.] + </documentation> + </annotation> + + <element name="extension"> + <annotation> + <appinfo> + <meta.element /> + </appinfo> + </annotation> + <complexType> + <sequence minOccurs="1" maxOccurs="unbounded"> + <element ref="mapping"/> + </sequence> + <attribute name="point" type="string" use="required"> + <annotation> + <documentation> + + </documentation> + </annotation> + </attribute> + <attribute name="id" type="string"> + <annotation> + <documentation> + + </documentation> + </annotation> + </attribute> + <attribute name="name" type="string"> + <annotation> + <documentation> + + </documentation> + <appinfo> + <meta.attribute translatable="true"/> + </appinfo> + </annotation> + </attribute> + </complexType> + </element> + + <element name="mapping"> + <complexType> + <sequence minOccurs="0" maxOccurs="unbounded"> + <element ref="property"/> + </sequence> + <attribute name="spec" type="string"> + <annotation> + <documentation> + + </documentation> + </annotation> + </attribute> + </complexType> + </element> + + <element name="property"> + <complexType> + <attribute name="key" type="string"> + <annotation> + <documentation> + + </documentation> + </annotation> + </attribute> + <attribute name="value" type="string"> + <annotation> + <documentation> + + </documentation> + </annotation> + </attribute> + </complexType> + </element> + + <annotation> + <appinfo> + <meta.section type="since"/> + </appinfo> + <documentation> + [Enter the first release in which this extension point appears.] + </documentation> + </annotation> + + <annotation> + <appinfo> + <meta.section type="examples"/> + </appinfo> + <documentation> + [Enter extension point usage example here.] + </documentation> + </annotation> + + <annotation> + <appinfo> + <meta.section type="apiinfo"/> + </appinfo> + <documentation> + [Enter API information here.] + </documentation> + </annotation> + + <annotation> + <appinfo> + <meta.section type="implementation"/> + </appinfo> + <documentation> + [Enter information about supplied implementation of this extension point.] + </documentation> + </annotation> + + +</schema> diff --git a/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/internal/qt/core/Activator.java b/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/internal/qt/core/Activator.java index 0e719146788..5739000726d 100644 --- a/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/internal/qt/core/Activator.java +++ b/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/internal/qt/core/Activator.java @@ -12,10 +12,8 @@ import java.io.IOException; import javax.script.ScriptException; import org.eclipse.cdt.core.model.CModelException; -import org.eclipse.cdt.internal.qt.core.build.QtBuildConfigurationFactory; import org.eclipse.cdt.qt.core.IQMLAnalyzer; import org.eclipse.cdt.qt.core.IQtInstallManager; -import org.eclipse.core.resources.ResourcesPlugin; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IStatus; @@ -47,7 +45,6 @@ public class Activator extends Plugin { public static final QualifiedName QTINDEX_PROP_NAME = new QualifiedName(ID, "qtindex"); //$NON-NLS-1$ private static Activator instance; - private static QtBuildConfigurationFactory.Cleanup configCleanup; public static Activator getDefault() { return instance; @@ -76,18 +73,12 @@ public class Activator extends Plugin { return Status.OK_STATUS; } }.schedule(); - - configCleanup = new QtBuildConfigurationFactory.Cleanup(); - ResourcesPlugin.getWorkspace().addResourceChangeListener(configCleanup); } @Override public void stop(BundleContext context) throws Exception { // QMakeProjectInfoManager.stop(); - ResourcesPlugin.getWorkspace().removeResourceChangeListener(configCleanup); - configCleanup = null; - super.stop(context); } diff --git a/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/internal/qt/core/LocalQtInstallTargetMapper.java b/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/internal/qt/core/LocalQtInstallTargetMapper.java deleted file mode 100644 index 45fbcee596e..00000000000 --- a/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/internal/qt/core/LocalQtInstallTargetMapper.java +++ /dev/null @@ -1,43 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2015 QNX Software Systems and others. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - *******************************************************************************/ -package org.eclipse.cdt.internal.qt.core; - -import org.eclipse.cdt.build.core.IToolChain; -import org.eclipse.cdt.build.gcc.core.GCCToolChainType; -import org.eclipse.cdt.qt.core.IQtInstall; -import org.eclipse.cdt.qt.core.IQtInstallTargetMapper; -import org.eclipse.core.runtime.Platform; -import org.eclipse.launchbar.core.target.ILaunchTarget; - -public class LocalQtInstallTargetMapper implements IQtInstallTargetMapper { - - @Override - public boolean supported(IQtInstall qtInstall, ILaunchTarget launchTarget) { - String os = Platform.getOS(); - String arch = Platform.getOSArch(); - - switch (qtInstall.getSpec()) { - case "macx-clang": //$NON-NLS-1$ - return Platform.OS_MACOSX.equals(os) && Platform.ARCH_X86_64.equals(arch); - case "win32-g++": //$NON-NLS-1$ - return Platform.OS_WIN32.equals(os); - default: - return false; - } - } - - @Override - public boolean supported(IQtInstall qtInstall, IToolChain toolChain) { - if (toolChain.getType().equals(GCCToolChainType.ID)) { - String spec = qtInstall.getSpec(); - return spec.endsWith("-clang") || spec.endsWith("-g++"); //$NON-NLS-1$ //$NON-NLS-2$ - } - return false; - } - -} 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 3cc3d7d92f9..c3e8c423761 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 @@ -16,21 +16,14 @@ import org.eclipse.cdt.qt.core.IQtInstall; public class QtInstall implements IQtInstall { - private final String name; private final Path qmakePath; private String spec; - public QtInstall(String name, Path qmakePath) { - this.name = name; + public QtInstall(Path qmakePath) { this.qmakePath = qmakePath; } @Override - public String getName() { - return name; - } - - @Override public Path getQmakePath() { return qmakePath; } 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 c71cb9afa82..ce8e6cb230c 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 @@ -7,31 +7,29 @@ *******************************************************************************/ package org.eclipse.cdt.internal.qt.core; +import java.nio.file.Path; import java.nio.file.Paths; import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.Map; -import org.eclipse.cdt.build.core.IToolChain; +import org.eclipse.cdt.core.build.IToolChain; import org.eclipse.cdt.qt.core.IQtInstall; import org.eclipse.cdt.qt.core.IQtInstallManager; -import org.eclipse.cdt.qt.core.IQtInstallTargetMapper; +import org.eclipse.cdt.qt.core.IQtInstallProvider; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IConfigurationElement; -import org.eclipse.core.runtime.IExtension; import org.eclipse.core.runtime.IExtensionPoint; import org.eclipse.core.runtime.Platform; import org.eclipse.core.runtime.preferences.ConfigurationScope; -import org.eclipse.launchbar.core.target.ILaunchTarget; import org.osgi.service.prefs.BackingStoreException; import org.osgi.service.prefs.Preferences; public class QtInstallManager implements IQtInstallManager { - private Map<String, IQtInstall> installs; - private Map<String, IConfigurationElement> mapperElements; - private Map<String, IQtInstallTargetMapper> mappers; + private Map<Path, IQtInstall> installs; + private Map<String, IConfigurationElement> toolChainMap; private Preferences getPreferences() { return ConfigurationScope.INSTANCE.getNode(Activator.ID).node("qtInstalls"); //$NON-NLS-1$ @@ -43,11 +41,25 @@ public class QtInstallManager implements IQtInstallManager { try { Preferences prefs = getPreferences(); for (String key : prefs.keys()) { - installs.put(key, new QtInstall(key, Paths.get(prefs.get(key, "/")))); //$NON-NLS-1$ + QtInstall install = new QtInstall(Paths.get(prefs.get(key, "/"))); //$NON-NLS-1$ + installs.put(install.getQmakePath(), install); } } catch (BackingStoreException e) { Activator.log(e); } + + // Auto installs + IExtensionPoint point = Platform.getExtensionRegistry().getExtensionPoint(Activator.ID, "qtInstallProvider"); //$NON-NLS-1$ + for (IConfigurationElement element : point.getConfigurationElements()) { + try { + IQtInstallProvider provider = (IQtInstallProvider) element.createExecutableExtension("class"); //$NON-NLS-1$ + for (IQtInstall install : provider.getInstalls()) { + installs.put(install.getQmakePath(), install); + } + } catch (CoreException e) { + Activator.log(e); + } + } } } @@ -63,7 +75,8 @@ public class QtInstallManager implements IQtInstallManager { } // Add new ones - for (String key : installs.keySet()) { + for (Path path : installs.keySet()) { + String key = path.toString(); if (prefs.get(key, null) == null) { prefs.put(key, installs.get(key).getQmakePath().toString()); } @@ -84,64 +97,49 @@ public class QtInstallManager implements IQtInstallManager { @Override public void addInstall(IQtInstall qt) { initInstalls(); - installs.put(qt.getName(), qt); + installs.put(qt.getQmakePath(), qt); saveInstalls(); } @Override - public IQtInstall getInstall(String name) { + public IQtInstall getInstall(Path qmakePath) { initInstalls(); - return installs.get(name); + return installs.get(qmakePath); } @Override public void removeInstall(IQtInstall install) { - installs.remove(install.getName()); + installs.remove(install.getQmakePath()); saveInstalls(); } @Override - public boolean supports(IQtInstall install, ILaunchTarget target) { - if (mapperElements == null) { - // init the extension point - mapperElements = new HashMap<>(); - mappers = new HashMap<>(); - - IExtensionPoint point = Platform.getExtensionRegistry() - .getExtensionPoint(Activator.ID + ".qtInstallTargetMapper"); //$NON-NLS-1$ - for (IExtension extension : point.getExtensions()) { - for (IConfigurationElement element : extension.getConfigurationElements()) { - String targetTypeId = element.getAttribute("targetTypeId"); //$NON-NLS-1$ - mapperElements.put(targetTypeId, element); + public boolean supports(IQtInstall install, IToolChain toolChain) { + if (toolChainMap == null) { + toolChainMap = new HashMap<>(); + IExtensionPoint point = Platform.getExtensionRegistry().getExtensionPoint(Activator.ID, "qtToolChainMapper"); //$NON-NLS-1$ + for (IConfigurationElement element : point.getConfigurationElements()) { + if (element.getName().equals("mapping")) { //$NON-NLS-1$ + String spec = element.getAttribute("spec"); //$NON-NLS-1$ + toolChainMap.put(spec, element); } } } - - String targetTypeId = target.getTypeId(); - IQtInstallTargetMapper mapper = mappers.get(targetTypeId); - if (mapper == null) { - IConfigurationElement element = mapperElements.get(targetTypeId); - if (element != null) { - try { - mapper = (IQtInstallTargetMapper) element.createExecutableExtension("class"); //$NON-NLS-1$ - mappers.put(targetTypeId, mapper); - } catch (CoreException e) { - Activator.log(e); + + IConfigurationElement element = toolChainMap.get(install.getSpec()); + if (element != null) { + for (IConfigurationElement property : element.getChildren("property")) { //$NON-NLS-1$ + String key = property.getAttribute("key"); //$NON-NLS-1$ + String value = property.getAttribute("value"); //$NON-NLS-1$ + if (!value.equals(toolChain.getProperty(key))) { + return false; } } - } - - if (mapper == null) { + return true; + } else { + // Don't know so returning false return false; } - - return mapper.supported(install, target); - } - - @Override - public boolean supports(IQtInstall install, IToolChain toolChain) { - // TODO need another extension point for this - return true; } } diff --git a/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/qt/core/QtBuildConfiguration.java b/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/internal/qt/core/build/QtBuildConfiguration.java index 881400776ef..93722eb532e 100644 --- a/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/qt/core/QtBuildConfiguration.java +++ b/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/internal/qt/core/build/QtBuildConfiguration.java @@ -5,7 +5,7 @@ * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html *******************************************************************************/ -package org.eclipse.cdt.qt.core; +package org.eclipse.cdt.internal.qt.core.build; import java.io.BufferedReader; import java.io.File; @@ -19,25 +19,26 @@ import java.util.HashMap; import java.util.List; import java.util.Map; -import org.eclipse.cdt.build.core.CBuildConfiguration; -import org.eclipse.cdt.build.core.IToolChain; -import org.eclipse.cdt.core.CCorePlugin; -import org.eclipse.cdt.core.model.ILanguage; -import org.eclipse.cdt.core.model.LanguageManager; -import org.eclipse.cdt.core.parser.IExtendedScannerInfo; +import org.eclipse.cdt.core.build.CBuildConfiguration; +import org.eclipse.cdt.core.build.ICBuildConfiguration; +import org.eclipse.cdt.core.build.IToolChain; +import org.eclipse.cdt.core.envvar.IEnvironmentVariable; import org.eclipse.cdt.core.parser.IScannerInfo; +import org.eclipse.cdt.core.parser.IScannerInfoChangeListener; import org.eclipse.cdt.internal.qt.core.Activator; +import org.eclipse.cdt.qt.core.IQtBuildConfiguration; +import org.eclipse.cdt.qt.core.IQtInstall; +import org.eclipse.cdt.qt.core.IQtInstallManager; import org.eclipse.core.resources.IBuildConfiguration; import org.eclipse.core.resources.IFile; +import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IResource; import org.eclipse.core.runtime.CoreException; -import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Platform; -import org.eclipse.core.runtime.Status; import org.osgi.service.prefs.BackingStoreException; import org.osgi.service.prefs.Preferences; -public class QtBuildConfiguration extends CBuildConfiguration { +public class QtBuildConfiguration extends CBuildConfiguration implements ICBuildConfiguration, IQtBuildConfiguration { private static final String QTINSTALL_NAME = "cdt.qt.install.name"; //$NON-NLS-1$ private static final String LAUNCH_MODE = "cdt.qt.launchMode"; //$NON-NLS-1$ @@ -53,7 +54,7 @@ public class QtBuildConfiguration extends CBuildConfiguration { String installName = settings.get(QTINSTALL_NAME, ""); //$NON-NLS-1$ if (!installName.isEmpty()) { IQtInstallManager manager = Activator.getService(IQtInstallManager.class); - qtInstall = manager.getInstall(installName); + qtInstall = manager.getInstall(Paths.get(installName)); } else { qtInstall = null; } @@ -61,14 +62,14 @@ public class QtBuildConfiguration extends CBuildConfiguration { launchMode = settings.get(LAUNCH_MODE, ""); //$NON-NLS-1$ } - public QtBuildConfiguration(IBuildConfiguration config, IToolChain toolChain, IQtInstall qtInstall, - String launchMode) { + QtBuildConfiguration(IBuildConfiguration config, IToolChain toolChain, IQtInstall qtInstall, String launchMode) + throws CoreException { super(config, toolChain); this.qtInstall = qtInstall; this.launchMode = launchMode; Preferences settings = getSettings(); - settings.put(QTINSTALL_NAME, qtInstall.getName()); + settings.put(QTINSTALL_NAME, qtInstall.getQmakePath().toString()); settings.put(LAUNCH_MODE, launchMode); try { settings.flush(); @@ -77,18 +78,26 @@ public class QtBuildConfiguration extends CBuildConfiguration { } } + @Override + public <T> T getAdapter(Class<T> adapter) { + return super.getAdapter(adapter); + } + public IQtInstall getQtInstall() { return qtInstall; } + @Override public String getLaunchMode() { return launchMode; } - public String getQmakeCommand() { - return qtInstall.getQmakePath().toString(); + @Override + public Path getQmakeCommand() { + return qtInstall.getQmakePath(); } + @Override public String getQmakeConfig() { switch (launchMode) { case "run": //$NON-NLS-1$ @@ -112,7 +121,8 @@ public class QtBuildConfiguration extends CBuildConfiguration { } } - public Path getProgramPath() throws CoreException { + @Override + public Path getProgramPath() { String projectName = getProject().getName(); switch (Platform.getOS()) { case Platform.OS_MACOSX: @@ -120,45 +130,24 @@ public class QtBuildConfiguration extends CBuildConfiguration { // in the config // TODO also need to pull the app name out of the pro // file name - Path appFolder = getBuildDirectory().resolve(projectName + ".app"); - Path contentsFolder = appFolder.resolve("Contents"); - Path macosFolder = contentsFolder.resolve("MacOS"); + 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: - Path releaseFolder = getBuildDirectory().resolve("release"); - return releaseFolder.resolve(projectName + ".exe"); - default: - throw new CoreException( - new Status(IStatus.ERROR, Activator.ID, "platform not supported: " + Platform.getOS())); + 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$ } - } - - public void setProgramEnvironment(Map<String, String> env) { - Path libPath = getQtInstall().getLibPath(); - switch (Platform.getOS()) { - case Platform.OS_MACOSX: - String libPathEnv = env.get("DYLD_LIBRARY_PATH"); - if (libPathEnv == null) { - libPathEnv = libPath.toString(); - } else { - libPathEnv = libPath.toString() + File.pathSeparator + libPathEnv; - } - env.put("DYLD_LIBRARY_PATH", libPathEnv); - break; - case Platform.OS_WIN32: - String path = env.get("PATH"); - // TODO really need a bin path - // and resolve doesn't work properly on Windows - path = "C:/Qt/5.5/mingw492_32/bin;" + path; - env.put("PATH", path); - break; + default: + Path releaseFolder = getBuildDirectory().resolve("release"); //$NON-NLS-1$ + return releaseFolder.resolve(projectName); } } public String getProperty(String key) { if (properties == null) { List<String> cmd = new ArrayList<>(); - cmd.add(getQmakeCommand()); + cmd.add(getQmakeCommand().toString()); cmd.add("-E"); //$NON-NLS-1$ String config = getQmakeConfig(); @@ -170,7 +159,6 @@ public class QtBuildConfiguration extends CBuildConfiguration { try { ProcessBuilder procBuilder = new ProcessBuilder(cmd).directory(getProjectFile().getParent().toFile()); - getToolChain().setEnvironment(procBuilder.environment()); Process proc = procBuilder.start(); try (BufferedReader reader = new BufferedReader(new InputStreamReader(proc.getInputStream()))) { properties = new HashMap<>(); @@ -192,58 +180,67 @@ public class QtBuildConfiguration extends CBuildConfiguration { } @Override - public IScannerInfo getScannerInfo(IResource resource) throws IOException { - IScannerInfo info = getCachedScannerInfo(resource); - if (info == null) { - String cxx = getProperty("QMAKE_CXX"); //$NON-NLS-1$ - if (cxx == null) { - Activator.log("No QMAKE_CXX for " + qtInstall.getSpec()); //$NON-NLS-1$ - return null; - } - String[] cxxSplit = cxx.split(" "); //$NON-NLS-1$ - String command = cxxSplit[0]; + public IEnvironmentVariable getVariable(String name) { + // TODO Auto-generated method stub + return null; + } - List<String> args = new ArrayList<>(); - for (int i = 1; i < cxxSplit.length; ++i) { - args.add(cxxSplit[i]); - } - args.addAll(Arrays.asList(getProperty("QMAKE_CXXFLAGS").split(" "))); //$NON-NLS-1$ //$NON-NLS-2$ - args.add("-o"); //$NON-NLS-1$ - args.add("-"); //$NON-NLS-1$ - - String srcFile; - if (resource instanceof IFile) { - srcFile = resource.getLocation().toOSString(); - // Only add file if it's an IFile - args.add(srcFile); - } else { - // Doesn't matter, the toolchain will create a tmp file for this - srcFile = "scannerInfo.cpp"; //$NON-NLS-1$ - } + @Override + public IEnvironmentVariable[] getVariables() { + // TODO + return new IEnvironmentVariable[0]; + } - String[] includePaths = getProperty("INCLUDEPATH").split(" "); //$NON-NLS-1$ //$NON-NLS-2$ - for (int i = 0; i < includePaths.length; ++i) { - Path path = Paths.get(includePaths[i]); - if (!path.isAbsolute()) { - includePaths[i] = getBuildDirectory().resolve(path).toString(); - } - } + @Override + public IScannerInfo getScannerInformation(IResource resource) { + IProject project = resource.getProject(); + IQtInstall qtInstall = getQtInstall(); - ILanguage language = LanguageManager.getInstance() - .getLanguage(CCorePlugin.getContentType(getProject(), srcFile), getProject()); // $NON-NLS-1$ - Path dir = Paths.get(getProject().getLocationURI()); - IExtendedScannerInfo extendedInfo = getToolChain().getScannerInfo(command, args, - Arrays.asList(includePaths), resource, dir); - putScannerInfo(language, extendedInfo); - info = extendedInfo; + String cxx = getProperty("QMAKE_CXX"); //$NON-NLS-1$ + if (cxx == null) { + Activator.log("No QMAKE_CXX for " + qtInstall.getSpec()); //$NON-NLS-1$ + return null; + } + String[] cxxSplit = cxx.split(" "); //$NON-NLS-1$ + Path command = Paths.get(cxxSplit[0]); + + List<String> args = new ArrayList<>(); + for (int i = 1; i < cxxSplit.length; ++i) { + args.add(cxxSplit[i]); } - return info; + args.addAll(Arrays.asList(getProperty("QMAKE_CXXFLAGS").split(" "))); //$NON-NLS-1$ //$NON-NLS-2$ + args.add("-o"); //$NON-NLS-1$ + args.add("-"); //$NON-NLS-1$ + + String srcFile; + if (resource instanceof IFile) { + srcFile = resource.getLocation().toOSString(); + // Only add file if it's an IFile + args.add(srcFile); + } else { + // Doesn't matter, the toolchain will create a tmp file for this + srcFile = "scannerInfo.cpp"; //$NON-NLS-1$ + } + + String[] includePaths = getProperty("INCLUDEPATH").split(" "); //$NON-NLS-1$ //$NON-NLS-2$ + for (int i = 0; i < includePaths.length; ++i) { + Path path = Paths.get(includePaths[i]); + if (!path.isAbsolute()) { + includePaths[i] = getBuildDirectory().resolve(path).toString(); + } + } + + Path dir = Paths.get(project.getLocationURI()); + return getToolChain().getScannerInfo(getBuildConfiguration(), command, args, Arrays.asList(includePaths), + resource, dir); + } + + @Override + public void subscribe(IResource resource, IScannerInfoChangeListener listener) { } @Override - public void clearScannerInfoCache() throws CoreException { - super.clearScannerInfoCache(); - properties = null; + public void unsubscribe(IResource resource, IScannerInfoChangeListener listener) { } } diff --git a/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/internal/qt/core/build/QtBuildConfigurationFactory.java b/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/internal/qt/core/build/QtBuildConfigurationFactory.java deleted file mode 100644 index 0faab232710..00000000000 --- a/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/internal/qt/core/build/QtBuildConfigurationFactory.java +++ /dev/null @@ -1,179 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2015 QNX Software Systems and others. All rights reserved. This - * program and the accompanying materials are made available under the terms of - * the Eclipse Public License v1.0 which accompanies this distribution, and is - * available at http://www.eclipse.org/legal/epl-v10.html - *******************************************************************************/ -package org.eclipse.cdt.internal.qt.core.build; - -import java.util.HashMap; -import java.util.HashSet; -import java.util.Map; -import java.util.Set; - -import org.eclipse.cdt.build.core.IToolChain; -import org.eclipse.cdt.build.core.IToolChainManager; -import org.eclipse.cdt.internal.qt.core.Activator; -import org.eclipse.cdt.internal.qt.core.QtNature; -import org.eclipse.cdt.qt.core.IQtInstall; -import org.eclipse.cdt.qt.core.IQtInstallManager; -import org.eclipse.cdt.qt.core.QtBuildConfiguration; -import org.eclipse.core.resources.IBuildConfiguration; -import org.eclipse.core.resources.IProject; -import org.eclipse.core.resources.IProjectDescription; -import org.eclipse.core.resources.IResource; -import org.eclipse.core.resources.IResourceChangeEvent; -import org.eclipse.core.resources.IResourceChangeListener; -import org.eclipse.core.runtime.CoreException; -import org.eclipse.core.runtime.IAdapterFactory; -import org.eclipse.core.runtime.IProgressMonitor; -import org.eclipse.core.runtime.IStatus; -import org.eclipse.core.runtime.Status; -import org.eclipse.launchbar.core.target.ILaunchTarget; -import org.eclipse.launchbar.core.target.ILaunchTargetManager; - -public class QtBuildConfigurationFactory implements IAdapterFactory { - - private static IQtInstallManager qtInstallManager = Activator.getService(IQtInstallManager.class); - private static IToolChainManager toolChainManager = Activator.getService(IToolChainManager.class); - - private static Map<IBuildConfiguration, QtBuildConfiguration> cache = new HashMap<>(); - - @Override - public Class<?>[] getAdapterList() { - return new Class<?>[] { QtBuildConfiguration.class }; - } - - @SuppressWarnings("unchecked") - @Override - public <T> T getAdapter(Object adaptableObject, Class<T> adapterType) { - if (adapterType.equals(QtBuildConfiguration.class) && adaptableObject instanceof IBuildConfiguration) { - IBuildConfiguration config = (IBuildConfiguration) adaptableObject; - synchronized (cache) { - QtBuildConfiguration qtConfig = cache.get(config); - if (qtConfig == null) { - if (!config.getName().equals(IBuildConfiguration.DEFAULT_CONFIG_NAME)) { - qtConfig = new QtBuildConfiguration(config); - cache.put(config, qtConfig); - return (T) qtConfig; - } else { - // Default to local - ILaunchTargetManager targetManager = Activator.getService(ILaunchTargetManager.class); - ILaunchTarget localTarget = targetManager - .getLaunchTargetsOfType(ILaunchTargetManager.localLaunchTargetTypeId)[0]; - qtConfig = createDefaultConfig(config, localTarget); - if (qtConfig != null) { - cache.put(config, qtConfig); - return (T) qtConfig; - } - - // Just find a combination that works - for (ILaunchTarget target : targetManager.getLaunchTargets()) { - if (!target.equals(localTarget)) { - qtConfig = createDefaultConfig(config, localTarget); - if (qtConfig != null) { - cache.put(config, qtConfig); - return (T) qtConfig; - } - } - } - - // TODO if we don't have a target, need another way to - // match whatever qtInstalls we have with matching - // toolchains - } - } - return (T) qtConfig; - } - } - return null; - } - - private static QtBuildConfiguration createDefaultConfig(IBuildConfiguration config, ILaunchTarget target) { - for (IQtInstall qtInstall : qtInstallManager.getInstalls()) { - if (qtInstallManager.supports(qtInstall, target)) { - // Find the toolchain - for (IToolChain toolChain : toolChainManager.getToolChainsSupporting(target)) { - if (qtInstallManager.supports(qtInstall, toolChain)) { - return new QtBuildConfiguration(config, toolChain, qtInstall, "run"); //$NON-NLS-1$ - } - } - } - } - - return null; - } - - public static QtBuildConfiguration getConfig(IProject project, String launchMode, ILaunchTarget target, - IProgressMonitor monitor) throws CoreException { - // return it if it exists already - for (IBuildConfiguration config : project.getBuildConfigs()) { - QtBuildConfiguration qtConfig = config.getAdapter(QtBuildConfiguration.class); - if (qtConfig != null) { - IQtInstall qtInstall = qtConfig.getQtInstall(); - if (qtInstall != null && qtInstallManager.supports(qtInstall, target) - && launchMode.equals(qtConfig.getLaunchMode())) { - return qtConfig; - } - } - } - - // Nope, create it - for (IQtInstall qtInstall : qtInstallManager.getInstalls()) { - if (qtInstallManager.supports(qtInstall, target)) { - // Create the build config - Set<String> configNames = new HashSet<>(); - for (IBuildConfiguration config : project.getBuildConfigs()) { - configNames.add(config.getName()); - } - String baseName = qtInstall.getSpec() + "." + launchMode; //$NON-NLS-1$ - String newName = baseName; - int n = 0; - while (configNames.contains(newName)) { - newName = baseName + (++n); - } - configNames.add(newName); - IProjectDescription projectDesc = project.getDescription(); - projectDesc.setBuildConfigs(configNames.toArray(new String[configNames.size()])); - project.setDescription(projectDesc, monitor); - - // Find the toolchain - IToolChainManager toolChainManager = Activator.getService(IToolChainManager.class); - for (IToolChain toolChain : toolChainManager.getToolChainsSupporting(target)) { - if (qtInstallManager.supports(qtInstall, toolChain)) { - QtBuildConfiguration qtConfig = new QtBuildConfiguration(project.getBuildConfig(newName), - toolChain, qtInstall, launchMode); - return qtConfig; - // TODO what if there's more than toolChain supported? - } - } - } - } - - // No appropriate Qt Install - throw new CoreException( - new Status(IStatus.ERROR, Activator.ID, "No appropriate Qt SDK found for target " + target.getId())); - } - - public static class Cleanup implements IResourceChangeListener { - @Override - public void resourceChanged(IResourceChangeEvent event) { - if (event.getType() == IResourceChangeEvent.PRE_CLOSE - || event.getType() == IResourceChangeEvent.PRE_DELETE) { - if (event.getResource().getType() == IResource.PROJECT) { - IProject project = event.getResource().getProject(); - if (project.isOpen() && project.exists() && QtNature.hasNature(project)) { - try { - for (IBuildConfiguration config : project.getBuildConfigs()) { - cache.remove(config); - } - } catch (CoreException e) { - Activator.log(e); - } - } - } - } - } - } - -}
\ No newline at end of file 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 new file mode 100644 index 00000000000..f0bbed84e37 --- /dev/null +++ b/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/internal/qt/core/build/QtBuildConfigurationProvider.java @@ -0,0 +1,164 @@ +/******************************************************************************* + * 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.build; + +import java.util.HashMap; +import java.util.Map; + +import org.eclipse.cdt.core.build.ICBuildConfiguration; +import org.eclipse.cdt.core.build.ICBuildConfigurationManager; +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.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; +import org.eclipse.launchbar.core.target.ILaunchTarget; + +public class QtBuildConfigurationProvider implements ICBuildConfigurationProvider { + + public static final String ID = "org.eclipse.cdt.qt.core.qtBuildConfigProvider"; //$NON-NLS-1$ + + private IToolChainManager toolChainManager = Activator.getService(IToolChainManager.class); + private IQtInstallManager qtInstallManager = Activator.getService(IQtInstallManager.class); + private ICBuildConfigurationManager configManager = Activator.getService(ICBuildConfigurationManager.class); + + @Override + public String getId() { + return ID; + } + + @Override + public ICBuildConfiguration getCBuildConfiguration(IBuildConfiguration config) { + try { + // Double check to make sure this config is ours + if (!config.getName().startsWith(getId() + '/')) { + return null; + } + + if (!config.getProject().hasNature(QtNature.ID)) { + return null; + } + + return new QtBuildConfiguration(config); + } catch (CoreException e) { + 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<String, String> 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, + IProgressMonitor monitor) throws CoreException { + 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; + } + } + } + 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, toolChain, qtInstall, + launchMode); + configManager.addBuildConfiguration(config, qtConfig); + return qtConfig; + } + } + + return null; + } + + public QtBuildConfiguration createConfiguration(IProject project, ILaunchTarget target, String launchMode, + IProgressMonitor monitor) throws CoreException { + // Find the toolchains + Map<String, String> properties = new HashMap<>(); + String os = target.getAttribute(ILaunchTarget.ATTR_OS, null); + if (os != null) { + properties.put(IToolChain.ATTR_OS, os); + } + String arch = target.getAttribute(ILaunchTarget.ATTR_ARCH, null); + if (arch != null) { + properties.put(IToolChain.ATTR_ARCH, arch); + } + + for (IToolChain toolChain : toolChainManager.getToolChainsMatching(properties)) { + 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, toolChain, qtInstall, + launchMode); + configManager.addBuildConfiguration(config, qtConfig); + return qtConfig; + } + } + } + + return null; + } + +} diff --git a/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/internal/qt/core/build/QtBuilder.java b/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/internal/qt/core/build/QtBuilder.java index 688b0309a03..2689c43a74b 100644 --- a/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/internal/qt/core/build/QtBuilder.java +++ b/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/internal/qt/core/build/QtBuilder.java @@ -7,28 +7,38 @@ *******************************************************************************/ package org.eclipse.cdt.internal.qt.core.build; +import java.io.File; import java.io.IOException; +import java.nio.file.Files; import java.nio.file.Path; +import java.nio.file.Paths; import java.util.ArrayList; +import java.util.HashMap; import java.util.List; import java.util.Map; -import org.eclipse.cdt.build.core.IConsoleService; -import org.eclipse.cdt.build.core.IToolChain; +import org.eclipse.cdt.core.CCorePlugin; +import org.eclipse.cdt.core.ConsoleOutputStream; +import org.eclipse.cdt.core.ErrorParserManager; +import org.eclipse.cdt.core.build.BuildCommandRunner; +import org.eclipse.cdt.core.build.ICBuildConfiguration; +import org.eclipse.cdt.core.model.ICModelMarker; +import org.eclipse.cdt.core.resources.ACBuilder; +import org.eclipse.cdt.core.resources.IConsole; import org.eclipse.cdt.internal.qt.core.Activator; import org.eclipse.cdt.internal.qt.core.Messages; -import org.eclipse.cdt.qt.core.QtBuildConfiguration; +import org.eclipse.cdt.qt.core.IQtBuildConfiguration; +import org.eclipse.core.resources.IBuildConfiguration; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IResource; -import org.eclipse.core.resources.IncrementalProjectBuilder; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Platform; import org.eclipse.core.runtime.Status; -public class QtBuilder extends IncrementalProjectBuilder { +public class QtBuilder extends ACBuilder { public static final String ID = Activator.ID + ".qtBuilder"; //$NON-NLS-1$ @@ -36,70 +46,162 @@ public class QtBuilder extends IncrementalProjectBuilder { protected IProject[] build(int kind, Map<String, String> args, IProgressMonitor monitor) throws CoreException { IProject project = getProject(); try { - IConsoleService console = Activator.getService(IConsoleService.class); - QtBuildConfiguration qtConfig = getBuildConfig().getAdapter(QtBuildConfiguration.class); + project.deleteMarkers(ICModelMarker.C_MODEL_PROBLEM_MARKER, false, IResource.DEPTH_INFINITE); + + IConsole console = CCorePlugin.getDefault().getConsole(); + console.start(project); + ConsoleOutputStream errStream = console.getErrorStream(); + ConsoleOutputStream outStream = console.getOutputStream(); + + ICBuildConfiguration cconfig = getBuildConfig().getAdapter(ICBuildConfiguration.class); + IQtBuildConfiguration qtConfig = cconfig.getAdapter(QtBuildConfiguration.class); if (qtConfig == null) { // Qt hasn't been configured yet print a message and bale - console.writeError(Messages.QtBuilder_0); + errStream.write(Messages.QtBuilder_0); return null; } - IToolChain toolChain = qtConfig.getToolChain(); - Path buildDir = qtConfig.getBuildDirectory(); - if (!buildDir.resolve("Makefile").toFile().exists()) { //$NON-NLS-1$ - // Need to run qmake - List<String> command = new ArrayList<>(); - command.add(qtConfig.getQmakeCommand()); - - String config = qtConfig.getQmakeConfig(); - if (config != null) { - command.add(config); - } + Path makeCommand = getMakeCommand(getBuildConfig()); + if (makeCommand == null) { + errStream.write("'make' not found.\n"); + return null; + } - IFile projectFile = qtConfig.getProject().getFile(project.getName() + ".pro"); //$NON-NLS-1$ - command.add(projectFile.getLocation().toOSString()); + try (ErrorParserManager epm = new ErrorParserManager(project, qtConfig.getBuildDirectory().toUri(), this, + qtConfig.getToolChain().getErrorParserIds())) { + BuildCommandRunner runner = new BuildCommandRunner(project, console, epm); - ProcessBuilder processBuilder = new ProcessBuilder(command).directory(buildDir.toFile()); - toolChain.setEnvironment(processBuilder.environment()); - Process process = processBuilder.start(); - StringBuffer msg = new StringBuffer(); - for (String arg : command) { - msg.append(arg).append(' '); + Path buildDir = qtConfig.getBuildDirectory(); + if (!buildDir.resolve("Makefile").toFile().exists()) { //$NON-NLS-1$ + // Need to run qmake + List<String> command = new ArrayList<>(); + command.add(qtConfig.getQmakeCommand().toString()); + + String config = qtConfig.getQmakeConfig(); + if (config != null) { + command.add(config); + } + + IFile projectFile = qtConfig.getBuildConfiguration().getProject() + .getFile(project.getName() + ".pro"); //$NON-NLS-1$ + command.add(projectFile.getLocation().toOSString()); + + ProcessBuilder processBuilder = new ProcessBuilder(command) + .directory(qtConfig.getBuildDirectory().toFile()); + CCorePlugin.getDefault().getBuildEnvironmentManager().setEnvironment(processBuilder.environment(), + getBuildConfig(), true); + Process process = processBuilder.start(); + + StringBuffer msg = new StringBuffer(); + for (String arg : command) { + msg.append(arg).append(' '); + } + msg.append('\n'); + outStream.write(msg.toString()); + + runner.monitor(process); } - msg.append('\n'); - console.writeOutput(msg.toString()); - console.monitor(process, null, buildDir); - } - // run make - // TODO obviously hardcoding here - boolean isWin = Platform.getOS().equals(Platform.OS_WIN32); - String make = isWin ? "C:/Qt/Tools/mingw492_32/bin/mingw32-make" : "make"; //$NON-NLS-1$ //$NON-NLS-2$ - ProcessBuilder procBuilder = new ProcessBuilder(make).directory(buildDir.toFile()); - if (isWin) { - // Need to put the toolchain into env - Map<String, String> env = procBuilder.environment(); - String path = env.get("PATH"); //$NON-NLS-1$ - path = "C:/Qt/Tools/mingw492_32/bin;" + path; //$NON-NLS-1$ - env.put("PATH", path); //$NON-NLS-1$ + // run make + ProcessBuilder procBuilder = new ProcessBuilder(makeCommand.toString()).directory(buildDir.toFile()); + CCorePlugin.getDefault().getBuildEnvironmentManager().setEnvironment(procBuilder.environment(), + getBuildConfig(), true); + Process process = procBuilder.start(); + outStream.write(makeCommand.toString() + '\n'); + runner.monitor(process); } - toolChain.setEnvironment(procBuilder.environment()); - Process process = procBuilder.start(); - console.writeOutput("make\n"); //$NON-NLS-1$ - console.monitor(process, null, buildDir); project.refreshLocal(IResource.DEPTH_INFINITE, monitor); // clear the scanner info cache // TODO be more surgical about what to clear based on what was // built. - qtConfig.clearScannerInfoCache(); + // qtConfig.clearScannerInfoCache(); - console.writeOutput("Complete.\n"); + outStream.write("Complete.\n"); return new IProject[] { project }; } catch (IOException e) { throw new CoreException(new Status(IStatus.ERROR, Activator.ID, "Building " + project.getName(), e)); //$NON-NLS-1$ } } + @Override + protected void clean(IProgressMonitor monitor) throws CoreException { + IProject project = getProject(); + try { + project.deleteMarkers(ICModelMarker.C_MODEL_PROBLEM_MARKER, false, IResource.DEPTH_INFINITE); + + IConsole console = CCorePlugin.getDefault().getConsole(); + console.start(getProject()); + ConsoleOutputStream errStream = console.getErrorStream(); + ConsoleOutputStream outStream = console.getOutputStream(); + + ICBuildConfiguration cconfig = getBuildConfig().getAdapter(ICBuildConfiguration.class); + IQtBuildConfiguration qtConfig = cconfig.getAdapter(QtBuildConfiguration.class); + if (qtConfig == null) { + // Qt hasn't been configured yet print a message and bale + errStream.write(Messages.QtBuilder_0); + return; + } + + Path makeCommand = getMakeCommand(getBuildConfig()); + if (makeCommand == null) { + errStream.write("'make' not found.\n"); + return; + } + + Path buildDir = qtConfig.getBuildDirectory(); + + try (ErrorParserManager epm = new ErrorParserManager(project, qtConfig.getBuildDirectory().toUri(), this, + qtConfig.getToolChain().getErrorParserIds())) { + BuildCommandRunner runner = new BuildCommandRunner(project, console, epm); + // run make + ProcessBuilder procBuilder = new ProcessBuilder(makeCommand.toString(), "clean") //$NON-NLS-1$ + .directory(buildDir.toFile()); + CCorePlugin.getDefault().getBuildEnvironmentManager().setEnvironment(procBuilder.environment(), + getBuildConfig(), true); + Process process = procBuilder.start(); + outStream.write(makeCommand.toString() + "clean\n"); //$NON-NLS-1$ + runner.monitor(process); + } + + project.refreshLocal(IResource.DEPTH_INFINITE, monitor); + + // clear the scanner info cache + // TODO be more surgical about what to clear based on what was + // built. + // qtConfig.clearScannerInfoCache(); + + outStream.write("Complete.\n"); + // TODO Auto-generated method stub + super.clean(monitor); + } catch (IOException e) { + throw new CoreException(new Status(IStatus.ERROR, Activator.ID, "Cleaning " + project.getName(), e)); //$NON-NLS-1$ + } + } + + public Path getMakeCommand(IBuildConfiguration config) { + Path makeCommand = findCommand(getBuildConfig(), "make"); //$NON-NLS-1$ + if (makeCommand == null) { + makeCommand = findCommand(getBuildConfig(), "mingw32-make"); //$NON-NLS-1$ + } + return makeCommand; + } + + public Path findCommand(IBuildConfiguration config, String command) { + if (Platform.getOS().equals(Platform.OS_WIN32)) { + command += ".exe"; //$NON-NLS-1$ + } + Map<String, String> env = new HashMap<>(System.getenv()); + CCorePlugin.getDefault().getBuildEnvironmentManager().setEnvironment(env, config, true); + String[] path = env.get("PATH").split(File.pathSeparator); //$NON-NLS-1$ + for (String dir : path) { + Path commandPath = Paths.get(dir, command); + if (Files.exists(commandPath)) { + return commandPath; + } + } + return null; + } + } diff --git a/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/internal/qt/core/build/QtScannerInfoProvider.java b/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/internal/qt/core/build/QtScannerInfoProvider.java deleted file mode 100644 index b2b8eacfe27..00000000000 --- a/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/internal/qt/core/build/QtScannerInfoProvider.java +++ /dev/null @@ -1,47 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2015 QNX Software Systems and others. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - *******************************************************************************/ -package org.eclipse.cdt.internal.qt.core.build; - -import java.io.IOException; - -import org.eclipse.cdt.core.parser.IScannerInfo; -import org.eclipse.cdt.core.parser.IScannerInfoChangeListener; -import org.eclipse.cdt.core.parser.IScannerInfoProvider; -import org.eclipse.cdt.internal.qt.core.Activator; -import org.eclipse.cdt.qt.core.QtBuildConfiguration; -import org.eclipse.core.resources.IBuildConfiguration; -import org.eclipse.core.resources.IProject; -import org.eclipse.core.resources.IResource; -import org.eclipse.core.runtime.CoreException; - -public class QtScannerInfoProvider implements IScannerInfoProvider { - - @Override - public IScannerInfo getScannerInformation(IResource resource) { - try { - IProject project = resource.getProject(); - IBuildConfiguration config = project.getActiveBuildConfig(); - QtBuildConfiguration qtConfig = config.getAdapter(QtBuildConfiguration.class); - if (qtConfig != null) { - return qtConfig.getScannerInfo(resource); - } - } catch (CoreException | IOException e) { - Activator.log(e); - } - return null; - } - - @Override - public void subscribe(IResource resource, IScannerInfoChangeListener listener) { - } - - @Override - public void unsubscribe(IResource resource, IScannerInfoChangeListener listener) { - } - -} diff --git a/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/internal/qt/core/launch/QtLocalDebugLaunchConfigDelegate.java b/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/internal/qt/core/launch/QtLocalDebugLaunchConfigDelegate.java index 2bf05390d69..9f02551480d 100644 --- a/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/internal/qt/core/launch/QtLocalDebugLaunchConfigDelegate.java +++ b/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/internal/qt/core/launch/QtLocalDebugLaunchConfigDelegate.java @@ -10,6 +10,7 @@ package org.eclipse.cdt.internal.qt.core.launch; import java.nio.file.Path; import java.util.concurrent.ExecutionException; +import org.eclipse.cdt.core.build.IToolChain; import org.eclipse.cdt.dsf.concurrent.DataRequestMonitor; import org.eclipse.cdt.dsf.concurrent.ImmediateExecutor; import org.eclipse.cdt.dsf.concurrent.Query; @@ -22,7 +23,7 @@ import org.eclipse.cdt.dsf.gdb.service.GdbDebugServicesFactory; import org.eclipse.cdt.dsf.gdb.service.command.IGDBControl; import org.eclipse.cdt.dsf.service.DsfServicesTracker; import org.eclipse.cdt.internal.qt.core.Activator; -import org.eclipse.cdt.qt.core.QtBuildConfiguration; +import org.eclipse.cdt.qt.core.IQtBuildConfiguration; import org.eclipse.cdt.qt.core.QtLaunchConfigurationDelegate; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IProgressMonitor; @@ -60,10 +61,10 @@ public class QtLocalDebugLaunchConfigDelegate extends QtLaunchConfigurationDeleg throws CoreException { GdbLaunch gdbLaunch = (GdbLaunch) launch; ILaunchTarget target = ((ITargetedLaunch) launch).getLaunchTarget(); - QtBuildConfiguration qtBuildConfig = getQtBuildConfiguration(configuration, mode, target, monitor); + IQtBuildConfiguration qtBuildConfig = getQtBuildConfiguration(configuration, mode, target, monitor); - // TODO get it from the toolchain - gdbLaunch.setGDBPath("/usr/local/bin/gdb"); + IToolChain toolChain = qtBuildConfig.getToolChain(); + gdbLaunch.setGDBPath(toolChain.getCommandPath("gdb").toString()); //$NON-NLS-1$ String gdbVersion = gdbLaunch.getGDBVersion(); Path exeFile = qtBuildConfig.getProgramPath(); diff --git a/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/internal/qt/core/launch/QtLocalRunLaunchConfigDelegate.java b/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/internal/qt/core/launch/QtLocalRunLaunchConfigDelegate.java index e0c5e0fdb36..c300c209f8d 100644 --- a/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/internal/qt/core/launch/QtLocalRunLaunchConfigDelegate.java +++ b/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/internal/qt/core/launch/QtLocalRunLaunchConfigDelegate.java @@ -8,12 +8,14 @@ package org.eclipse.cdt.internal.qt.core.launch; import java.io.IOException; -import java.nio.file.Path; import java.util.Map; +import org.eclipse.cdt.core.CCorePlugin; +import org.eclipse.cdt.core.envvar.IEnvironmentVariable; import org.eclipse.cdt.internal.qt.core.Activator; -import org.eclipse.cdt.qt.core.QtBuildConfiguration; +import org.eclipse.cdt.qt.core.IQtBuildConfiguration; import org.eclipse.cdt.qt.core.QtLaunchConfigurationDelegate; +import org.eclipse.core.resources.IBuildConfiguration; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IStatus; @@ -33,17 +35,17 @@ public class QtLocalRunLaunchConfigDelegate extends QtLaunchConfigurationDelegat public void launch(ILaunchConfiguration configuration, String mode, ILaunch launch, IProgressMonitor monitor) throws CoreException { ILaunchTarget target = ((ITargetedLaunch) launch).getLaunchTarget(); - QtBuildConfiguration qtBuildConfig = getQtBuildConfiguration(configuration, mode, target, monitor); + IQtBuildConfiguration qtBuildConfig = getQtBuildConfiguration(configuration, mode, target, monitor); - // get the executable - Path exeFile = qtBuildConfig.getProgramPath(); - - ProcessBuilder builder = new ProcessBuilder(exeFile.toString()) - .directory(qtBuildConfig.getProject().getLocation().toFile()); - - // set up the environment - Map<String, String> env = builder.environment(); - qtBuildConfig.setProgramEnvironment(env); + IBuildConfiguration buildConfig = qtBuildConfig.getBuildConfiguration(); + ProcessBuilder processBuilder = new ProcessBuilder(qtBuildConfig.getProgramPath().toString()) + .directory(buildConfig.getProject().getLocation().toFile()); + + Map<String, String> env = processBuilder.environment(); + for (IEnvironmentVariable var : CCorePlugin.getDefault().getBuildEnvironmentManager() + .getVariables(qtBuildConfig.getBuildConfiguration(), true)) { + env.put(var.getName(), var.getValue()); + } Map<String, String> configEnv = configuration.getAttribute(ILaunchManager.ATTR_ENVIRONMENT_VARIABLES, (Map<String, String>) null); @@ -54,10 +56,10 @@ public class QtLocalRunLaunchConfigDelegate extends QtLaunchConfigurationDelegat } try { - Process process = builder.start(); - DebugPlugin.newProcess(launch, process, "main"); + Process process = processBuilder.start(); + DebugPlugin.newProcess(launch, process, qtBuildConfig.getProgramPath().toString()); } catch (IOException e) { - throw new CoreException(new Status(IStatus.ERROR, Activator.ID, "Failed to start", e)); + throw new CoreException(new Status(IStatus.ERROR, Activator.ID, "Launching", e)); } } diff --git a/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/internal/qt/core/provider/HomebrewQtInstallProvider.java b/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/internal/qt/core/provider/HomebrewQtInstallProvider.java new file mode 100644 index 00000000000..d9614222cd8 --- /dev/null +++ b/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/internal/qt/core/provider/HomebrewQtInstallProvider.java @@ -0,0 +1,39 @@ +/******************************************************************************* + * 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.internal.qt.core.QtInstall; +import org.eclipse.cdt.qt.core.IQtInstall; +import org.eclipse.cdt.qt.core.IQtInstallProvider; +import org.eclipse.core.runtime.Platform; + +/** + * QtInstall provider for qt out of Homebrew. Unfortunately they don't put it on the path so we have + * to look where they put it. + */ +public class HomebrewQtInstallProvider implements IQtInstallProvider { + + @Override + public Collection<IQtInstall> getInstalls() { + if (Platform.getOS().equals(Platform.OS_MACOSX)) { + Path qmakePath = Paths.get("/usr/local/opt/qt5/bin/qmake"); //$NON-NLS-1$ + if (Files.exists(qmakePath)) { + return Arrays.asList(new QtInstall(qmakePath)); + } + } + 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 new file mode 100644 index 00000000000..7f0b1a5b037 --- /dev/null +++ b/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/internal/qt/core/provider/Msys2QtInstallProvider.java @@ -0,0 +1,52 @@ +/******************************************************************************* + * 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.Path; +import java.nio.file.Paths; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.List; + +import org.eclipse.cdt.internal.qt.core.QtInstall; +import org.eclipse.cdt.qt.core.IQtInstall; +import org.eclipse.cdt.qt.core.IQtInstallProvider; +import org.eclipse.cdt.utils.WindowsRegistry; +import org.eclipse.core.runtime.Platform; + +/** + * QtInstall provider for Qt in MSYS2. Use the registry to find out where MSYS2 is installed. + */ +public class Msys2QtInstallProvider implements IQtInstallProvider { + + @Override + public Collection<IQtInstall> getInstalls() { + if (Platform.getOS().equals(Platform.OS_WIN32)) { + List<IQtInstall> installs = new ArrayList<>(); + // Look in the current user Uninstall key to look for the uninstaller + 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 ("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)); + } + } + return installs; + } else { + return Collections.emptyList(); + } + } + +} 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 new file mode 100644 index 00000000000..1ebfe465d0e --- /dev/null +++ b/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/internal/qt/core/provider/QtInstallProvider.java @@ -0,0 +1,69 @@ +/******************************************************************************* + * 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.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.Collection; +import java.util.Collections; +import java.util.stream.Collectors; + +import org.eclipse.cdt.codan.core.cxx.Activator; +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.cdt.utils.WindowsRegistry; +import org.eclipse.core.runtime.Platform; + +/** + * Qt Install provider that attempts to find the Qt package as installed using Qt's own installer. + */ +public class QtInstallProvider implements IQtInstallProvider { + + @Override + public Collection<IQtInstall> 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) { + try { + return Files.walk(root, 2).filter((path) -> Files.exists(path.resolve(qmake))) + .map((path) -> new QtInstall(path.resolve(qmake))).collect(Collectors.toList()); + } catch (IOException e) { + Activator.log(e); + } + } + return Collections.emptyList(); + } + + private Path getQtRoot() { + if (Platform.getOS().equals(Platform.OS_WIN32)) { + 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); + } + } + } else { + Path qtDir = Paths.get(System.getProperty("user.home"), "Qt"); //$NON-NLS-1$ //$NON-NLS-2$ + if (Files.exists(qtDir)) { + return qtDir; + } + } + return null; + } + + // gcc is in C:\Qt\Tools\mingw492_32\bin +} 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 new file mode 100644 index 00000000000..08abf17b83f --- /dev/null +++ b/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/qt/core/IQtBuildConfiguration.java @@ -0,0 +1,26 @@ +/*******************************************************************************
+ * 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.qt.core;
+
+import java.nio.file.Path;
+
+import org.eclipse.cdt.core.build.ICBuildConfiguration;
+
+public interface IQtBuildConfiguration extends ICBuildConfiguration {
+
+ Path getBuildDirectory();
+
+ Path getQmakeCommand();
+
+ String getQmakeConfig();
+
+ Path getProgramPath();
+
+ String getLaunchMode();
+
+}
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 b3014cbc51b..c55fd1a5f02 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 @@ -17,8 +17,6 @@ import java.nio.file.Path; */ public interface IQtInstall { - String getName(); - Path getQmakePath(); String getSpec(); diff --git a/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/qt/core/IQtInstallManager.java b/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/qt/core/IQtInstallManager.java index 424c5cfd475..ee65f0dc517 100644 --- a/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/qt/core/IQtInstallManager.java +++ b/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/qt/core/IQtInstallManager.java @@ -7,10 +7,10 @@ *******************************************************************************/ package org.eclipse.cdt.qt.core; +import java.nio.file.Path; import java.util.Collection; -import org.eclipse.cdt.build.core.IToolChain; -import org.eclipse.launchbar.core.target.ILaunchTarget; +import org.eclipse.cdt.core.build.IToolChain; /** * The manager for Qt installs. @@ -23,12 +23,10 @@ public interface IQtInstallManager { public void addInstall(IQtInstall install); - public IQtInstall getInstall(String name); + public IQtInstall getInstall(Path qmakePath); public void removeInstall(IQtInstall install); - public boolean supports(IQtInstall install, ILaunchTarget target); - public boolean supports(IQtInstall install, IToolChain toolChain); } diff --git a/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/qt/core/IQtInstallProvider.java b/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/qt/core/IQtInstallProvider.java new file mode 100644 index 00000000000..174a8db53c1 --- /dev/null +++ b/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/qt/core/IQtInstallProvider.java @@ -0,0 +1,16 @@ +/******************************************************************************* + * 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.qt.core; + +import java.util.Collection; + +public interface IQtInstallProvider { + + Collection<IQtInstall> getInstalls(); + +} diff --git a/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/qt/core/IQtInstallTargetMapper.java b/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/qt/core/IQtInstallTargetMapper.java deleted file mode 100644 index 9e61e12b255..00000000000 --- a/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/qt/core/IQtInstallTargetMapper.java +++ /dev/null @@ -1,37 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2015 QNX Software Systems and others. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - *******************************************************************************/ -package org.eclipse.cdt.qt.core; - -import org.eclipse.cdt.build.core.IToolChain; -import org.eclipse.launchbar.core.target.ILaunchTarget; - -public interface IQtInstallTargetMapper { - - /** - * Does the Qt install support the given target. - * - * @param qtInstall - * Qt install - * @param launchTarget - * launch target - * @return does the Qt install support the target - */ - public boolean supported(IQtInstall qtInstall, ILaunchTarget launchTarget); - - /** - * Does the Qt install build using the given toolchain? - * - * @param qtInstall - * Qt install - * @param toolChain - * ToolChain - * @return does the Qt install build with the toolchain - */ - public boolean supported(IQtInstall qtInstall, IToolChain toolChain); - -} 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 0001dd62c27..dc3862bccca 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 @@ -7,7 +7,14 @@ *******************************************************************************/ package org.eclipse.cdt.qt.core; -import org.eclipse.cdt.internal.qt.core.build.QtBuildConfigurationFactory; +import java.util.HashMap; +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; import org.eclipse.core.resources.IProjectDescription; import org.eclipse.core.runtime.CoreException; @@ -21,11 +28,11 @@ public abstract class QtLaunchConfigurationDelegate extends LaunchConfigurationT @Override public boolean buildForLaunch(ILaunchConfiguration configuration, String mode, ILaunchTarget target, IProgressMonitor monitor) throws CoreException { - QtBuildConfiguration qtBuildConfig = getQtBuildConfiguration(configuration, mode, target, monitor); + IQtBuildConfiguration qtBuildConfig = getQtBuildConfiguration(configuration, mode, target, monitor); // Set it as active if (qtBuildConfig != null) { - IProject project = qtBuildConfig.getProject(); + IProject project = qtBuildConfig.getBuildConfiguration().getProject(); IProjectDescription desc = project.getDescription(); desc.setActiveBuildConfig(qtBuildConfig.getBuildConfiguration().getName()); project.setDescription(desc, monitor); @@ -43,11 +50,39 @@ public abstract class QtLaunchConfigurationDelegate extends LaunchConfigurationT return new IProject[] { project }; } - protected QtBuildConfiguration getQtBuildConfiguration(ILaunchConfiguration configuration, String mode, + protected void populateToolChainProperties(ILaunchTarget target, Map<String, String> properties) { + String os = target.getAttribute(ILaunchTarget.ATTR_OS, null); + if (os != null) { + properties.put(IToolChain.ATTR_OS, os); + } + String arch = target.getAttribute(ILaunchTarget.ATTR_ARCH, null); + if (arch != null) { + properties.put(IToolChain.ATTR_ARCH, arch); + } + } + + protected IQtBuildConfiguration getQtBuildConfiguration(ILaunchConfiguration configuration, String mode, ILaunchTarget target, IProgressMonitor monitor) throws CoreException { // Find the Qt build config + ICBuildConfigurationManager configManager = Activator.getService(ICBuildConfigurationManager.class); + QtBuildConfigurationProvider provider = (QtBuildConfigurationProvider) configManager + .getProvider(QtBuildConfigurationProvider.ID); IProject project = configuration.getMappedResources()[0].getProject(); - return QtBuildConfigurationFactory.getConfig(project, mode, target, monitor); + + // Find the toolchains that support this target + Map<String, String> properties = new HashMap<>(); + populateToolChainProperties(target, properties); + + IToolChainManager toolChainManager = Activator.getService(IToolChainManager.class); + for (IToolChain toolChain : toolChainManager.getToolChainsMatching(properties)) { + IQtBuildConfiguration qtConfig = provider.createConfiguration(project, toolChain, mode, monitor); + if (qtConfig != null) { + return qtConfig; + } + } + + // Couldn't find any + return null; } } diff --git a/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/qt/core/QtLaunchConfigurationProvider.java b/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/qt/core/QtLaunchConfigurationProvider.java index b325ccf6b90..0ef7ef98c1a 100644 --- a/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/qt/core/QtLaunchConfigurationProvider.java +++ b/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/qt/core/QtLaunchConfigurationProvider.java @@ -11,6 +11,7 @@ import java.util.HashMap; import java.util.Map; import java.util.Map.Entry; +import org.eclipse.cdt.debug.core.ICDTLaunchConfigurationConstants; import org.eclipse.cdt.internal.qt.core.launch.QtLaunchDescriptor; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IResource; @@ -45,6 +46,9 @@ public abstract class QtLaunchConfigurationProvider extends AbstractLaunchConfig protected void populateLaunchConfiguration(ILaunchDescriptor descriptor, ILaunchTarget target, ILaunchConfigurationWorkingCopy workingCopy) throws CoreException { super.populateLaunchConfiguration(descriptor, target, workingCopy); + + // Main is actually in the library. Don't stop there + workingCopy.setAttribute(ICDTLaunchConfigurationConstants.ATTR_DEBUGGER_STOP_AT_MAIN, false); // Set the project and the connection QtLaunchDescriptor qtDesc = (QtLaunchDescriptor) descriptor; 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 new file mode 100644 index 00000000000..a484f8dedb5 --- /dev/null +++ b/qt/org.eclipse.cdt.qt.core/src/org/eclipse/cdt/qt/core/QtMinGWToolChainProvider.java @@ -0,0 +1,58 @@ +/******************************************************************************* + * 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.qt.core; + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.Collection; +import java.util.Collections; +import java.util.stream.Collectors; + +import org.eclipse.cdt.build.gcc.core.GCCToolChain; +import org.eclipse.cdt.build.gcc.core.GCCToolChainType; +import org.eclipse.cdt.core.build.IToolChain; +import org.eclipse.cdt.core.build.IToolChainManager; +import org.eclipse.cdt.core.build.IToolChainProvider; +import org.eclipse.cdt.core.build.IToolChainType; +import org.eclipse.cdt.internal.qt.core.Activator; +import org.eclipse.cdt.utils.WindowsRegistry; +import org.eclipse.core.runtime.Platform; + +public class QtMinGWToolChainProvider implements IToolChainProvider { + + @Override + public Collection<IToolChain> getToolChains() { + if (Platform.getOS().equals(Platform.OS_WIN32)) { + WindowsRegistry registry = WindowsRegistry.getRegistry(); + String uninstallKey = "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall"; //$NON-NLS-1$ + String subkey; + IToolChainType type = Activator.getService(IToolChainManager.class).getToolChainType(GCCToolChainType.ID); + for (int i = 0; (subkey = registry.getCurrentUserKeyName(uninstallKey, i)) != null; i++) { + String compKey = uninstallKey + '\\' + subkey; + String displayName = registry.getCurrentUserValue(compKey, "DisplayName"); //$NON-NLS-1$ + 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 { + return Files.walk(Paths.get(installLocation).resolve("Tools"), 1) //$NON-NLS-1$ + .filter((path) -> Files.exists(path.resolve(gcc))) + .map((path) -> new GCCToolChain(type, path.resolve("bin"), "gcc.exe")) //$NON-NLS-1$ //$NON-NLS-2$ + .collect(Collectors.toList()); + } catch (IOException e) { + Activator.log(e); + } + } + } + } + // default + return Collections.emptyList(); + } + +} diff --git a/qt/org.eclipse.cdt.qt.ui/src/org/eclipse/cdt/internal/qt/ui/preferences/NewQtInstallWizard.java b/qt/org.eclipse.cdt.qt.ui/src/org/eclipse/cdt/internal/qt/ui/preferences/NewQtInstallWizard.java index 98345cab2b4..9d736437c03 100644 --- a/qt/org.eclipse.cdt.qt.ui/src/org/eclipse/cdt/internal/qt/ui/preferences/NewQtInstallWizard.java +++ b/qt/org.eclipse.cdt.qt.ui/src/org/eclipse/cdt/internal/qt/ui/preferences/NewQtInstallWizard.java @@ -7,6 +7,7 @@ *******************************************************************************/ package org.eclipse.cdt.internal.qt.ui.preferences; +import java.nio.file.Path; import java.util.Map; import org.eclipse.cdt.qt.core.IQtInstall; @@ -17,7 +18,7 @@ public class NewQtInstallWizard extends Wizard { private final NewQtInstallWizardPage page; private IQtInstall install; - public NewQtInstallWizard(Map<String, IQtInstall> existing) { + public NewQtInstallWizard(Map<Path, IQtInstall> existing) { page = new NewQtInstallWizardPage(existing); } 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 c1b870d97d7..a870cafddeb 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 @@ -8,6 +8,7 @@ package org.eclipse.cdt.internal.qt.ui.preferences; import java.io.IOException; +import java.nio.file.Path; import java.nio.file.Paths; import java.util.Map; @@ -31,13 +32,12 @@ import org.eclipse.swt.widgets.Text; public class NewQtInstallWizardPage extends WizardPage { - private Text nameText; private Text locationText; private Text specText; - private final Map<String, IQtInstall> existing; + private final Map<Path, IQtInstall> existing; - public NewQtInstallWizardPage(Map<String, IQtInstall> existing) { + public NewQtInstallWizardPage(Map<Path, IQtInstall> existing) { super(Messages.NewQtInstallWizardPage_0, Messages.NewQtInstallWizardPage_1, null); this.existing = existing; } @@ -52,10 +52,6 @@ public class NewQtInstallWizardPage extends WizardPage { nameLabel.setLayoutData(new GridData(SWT.BEGINNING, SWT.CENTER, false, false)); nameLabel.setText(Messages.NewQtInstallWizardPage_2); - nameText = new Text(comp, SWT.BORDER); - nameText.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false)); - nameText.addModifyListener(e -> validate()); - Label locationLabel = new Label(comp, SWT.NONE); locationLabel.setLayoutData(new GridData(SWT.BEGINNING, SWT.CENTER, false, false)); locationLabel.setText(Messages.NewQtInstallWizardPage_3); @@ -88,9 +84,6 @@ public class NewQtInstallWizardPage extends WizardPage { String spec = QtInstall.getSpec(selected); getControl().getDisplay().asyncExec(() -> { specText.setText(spec); - if (nameText.getText().isEmpty() && !existing.containsKey(spec)) { - nameText.setText(spec); - } }); return Status.OK_STATUS; } catch (IOException e) { @@ -114,13 +107,7 @@ public class NewQtInstallWizardPage extends WizardPage { private void validate() { setPageComplete(false); - String name = nameText.getText().trim(); - if (name.isEmpty()) { - setErrorMessage(Messages.NewQtInstallWizardPage_10); - return; - } - - if (existing.containsKey(name)) { + if (existing.containsKey(Paths.get(locationText.getText()))) { setErrorMessage(Messages.NewQtInstallWizardPage_11); return; } @@ -130,7 +117,7 @@ public class NewQtInstallWizardPage extends WizardPage { } IQtInstall getInstall() { - return new QtInstall(nameText.getText(), Paths.get(locationText.getText())); + return new QtInstall(Paths.get(locationText.getText())); } } diff --git a/qt/org.eclipse.cdt.qt.ui/src/org/eclipse/cdt/internal/qt/ui/preferences/QtPreferencePage.java b/qt/org.eclipse.cdt.qt.ui/src/org/eclipse/cdt/internal/qt/ui/preferences/QtPreferencePage.java index 2dc37db00f9..d0260e57cea 100644 --- a/qt/org.eclipse.cdt.qt.ui/src/org/eclipse/cdt/internal/qt/ui/preferences/QtPreferencePage.java +++ b/qt/org.eclipse.cdt.qt.ui/src/org/eclipse/cdt/internal/qt/ui/preferences/QtPreferencePage.java @@ -10,14 +10,15 @@ *******************************************************************************/ package org.eclipse.cdt.internal.qt.ui.preferences; +import java.nio.file.Path; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; -import org.eclipse.cdt.internal.qt.ui.Messages; import org.eclipse.cdt.internal.qt.ui.Activator; +import org.eclipse.cdt.internal.qt.ui.Messages; import org.eclipse.cdt.qt.core.IQtInstall; import org.eclipse.cdt.qt.core.IQtInstallManager; import org.eclipse.jface.dialogs.MessageDialog; @@ -47,8 +48,8 @@ public class QtPreferencePage extends PreferencePage implements IWorkbenchPrefer private Table installTable; private Button removeButton; - private Map<String, IQtInstall> installsToAdd = new HashMap<>(); - private Map<String, IQtInstall> installsToRemove = new HashMap<>(); + private Map<Path, IQtInstall> installsToAdd = new HashMap<>(); + private Map<Path, IQtInstall> installsToRemove = new HashMap<>(); @Override public void init(IWorkbench workbench) { @@ -102,7 +103,7 @@ public class QtPreferencePage extends PreferencePage implements IWorkbenchPrefer WizardDialog dialog = new WizardDialog(getShell(), wizard); if (dialog.open() == Window.OK) { IQtInstall install = wizard.getInstall(); - installsToAdd.put(install.getName(), install); + installsToAdd.put(install.getQmakePath(), install); updateTable(); } } @@ -116,7 +117,7 @@ public class QtPreferencePage extends PreferencePage implements IWorkbenchPrefer if (MessageDialog.openConfirm(getShell(), Messages.QtPreferencePage_5, Messages.QtPreferencePage_6)) { for (TableItem item : installTable.getSelection()) { IQtInstall install = (IQtInstall) item.getData(); - installsToRemove.put(install.getName(), install); + installsToRemove.put(install.getQmakePath(), install); updateTable(); } } @@ -127,18 +128,18 @@ public class QtPreferencePage extends PreferencePage implements IWorkbenchPrefer return control; } - private Map<String, IQtInstall> getInstalls() { - Map<String, IQtInstall> installs = new HashMap<>(); + private Map<Path, IQtInstall> getInstalls() { + Map<Path, IQtInstall> installs = new HashMap<>(); for (IQtInstall install : manager.getInstalls()) { - installs.put(install.getName(), install); + installs.put(install.getQmakePath(), install); } for (IQtInstall install : installsToAdd.values()) { - installs.put(install.getName(), install); + installs.put(install.getQmakePath(), install); } for (IQtInstall install : installsToRemove.values()) { - installs.remove(install.getName()); + installs.remove(install.getQmakePath()); } return installs; @@ -146,13 +147,13 @@ public class QtPreferencePage extends PreferencePage implements IWorkbenchPrefer private void updateTable() { List<IQtInstall> sorted = new ArrayList<>(getInstalls().values()); - Collections.sort(sorted, (o1, o2) -> o1.getName().compareToIgnoreCase(o2.getName())); + Collections.sort(sorted, (o1, o2) -> o1.getQmakePath().toString().compareToIgnoreCase(o2.getQmakePath().toString())); installTable.removeAll(); for (IQtInstall install : sorted) { TableItem item = new TableItem(installTable, SWT.NONE); - item.setText(0, install.getName()); - item.setText(1, install.getQmakePath().toString()); + item.setText(0, install.getQmakePath().toString()); + item.setText(1, install.getSpec()); item.setData(install); } } |