Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndrew Gvozdev2012-07-11 21:56:33 +0000
committerAndrew Gvozdev2013-02-01 15:32:41 +0000
commit4b5b30fe150c8ba54ebf4a6c156fd8aae007f6d8 (patch)
tree8f30e1ce55ad0b479e4e55b74c87bedc3563d91d
parenta3783e3f840a9bc2fa8d13fe05585d85ffa2d388 (diff)
downloadorg.eclipse.cdt-4b5b30fe150c8ba54ebf4a6c156fd8aae007f6d8.tar.gz
org.eclipse.cdt-4b5b30fe150c8ba54ebf4a6c156fd8aae007f6d8.tar.xz
org.eclipse.cdt-4b5b30fe150c8ba54ebf4a6c156fd8aae007f6d8.zip
bug 357442: Added $CYGWIN_HOME to cygwin toolchain detection algorithm
-rw-r--r--build/org.eclipse.cdt.make.core/src/org/eclipse/cdt/make/internal/core/scannerconfig/util/CygpathTranslator.java238
-rw-r--r--build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/envvar/EnvironmentVariableManagerToolChain.java220
-rw-r--r--build/org.eclipse.cdt.managedbuilder.gnu.ui/src/org/eclipse/cdt/managedbuilder/gnu/cygwin/CygwinPathResolver.java270
-rw-r--r--build/org.eclipse.cdt.managedbuilder.gnu.ui/src/org/eclipse/cdt/managedbuilder/gnu/cygwin/GnuCygwinConfigurationEnvironmentSupplier.java67
-rw-r--r--build/org.eclipse.cdt.managedbuilder.gnu.ui/src/org/eclipse/cdt/managedbuilder/gnu/cygwin/IsGnuCygwinToolChainSupported.java71
-rw-r--r--core/org.eclipse.cdt.core/utils/org/eclipse/cdt/internal/core/Cygwin.java252
-rw-r--r--core/org.eclipse.cdt.core/utils/org/eclipse/cdt/internal/core/LRUCache.java50
-rw-r--r--core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/newui/AbstractPage.java5
8 files changed, 790 insertions, 383 deletions
diff --git a/build/org.eclipse.cdt.make.core/src/org/eclipse/cdt/make/internal/core/scannerconfig/util/CygpathTranslator.java b/build/org.eclipse.cdt.make.core/src/org/eclipse/cdt/make/internal/core/scannerconfig/util/CygpathTranslator.java
index 820df07aac7..3dca63cf0c0 100644
--- a/build/org.eclipse.cdt.make.core/src/org/eclipse/cdt/make/internal/core/scannerconfig/util/CygpathTranslator.java
+++ b/build/org.eclipse.cdt.make.core/src/org/eclipse/cdt/make/internal/core/scannerconfig/util/CygpathTranslator.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2004, 2011 IBM Corporation and others.
+ * Copyright (c) 2004, 2013 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -20,8 +20,14 @@ import java.util.List;
import org.eclipse.cdt.core.CCorePlugin;
import org.eclipse.cdt.core.IBinaryParser;
+import org.eclipse.cdt.core.envvar.IEnvironmentVariable;
+import org.eclipse.cdt.core.envvar.IEnvironmentVariableManager;
import org.eclipse.cdt.core.model.CoreModelUtil;
import org.eclipse.cdt.core.settings.model.ICConfigExtensionReference;
+import org.eclipse.cdt.core.settings.model.ICConfigurationDescription;
+import org.eclipse.cdt.core.settings.model.ICProjectDescription;
+import org.eclipse.cdt.internal.core.Cygwin;
+import org.eclipse.cdt.make.core.MakeCorePlugin;
import org.eclipse.cdt.utils.CygPath;
import org.eclipse.cdt.utils.ICygwinToolsFactroy;
import org.eclipse.core.resources.IProject;
@@ -32,125 +38,135 @@ import org.eclipse.core.runtime.Platform;
/**
* Use binary parser's 'cygpath' command to translate cygpaths to absolute paths.
+ * Note that this class does not support build configurations.
*
* @author vhirsl
*/
public class CygpathTranslator {
- /** Default Cygwin root dir */
- private static final String DEFAULT_CYGWIN_ROOT= "C:\\cygwin"; //$NON-NLS-1$
- // private static final String CYGPATH_ERROR_MESSAGE = "CygpathTranslator.NotAvailableErrorMessage"; //$NON-NLS-1$
- private CygPath cygPath = null;
- private boolean isAvailable = false;
-
- public CygpathTranslator(IProject project) {
- try {
- ICConfigExtensionReference[] parserRef = CCorePlugin.getDefault().getDefaultBinaryParserExtensions(project);
- for (int i = 0; i < parserRef.length; i++) {
- try {
- IBinaryParser parser = CoreModelUtil.getBinaryParser(parserRef[i]);
- ICygwinToolsFactroy cygwinToolFactory = (ICygwinToolsFactroy) parser.getAdapter(ICygwinToolsFactroy.class);
- if (cygwinToolFactory != null) {
- cygPath = cygwinToolFactory.getCygPath();
- if (cygPath != null) {
- isAvailable = true;
- break;
- }
- }
- } catch (ClassCastException e) {
- }
- }
- // No CygPath specified in BinaryParser page or not supported.
- // Hoping that cygpath is on the path.
- if (cygPath == null && Platform.getOS().equals(Platform.OS_WIN32)) {
- if (new File(DEFAULT_CYGWIN_ROOT).exists()) {
- cygPath = new CygPath(DEFAULT_CYGWIN_ROOT + "\\bin\\cygpath.exe"); //$NON-NLS-1$
- } else {
- cygPath = new CygPath("cygpath"); //$NON-NLS-1$
- }
- isAvailable = cygPath.getFileName("test").equals("test"); //$NON-NLS-1$ //$NON-NLS-2$
- }
- }
- catch (CoreException e) {
- }
- catch (IOException e) {
- isAvailable = false;
- // Removing markers. if cygpath isn't in your path then you aren't using cygwin.
- // Then why are we calling this....
-// scMarkerGenerator.addMarker(project, -1,
-// MakeMessages.getString(CYGPATH_ERROR_MESSAGE),
-// IMarkerGenerator.SEVERITY_WARNING, null);
- }
- }
-
- public static List<String> translateIncludePaths(IProject project, List<String> sumIncludes) {
- // first check if cygpath translation is needed at all
- boolean translationNeeded = false;
- if (Platform.getOS().equals(Platform.OS_WIN32)) {
- for (Iterator<String> i = sumIncludes.iterator(); i.hasNext(); ) {
+ private static final String ENV_PATH = "PATH"; //$NON-NLS-1$
+
+ private CygPath cygPath = null;
+
+ public CygpathTranslator(IProject project) {
+ try {
+ ICConfigExtensionReference[] parserRef = CCorePlugin.getDefault().getDefaultBinaryParserExtensions(project);
+ for (int i = 0; i < parserRef.length; i++) {
+ try {
+ IBinaryParser parser = CoreModelUtil.getBinaryParser(parserRef[i]);
+ ICygwinToolsFactroy cygwinToolFactory = (ICygwinToolsFactroy) parser.getAdapter(ICygwinToolsFactroy.class);
+ if (cygwinToolFactory != null) {
+ cygPath = cygwinToolFactory.getCygPath();
+ }
+ } catch (ClassCastException e) {
+ }
+ }
+ }
+ catch (CoreException e) {
+ }
+ }
+
+ public static List<String> translateIncludePaths(IProject project, List<String> sumIncludes) {
+ // first check if cygpath translation is needed at all
+ boolean translationNeeded = false;
+ if (Platform.getOS().equals(Platform.OS_WIN32)) {
+ for (Iterator<String> i = sumIncludes.iterator(); i.hasNext(); ) {
String include = i.next();
if (include.startsWith("/")) { //$NON-NLS-1$
translationNeeded = true;
break;
}
}
- }
- if (!translationNeeded) {
- return sumIncludes;
- }
-
- CygpathTranslator cygpath = new CygpathTranslator(project);
-
- List<String> translatedIncludePaths = new ArrayList<String>();
- for (Iterator<String> i = sumIncludes.iterator(); i.hasNext(); ) {
- String includePath = i.next();
- IPath realPath = new Path(includePath);
- // only allow native pathes if they have a device prefix
- // to avoid matches on the current drive, e.g. /usr/bin = C:\\usr\\bin
- if (realPath.getDevice() != null && realPath.toFile().exists()) {
- translatedIncludePaths.add(includePath);
- }
- else {
- String translatedPath = includePath;
- if (cygpath.isAvailable) {
- try {
- translatedPath = cygpath.cygPath.getFileName(includePath);
- }
- catch (IOException e) {
- TraceUtil.outputError("CygpathTranslator unable to translate path: ", includePath); //$NON-NLS-1$
- }
- } else if (realPath.segmentCount() >= 2) {
- // try default conversions
- // /cygdrive/x/ --> X:\
- if ("cygdrive".equals(realPath.segment(0))) { //$NON-NLS-1$
- String drive= realPath.segment(1);
- if (drive.length() == 1) {
- translatedPath= realPath.removeFirstSegments(2).makeAbsolute().setDevice(drive.toUpperCase() + ':').toOSString();
- }
- }
- }
- if (!translatedPath.equals(includePath)) {
- // Check if the translated path exists
- if (new File(translatedPath).exists()) {
- translatedIncludePaths.add(translatedPath);
- }
- else if (cygpath.isAvailable) {
- // TODO VMIR for now add even if it does not exist
- translatedIncludePaths.add(translatedPath);
- }
- else {
- translatedIncludePaths.add(includePath);
- }
- }
- else {
- // TODO VMIR for now add even if it does not exist
- translatedIncludePaths.add(translatedPath);
- }
- }
- }
- if (cygpath.cygPath != null) {
- cygpath.cygPath.dispose();
- }
- return translatedIncludePaths;
- }
+ }
+ if (!translationNeeded) {
+ return sumIncludes;
+ }
+
+ CygpathTranslator cygpath = new CygpathTranslator(project);
+ boolean useCygPathExtension = cygpath.cygPath != null;
+ boolean useCygwinFromPath = !useCygPathExtension;
+
+ String envPath = null;
+ if (useCygwinFromPath) {
+ IEnvironmentVariableManager mngr = CCorePlugin.getDefault().getBuildEnvironmentManager();
+ ICProjectDescription prjDes = CCorePlugin.getDefault().getProjectDescription(project, false);
+ if (prjDes != null) {
+ // we don't know for sure which configuration needs to be used here, so betting on "DefaultSettingConfiguration"
+ // considering that scanner discovery uses "DefaultSettingConfiguration" rather than "Active" configuration,
+ // see org.eclipse.cdt.build.core.scannerconfig.ScannerConfigBuilder.build(CfgInfoContext context, ...)
+ ICConfigurationDescription cfgDes = prjDes.getDefaultSettingConfiguration();
+ IEnvironmentVariable envVar = mngr.getVariable(ENV_PATH, cfgDes, true);
+ if (envVar != null) {
+ envPath = envVar.getValue();
+ }
+ }
+ if (envPath == null) {
+ IEnvironmentVariable envVar = mngr.getVariable(ENV_PATH, null, true);
+ if (envVar != null) {
+ envPath = envVar.getValue();
+ }
+ }
+
+ useCygwinFromPath = Cygwin.isAvailable(envPath);
+ }
+
+ List<String> translatedIncludePaths = new ArrayList<String>();
+ for (Iterator<String> i = sumIncludes.iterator(); i.hasNext(); ) {
+ String includePath = i.next();
+ IPath realPath = new Path(includePath);
+ // only allow native pathes if they have a device prefix
+ // to avoid matches on the current drive, e.g. /usr/bin = C:\\usr\\bin
+ if (realPath.getDevice() != null && realPath.toFile().exists()) {
+ translatedIncludePaths.add(includePath);
+ }
+ else {
+ String translatedPath = includePath;
+
+ if (useCygPathExtension) {
+ try {
+ translatedPath = cygpath.cygPath.getFileName(includePath);
+ }
+ catch (IOException e) {
+ TraceUtil.outputError("CygpathTranslator unable to translate path: ", includePath); //$NON-NLS-1$
+ }
+ } else if (useCygwinFromPath) {
+ try {
+ translatedPath = Cygwin.cygwinToWindowsPath(includePath, envPath);
+ } catch (Exception e) {
+ MakeCorePlugin.log(e);
+ }
+ } else if (realPath.segmentCount() >= 2) {
+ // try default conversions
+ // /cygdrive/x/ --> X:\
+ if ("cygdrive".equals(realPath.segment(0))) { //$NON-NLS-1$
+ String drive= realPath.segment(1);
+ if (drive.length() == 1) {
+ translatedPath= realPath.removeFirstSegments(2).makeAbsolute().setDevice(drive.toUpperCase() + ':').toOSString();
+ }
+ }
+ }
+ if (!translatedPath.equals(includePath)) {
+ // Check if the translated path exists
+ if (new File(translatedPath).exists()) {
+ translatedIncludePaths.add(translatedPath);
+ }
+ else if (useCygPathExtension || useCygwinFromPath) {
+ // TODO VMIR for now add even if it does not exist
+ translatedIncludePaths.add(translatedPath);
+ }
+ else {
+ translatedIncludePaths.add(includePath);
+ }
+ }
+ else {
+ // TODO VMIR for now add even if it does not exist
+ translatedIncludePaths.add(translatedPath);
+ }
+ }
+ }
+ if (useCygPathExtension) {
+ cygpath.cygPath.dispose();
+ }
+ return translatedIncludePaths;
+ }
}
diff --git a/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/envvar/EnvironmentVariableManagerToolChain.java b/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/envvar/EnvironmentVariableManagerToolChain.java
new file mode 100644
index 00000000000..5072fc95c50
--- /dev/null
+++ b/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/envvar/EnvironmentVariableManagerToolChain.java
@@ -0,0 +1,220 @@
+/*******************************************************************************
+ * Copyright (c) 2012, 2012 Andrew Gvozdev and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Andrew Gvozdev - Initial API and implementation
+ *******************************************************************************/
+package org.eclipse.cdt.managedbuilder.internal.envvar;
+
+import org.eclipse.cdt.core.cdtvariables.ICdtVariable;
+import org.eclipse.cdt.core.envvar.IEnvironmentVariable;
+import org.eclipse.cdt.core.settings.model.ICConfigurationDescription;
+import org.eclipse.cdt.internal.core.cdtvariables.DefaultVariableContextInfo;
+import org.eclipse.cdt.internal.core.cdtvariables.EnvironmentVariableSupplier;
+import org.eclipse.cdt.internal.core.cdtvariables.ICoreVariableContextInfo;
+import org.eclipse.cdt.internal.core.envvar.DefaultEnvironmentContextInfo;
+import org.eclipse.cdt.internal.core.envvar.EnvVarDescriptor;
+import org.eclipse.cdt.internal.core.envvar.EnvironmentVariableManager;
+import org.eclipse.cdt.internal.core.envvar.ICoreEnvironmentVariableSupplier;
+import org.eclipse.cdt.internal.core.envvar.IEnvironmentContextInfo;
+import org.eclipse.cdt.managedbuilder.core.IConfiguration;
+import org.eclipse.cdt.managedbuilder.core.IToolChain;
+import org.eclipse.cdt.managedbuilder.core.ManagedBuildManager;
+import org.eclipse.cdt.managedbuilder.envvar.IConfigurationEnvironmentVariableSupplier;
+import org.eclipse.cdt.managedbuilder.envvar.IEnvironmentVariableProvider;
+import org.eclipse.cdt.utils.cdtvariables.ICdtVariableSupplier;
+import org.eclipse.cdt.utils.cdtvariables.IVariableContextInfo;
+
+
+/**
+ * Helper class to resolve environment variables directly from toolchain. The intention is
+ * to use that in New Project Wizard scenarios when no configuration is available yet.
+ */
+public class EnvironmentVariableManagerToolChain extends EnvironmentVariableManager {
+ private static EnvironmentVariableManagerToolChain fInstance = null;
+
+ /**
+ * Basically, converter from IEnvironmentVariable to ICdtVariable (build macros) which
+ * is used by EnvironmentVariableManager implementation to resolve variables/macros.
+ */
+ private final class CoreVariableContextInfoToolChain implements ICoreVariableContextInfo {
+ public final static int CONTEXT_TOOLCHAIN = 1009; // arbitrary value different from ICoreVariableContextInfo.CONTEXT_XXX
+
+ private final IToolChain toolChain;
+ private final IConfigurationEnvironmentVariableSupplier mbsSupplier;
+
+ private CoreVariableContextInfoToolChain(IToolChain toolChain) {
+ this.toolChain = toolChain;
+ this.mbsSupplier = toolChain.getEnvironmentVariableSupplier();
+ }
+
+ @Override
+ public ICdtVariableSupplier[] getSuppliers() {
+ ICdtVariableSupplier sup = new ICdtVariableSupplier() {
+ @Override
+ public ICdtVariable getVariable(String macroName, IVariableContextInfo context) {
+ IEnvironmentVariable var = mbsSupplier.getVariable(macroName, null, ManagedBuildManager.getEnvironmentVariableProvider());
+ return EnvironmentVariableSupplier.getInstance().createBuildMacro(var);
+ }
+ @Override
+ public ICdtVariable[] getVariables(IVariableContextInfo context) {
+ IEnvironmentVariable[] vars = mbsSupplier.getVariables(null, ManagedBuildManager.getEnvironmentVariableProvider());
+ if (vars != null) {
+ ICdtVariable[] cdtVars = new ICdtVariable[vars.length];
+ for (int i = 0; i < vars.length; i++) {
+ cdtVars[i] = EnvironmentVariableSupplier.getInstance().createBuildMacro(vars[i]);
+ }
+ }
+ return null;
+ }
+
+ };
+ return new ICdtVariableSupplier[] { sup };
+ }
+
+ @Override
+ public IVariableContextInfo getNext() {
+ return new DefaultVariableContextInfo(ICoreVariableContextInfo.CONTEXT_WORKSPACE, null);
+ }
+
+ @Override
+ public int getContextType() {
+ return CONTEXT_TOOLCHAIN;
+ }
+
+ @Override
+ public Object getContextData() {
+ return toolChain;
+ }
+ }
+
+ private final class EnvironmentContextInfoToolChain implements IEnvironmentContextInfo {
+ private final IToolChain toolChain;
+
+ private EnvironmentContextInfoToolChain(IToolChain toolChain) {
+ this.toolChain = toolChain;
+ }
+
+ @Override
+ public IEnvironmentContextInfo getNext() {
+ return new DefaultEnvironmentContextInfo(null);
+ }
+
+ @Override
+ public ICoreEnvironmentVariableSupplier[] getSuppliers() {
+ final IConfigurationEnvironmentVariableSupplier cevSupplier = toolChain.getEnvironmentVariableSupplier();
+
+ ICoreEnvironmentVariableSupplier toolchainSupplier = new ICoreEnvironmentVariableSupplier() {
+ @Override
+ public IEnvironmentVariable getVariable(String name, Object context) {
+ IEnvironmentVariableProvider provider = ManagedBuildManager.getEnvironmentVariableProvider();
+ return cevSupplier.getVariable(name, null, provider);
+ }
+ @Override
+ public IEnvironmentVariable[] getVariables(Object context) {
+ return cevSupplier.getVariables(null, ManagedBuildManager.getEnvironmentVariableProvider());
+ }
+ @Override
+ public boolean appendEnvironment(Object context) {
+ // Arbitrary value, it did not appear being used in tested scenarios
+ return false;
+ }
+ };
+ return new ICoreEnvironmentVariableSupplier[] { EnvironmentVariableManagerToolChain.fUserSupplier, toolchainSupplier };
+ }
+
+ @Override
+ public Object getContext() {
+ return toolChain;
+ }
+ }
+
+ public static EnvironmentVariableManagerToolChain getDefault() {
+ if (fInstance == null)
+ fInstance = new EnvironmentVariableManagerToolChain();
+ return fInstance;
+ }
+
+ @Override
+ public IEnvironmentContextInfo getContextInfo(Object level) {
+ if (level instanceof IToolChain) {
+ return new EnvironmentContextInfoToolChain((IToolChain) level);
+ }
+
+ return super.getContextInfo(level);
+ }
+
+ @Override
+ protected int getMacroContextTypeFromContext(Object context) {
+ if (context instanceof IToolChain) {
+ return CoreVariableContextInfoToolChain.CONTEXT_TOOLCHAIN;
+ }
+
+ return super.getMacroContextTypeFromContext(context);
+ }
+
+ @Override
+ public ICoreVariableContextInfo getMacroContextInfoForContext(Object context) {
+ if (context instanceof IToolChain) {
+ return new CoreVariableContextInfoToolChain((IToolChain) context);
+ }
+
+ return super.getMacroContextInfoForContext(context);
+ }
+
+ /**
+ * Get environment variable value from toolchain definition.
+ *
+ * @param name - name of the variable.
+ * @param toolChain - toolchain.
+ * @param resolveMacros - {@code true} to expand macros, {@code false} otherwise.
+ *
+ * @return value of the variable.
+ */
+ public IEnvironmentVariable getVariable(String name, IToolChain toolChain, boolean resolveMacros) {
+ if (name == null || name.isEmpty())
+ return null;
+
+ IEnvironmentContextInfo info = getContextInfo(toolChain);
+ EnvVarDescriptor var = EnvironmentVariableManagerToolChain.getVariable(name,info,true);
+
+ if (var != null && var.getOperation() != IEnvironmentVariable.ENVVAR_REMOVE) {
+ return resolveMacros ? calculateResolvedVariable(var,info) : var;
+ }
+ return null;
+ }
+
+ /**
+ * Get environment variable value resolved in context of configuration.
+ * If no configuration available use toolchain definition.
+ *
+ * @param name - name of the variable.
+ * @param toolChain - toolchain.
+ * @param resolveMacros - {@code true} to expand macros, {@code false} otherwise.
+ *
+ * @return value of the variable.
+ */
+ public String getVariableInConfigurationContext(String name, IToolChain toolChain, boolean resolveMacros) {
+ if (toolChain == null) {
+ return null;
+ }
+
+ IConfiguration cfg = toolChain.getParent();
+ ICConfigurationDescription cfgDescription = cfg != null ? ManagedBuildManager.getDescriptionForConfiguration(cfg) : null;
+
+ IEnvironmentVariable var = null;
+ if (cfgDescription != null) {
+ var = getVariable(name, cfgDescription, resolveMacros);
+ } else {
+ var = getVariable(name, toolChain, resolveMacros);
+ }
+
+ String value = var != null ? var.getValue() : null;
+ return value;
+ }
+
+}
diff --git a/build/org.eclipse.cdt.managedbuilder.gnu.ui/src/org/eclipse/cdt/managedbuilder/gnu/cygwin/CygwinPathResolver.java b/build/org.eclipse.cdt.managedbuilder.gnu.ui/src/org/eclipse/cdt/managedbuilder/gnu/cygwin/CygwinPathResolver.java
index 8f2b5b7e781..f3e5dc9e034 100644
--- a/build/org.eclipse.cdt.managedbuilder.gnu.ui/src/org/eclipse/cdt/managedbuilder/gnu/cygwin/CygwinPathResolver.java
+++ b/build/org.eclipse.cdt.managedbuilder.gnu.ui/src/org/eclipse/cdt/managedbuilder/gnu/cygwin/CygwinPathResolver.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2005, 2010 Intel Corporation and others.
+ * Copyright (c) 2005, 2013 Intel Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -9,6 +9,7 @@
* Intel Corporation - Initial API and implementation
* Enrico Ehrich - http://bugs.eclipse.org/233866
* Marc-Andre Laperle - fix for Cygwin GCC is Not detected (bug 303900)
+ * Andrew Gvozdev - changes to recognize $CYGWIN_HOME
*******************************************************************************/
package org.eclipse.cdt.managedbuilder.gnu.cygwin;
@@ -19,9 +20,8 @@ import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
-import org.eclipse.cdt.core.CCorePlugin;
import org.eclipse.cdt.core.envvar.IEnvironmentVariable;
-import org.eclipse.cdt.core.settings.model.util.CDataUtil;
+import org.eclipse.cdt.internal.core.Cygwin;
import org.eclipse.cdt.managedbuilder.core.IBuildPathResolver;
import org.eclipse.cdt.managedbuilder.core.IConfiguration;
import org.eclipse.cdt.managedbuilder.core.ManagedBuildManager;
@@ -30,40 +30,35 @@ import org.eclipse.cdt.utils.PathUtil;
import org.eclipse.cdt.utils.WindowsRegistry;
import org.eclipse.cdt.utils.spawner.ProcessFactory;
import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
/**
* @noextend This class is not intended to be subclassed by clients.
*/
public class CygwinPathResolver implements IBuildPathResolver {
- private static final String DEFAULT_ROOT = "C:\\cygwin"; //$NON-NLS-1$
- private static final String TOOL = "/cygpath -w -p "; //$NON-NLS-1$
- private static final char BS = '\\';
- private static final char SLASH = '/';
+ private static final String ENV_PATH = "PATH"; //$NON-NLS-1$
+ private static final String DELIMITER_UNIX = ":"; //$NON-NLS-1$
+ private static final String DELIMITER_WIN = ";"; //$NON-NLS-1$
+
private static final String PROPERTY_OS_NAME = "os.name"; //$NON-NLS-1$
- private static final String PROPERTY_OS_VALUE = "windows";//$NON-NLS-1$
- private static final String SP = " "; //$NON-NLS-1$
- private static final String REGISTRY_KEY_SETUP = "SOFTWARE\\Cygwin\\setup"; //$NON-NLS-1$
- private static final String REGISTRY_KEY_SETUP_WIN64 = "SOFTWARE\\Wow6432Node\\Cygwin\\setup"; //$NON-NLS-1$
+ private static final String OS_WINDOWS = "windows";//$NON-NLS-1$
+ private static final char SLASH = '/';
+ private static final char BACKSLASH = '\\';
+
+ private static final String CYGPATH_PATH_LIST_TO_WINDOWS = "cygpath -w -p "; //$NON-NLS-1$
+
// note that in Cygwin 1.7 the mount point storage has been moved out of the registry
private static final String REGISTRY_KEY_MOUNTS = "SOFTWARE\\Cygnus Solutions\\Cygwin\\mounts v2\\"; //$NON-NLS-1$
private static final String PATH_NAME = "native"; //$NON-NLS-1$
- private static final String SSLASH = "/"; //$NON-NLS-1$
- private static final String BSLASH = "\\\\"; //$NON-NLS-1$
private static final String BINPATTERN = "/usr/bin"; //$NON-NLS-1$
private static final String BINPATTERN_ALTERNATE = "/bin"; //$NON-NLS-1$
private static final String ETCPATTERN = "/etc"; //$NON-NLS-1$
- private static final String ROOTPATTERN = SSLASH;
- private static final String DELIMITER_UNIX = ":"; //$NON-NLS-1$
- private static final String DELIMITER_WIN = ";"; //$NON-NLS-1$
+
private static final String GCC_VERSION_CMD = "gcc --version"; //$NON-NLS-1$
private static final String MINGW_SPECIAL = "mingw "; //$NON-NLS-1$
private static final String CYGWIN_SPECIAL = "cygwin "; //$NON-NLS-1$
- private static String envPathValueCached = null;
- private static String binCygwin = null;
- private static String rootCygwin = null;
- private static String etcCygwin = null;
-
@Override
public String[] resolveBuildPaths(int pathType, String variableName, String variableValue, IConfiguration configuration) {
if(!isWindows()) {
@@ -72,58 +67,66 @@ public class CygwinPathResolver implements IBuildPathResolver {
return variableValue.split(DELIMITER_WIN);
}
- String[] result = variableValue.split(DELIMITER_UNIX);
- String exePath = getBinPath();
- if (exePath == null) {
- return result; // no changes
- }
- File file = new File(exePath);
- if (!file.exists() || !file.isDirectory()) {
- return result; // no changes
- }
- String s = exePath + TOOL + variableValue;
- String[] lines = exec(s, configuration);
+ String[] lines = executeInConfigurationContext(CYGPATH_PATH_LIST_TO_WINDOWS + variableValue, configuration);
if (lines != null && lines.length > 0) {
- result = lines[0].replace(BS,SLASH).split(DELIMITER_WIN);
+ String pathList = lines[0].replace(BACKSLASH, SLASH);
+ return pathList.split(DELIMITER_WIN);
}
- return result;
+
+ return variableValue.split(DELIMITER_UNIX);
}
/**
- * returns "/etc" path in Windows format
+ * @return "/etc" path in Windows format for workspace.
+ * @deprecated. Deprecated as of CDT 8.2. Note that Cygwin root path in general may depend on configuration.
*
* If you use this do not cache results to ensure user preferences are accounted for.
* Please rely on internal caching.
*/
+ @Deprecated
public static String getEtcPath() {
- findPaths();
+ String etcCygwin = getPathFromRoot(ETCPATTERN);
+ // Try to find the paths in SOFTWARE\\Cygnus Solutions
+ if(etcCygwin == null) {
+ etcCygwin = readValueFromRegistry(REGISTRY_KEY_MOUNTS + ETCPATTERN, PATH_NAME);
+ }
return etcCygwin;
}
/**
- * returns "/usr/bin" path in Windows format
+ * @return "/usr/bin" path in Windows format for workspace.
+ * @deprecated. Deprecated as of CDT 8.2. Note that Cygwin root path in general may depend on configuration.
*
* If you use this do not cache results to ensure user preferences are accounted for.
* Please rely on internal caching.
*/
+ @Deprecated
public static String getBinPath() {
- findPaths();
+ String binCygwin = getPathFromRoot(BINPATTERN);
+ if(binCygwin == null) {
+ binCygwin = getPathFromRoot(BINPATTERN_ALTERNATE);
+ }
+ // Try to find the paths in SOFTWARE\\Cygnus Solutions
+ if(binCygwin == null) {
+ binCygwin = readValueFromRegistry(REGISTRY_KEY_MOUNTS + BINPATTERN, PATH_NAME);
+ }
return binCygwin;
}
/**
- * returns Cygwin root ("/") path in Windows format
+ * @return Cygwin root ("/") path in Windows format for workspace.
+ * @deprecated. Deprecated as of CDT 8.2. Note that Cygwin root path in general may depend on configuration.
*
* If you use this do not cache results to ensure user preferences are accounted for.
* Please rely on internal caching.
*/
+ @Deprecated
public static String getRootPath() {
- findPaths();
- return rootCygwin;
+ return Cygwin.getCygwinHome();
}
public static boolean isWindows() {
- return (System.getProperty(PROPERTY_OS_NAME).toLowerCase().startsWith(PROPERTY_OS_VALUE));
+ return (System.getProperty(PROPERTY_OS_NAME).toLowerCase().startsWith(OS_WINDOWS));
}
/**
@@ -136,146 +139,117 @@ public class CygwinPathResolver implements IBuildPathResolver {
*/
private static String readValueFromRegistry(String key, String name) {
WindowsRegistry registry = WindowsRegistry.getRegistry();
- if (null != registry) {
- String s = registry.getCurrentUserValue(key, name);
- if(s == null)
- s = registry.getLocalMachineValue(key, name);
-
- if (s != null)
- return (s.replaceAll(BSLASH, SSLASH));
+ if (registry != null) {
+ String value = registry.getCurrentUserValue(key, name);
+ if (value == null) {
+ value = registry.getLocalMachineValue(key, name);
+ }
+ if (value != null) {
+ return value.replace(BACKSLASH, SLASH);
+ }
}
return null;
}
/**
- * Returns the absolute path of the pattern by
- * simply appending the pattern to the root
+ * Returns the absolute path of the pattern by simply appending the relativePath to the root.
*
- * @param pattern The pattern to find
- * @return The absolute path to the pattern or null if pattern is not found
+ * @param relativePath - the pattern to find.
+ * @return The absolute path to the pattern or {@code null} if path does not exist.
*/
- private static String getValueFromRoot(String pattern) {
+ private static String getPathFromRoot(String relativePath) {
+ String rootCygwin = Cygwin.getCygwinHome();
if (rootCygwin != null) {
- String path = rootCygwin + pattern;
+ String path = rootCygwin + relativePath;
File file = new File(path);
- if (file.exists() && file.isDirectory())
- return (path.replaceAll(BSLASH, SSLASH));
- else
- return null;
+ if (file.exists() && file.isDirectory()) {
+ return path.replace(BACKSLASH, SLASH);
+ }
}
-
return null;
}
/**
- * Returns the absolute path to cygwin's root
+ * Resolve and return full path to program in context of configuration.
*
- * @return The absolute path to cygwin's root or null if not found
+ * @param program - program to resolve.
+ * @param cfg - configuration context.
+ * @return absolute path to program.
*/
- private static String findRoot(String paths) {
- String rootValue = null;
-
- // 1. Look in PATH values. Look for bin\cygwin1.dll
- IPath location = PathUtil.findProgramLocation("cygwin1.dll", paths); //$NON-NLS-1$
- if (location!=null) {
- rootValue = location.removeLastSegments(2).toOSString();
- }
-
- // 2. Try to find the root dir in SOFTWARE\Cygwin\setup
- if(rootValue == null) {
- rootValue = readValueFromRegistry(REGISTRY_KEY_SETUP, "rootdir"); //$NON-NLS-1$
- }
-
- // 3. Try to find the root dir in SOFTWARE\Wow6432Node\Cygwin\setup
- if(rootValue == null) {
- rootValue = readValueFromRegistry(REGISTRY_KEY_SETUP_WIN64, "rootdir"); //$NON-NLS-1$
- }
-
- // 4. Try to find the root dir in SOFTWARE\Cygnus Solutions
- if (rootValue == null) {
- rootValue = readValueFromRegistry(REGISTRY_KEY_MOUNTS + ROOTPATTERN, PATH_NAME);
- }
-
- // 5. Try the default Cygwin install dir
- if(rootValue == null) {
- File file = new File(DEFAULT_ROOT);
- if (file.exists() && file.isDirectory())
- rootValue = DEFAULT_ROOT;
+ private static String resolveProgram(String program, IConfiguration cfg) {
+ String envPathValue = null;
+ try {
+ IEnvironmentVariable envPathVar = ManagedBuildManager.getEnvironmentVariableProvider().getVariable(ENV_PATH, cfg, true);
+ if (envPathVar != null) {
+ envPathValue = envPathVar.getValue();
+ IPath progPath = PathUtil.findProgramLocation(program, envPathValue);
+ if (progPath != null) {
+ program = progPath.toOSString();
+ }
+ // this resolves cygwin symbolic links
+ program = Cygwin.cygwinToWindowsPath(program, envPathValue);
+ }
+ } catch (Exception e) {
+ GnuUIPlugin.getDefault().log(new Status(IStatus.WARNING, GnuUIPlugin.PLUGIN_ID, "Problem trying to find program [" + program + "] in $PATH=[" + envPathValue + "]", e));
}
-
- if(rootValue != null)
- rootValue = rootValue.replaceAll(BSLASH, SSLASH);
-
- return rootValue;
+ return program;
}
/**
- * Finds Cygwin's paths and sets corresponding properties.
+ * Return environment in envp format, see {@link Runtime#exec(String, String[])}.
+ *
+ * @param cfg - configuration.
+ * @return environment as array of strings in format name=value.
*/
- private static synchronized void findPaths() {
- if (!isWindows()) {
- return;
+ private static String[] getEnvp(IConfiguration cfg) {
+ IEnvironmentVariable vars[] = ManagedBuildManager.getEnvironmentVariableProvider().getVariables(cfg,true);
+ String envp[] = new String[vars.length];
+ for(int i = 0; i < envp.length; i++) {
+ envp[i] = vars[i].getName() +'=';
+ String value = vars[i].getValue();
+ if(value != null)
+ envp[i] += value;
}
-
- IEnvironmentVariable varPath = CCorePlugin.getDefault().getBuildEnvironmentManager().getVariable("PATH", null, true); //$NON-NLS-1$
- String envPathValue = varPath != null ? varPath.getValue() : null;
-
- if (CDataUtil.objectsEqual(envPathValue, envPathValueCached)) {
- return;
- }
-
- etcCygwin = null;
- binCygwin = null;
- rootCygwin = null;
-
- rootCygwin = findRoot(envPathValue);
-
- // 1. Try to find the paths by appending the patterns to the root dir
- etcCygwin = getValueFromRoot(ETCPATTERN);
- binCygwin = getValueFromRoot(BINPATTERN);
- if(binCygwin == null)
- binCygwin = getValueFromRoot(BINPATTERN_ALTERNATE);
-
- // 2. Try to find the paths in SOFTWARE\\Cygnus Solutions
- if(etcCygwin == null)
- etcCygwin = readValueFromRegistry(REGISTRY_KEY_MOUNTS + ETCPATTERN, PATH_NAME);
- if(binCygwin == null)
- binCygwin = readValueFromRegistry(REGISTRY_KEY_MOUNTS + BINPATTERN, PATH_NAME);
-
- envPathValueCached = envPathValue;
+ return envp;
}
- private static String[] exec(String cmd, IConfiguration cfg) {
+ /**
+ * Execute command taking in account configuration environment.
+ *
+ * @param cmd - command to execute.
+ * @param cfg - configuration context.
+ * @return command output as string array.
+ */
+ private static String[] executeInConfigurationContext(String cmd, IConfiguration cfg) {
+ String[] args = cmd.split(" "); //$NON-NLS-1$
+ args[0] = resolveProgram(args[0], cfg);
+
+ String[] result = null;
try {
- IEnvironmentVariable vars[] = ManagedBuildManager.getEnvironmentVariableProvider().getVariables(cfg,true);
- String env[] = new String[vars.length];
- for(int i = 0; i < env.length; i++) {
- env[i] = vars[i].getName() + "="; //$NON-NLS-1$
- String value = vars[i].getValue();
- if(value != null)
- env[i] += value;
- }
- Process proc = ProcessFactory.getFactory().exec(cmd.split(SP), env);
+ String[] envp = getEnvp(cfg);
+ Process proc = ProcessFactory.getFactory().exec(args, envp);
if (proc != null) {
-
InputStream ein = proc.getInputStream();
- BufferedReader d1 = new BufferedReader(new InputStreamReader(ein));
- ArrayList<String> ls = new ArrayList<String>(10);
- String s;
- while ((s = d1.readLine() ) != null ) {
- ls.add(s);
+ try {
+ BufferedReader d1 = new BufferedReader(new InputStreamReader(ein));
+ ArrayList<String> ls = new ArrayList<String>(10);
+ String s;
+ while ((s = d1.readLine()) != null ) {
+ ls.add(s);
+ }
+ result = ls.toArray(new String[0]);
+ } finally {
+ ein.close();
}
- ein.close();
- return ls.toArray(new String[0]);
}
} catch (IOException e) {
- GnuUIPlugin.getDefault().log(e);
+ GnuUIPlugin.getDefault().log(new Status(IStatus.ERROR, GnuUIPlugin.PLUGIN_ID, "Error executing program [" +cmd + "]", e));
}
- return null;
+ return result;
}
public static boolean isMinGW(IConfiguration cfg) {
- String versionInfo[] = exec(GCC_VERSION_CMD, cfg);
+ String versionInfo[] = executeInConfigurationContext(GCC_VERSION_CMD, cfg);
if(versionInfo != null) {
for(int i = 0; i < versionInfo.length; i++) {
if(versionInfo[i].indexOf(MINGW_SPECIAL) != -1)
diff --git a/build/org.eclipse.cdt.managedbuilder.gnu.ui/src/org/eclipse/cdt/managedbuilder/gnu/cygwin/GnuCygwinConfigurationEnvironmentSupplier.java b/build/org.eclipse.cdt.managedbuilder.gnu.ui/src/org/eclipse/cdt/managedbuilder/gnu/cygwin/GnuCygwinConfigurationEnvironmentSupplier.java
index ae08fcf841d..5b659ead2d2 100644
--- a/build/org.eclipse.cdt.managedbuilder.gnu.ui/src/org/eclipse/cdt/managedbuilder/gnu/cygwin/GnuCygwinConfigurationEnvironmentSupplier.java
+++ b/build/org.eclipse.cdt.managedbuilder.gnu.ui/src/org/eclipse/cdt/managedbuilder/gnu/cygwin/GnuCygwinConfigurationEnvironmentSupplier.java
@@ -1,33 +1,38 @@
/*******************************************************************************
- * Copyright (c) 2005, 2011 Intel Corporation and others.
+ * Copyright (c) 2005, 2012 Intel Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
- * Intel Corporation - Initial API and implementation
+ * Intel Corporation - Initial API and implementation
+ * Andrew Gvozdev - Ability to use different Cygwin versions in different cfg
*******************************************************************************/
package org.eclipse.cdt.managedbuilder.gnu.cygwin;
+import org.eclipse.cdt.core.CCorePlugin;
+import org.eclipse.cdt.core.envvar.IEnvironmentVariable;
+import org.eclipse.cdt.internal.core.Cygwin;
import org.eclipse.cdt.managedbuilder.core.IConfiguration;
import org.eclipse.cdt.managedbuilder.envvar.IBuildEnvironmentVariable;
import org.eclipse.cdt.managedbuilder.envvar.IConfigurationEnvironmentVariableSupplier;
import org.eclipse.cdt.managedbuilder.envvar.IEnvironmentVariableProvider;
import org.eclipse.cdt.managedbuilder.internal.envvar.BuildEnvVar;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.Path;
/**
* @noextend This class is not intended to be subclassed by clients.
*/
public class GnuCygwinConfigurationEnvironmentSupplier implements IConfigurationEnvironmentVariableSupplier {
- private static final String PATH = "PATH"; //$NON-NLS-1$
- private static final String DELIMITER_UNIX = ":"; //$NON-NLS-1$
- private static final String PROPERTY_DELIMITER = "path.separator"; //$NON-NLS-1$
- private static final String PROPERTY_OSNAME = "os.name"; //$NON-NLS-1$
+ private static final String ENV_PATH = "PATH"; //$NON-NLS-1$
+ private static final String ENV_LANG = "LANG"; //$NON-NLS-1$
+ private static final String ENV_LC_ALL = "LC_ALL"; //$NON-NLS-1$
+ private static final String ENV_LC_MESSAGES = "LC_MESSAGES"; //$NON-NLS-1$
- private static final String LANG = "LANG"; //$NON-NLS-1$
- private static final String LC_ALL = "LC_ALL"; //$NON-NLS-1$
- private static final String LC_MESSAGES = "LC_MESSAGES"; //$NON-NLS-1$
+ private static final String PROPERTY_OSNAME = "os.name"; //$NON-NLS-1$
+ private static final String BACKSLASH = java.io.File.separator;
@Override
public IBuildEnvironmentVariable getVariable(String variableName, IConfiguration configuration, IEnvironmentVariableProvider provider) {
@@ -39,19 +44,33 @@ public class GnuCygwinConfigurationEnvironmentSupplier implements IConfiguration
return null;
}
- if (variableName.equalsIgnoreCase(PATH)) {
- String p = CygwinPathResolver.getBinPath();
- if (p != null) {
- return new BuildEnvVar(PATH, p.replace('/','\\'), IBuildEnvironmentVariable.ENVVAR_PREPEND, System.getProperty(PROPERTY_DELIMITER, DELIMITER_UNIX));
+ if (variableName.equalsIgnoreCase(ENV_PATH)) {
+ @SuppressWarnings("nls")
+ String path = "${" + Cygwin.ENV_CYGWIN_HOME + "}" + BACKSLASH + "bin";
+ return new BuildEnvVar(ENV_PATH, path, IBuildEnvironmentVariable.ENVVAR_PREPEND);
+
+ } else if (variableName.equals(Cygwin.ENV_CYGWIN_HOME)) {
+ String home = Cygwin.getCygwinHome();
+ // If the variable is not defined still show it in the environment variables list as a hint to user
+ if (home == null) {
+ home = ""; //$NON-NLS-1$
+ }
+ IPath homePath = new Path(home);
+ IEnvironmentVariable varCygwinHome = CCorePlugin.getDefault().getBuildEnvironmentManager().getVariable(Cygwin.ENV_CYGWIN_HOME, null, false);
+ if (varCygwinHome == null || (!homePath.equals(new Path(varCygwinHome.getValue())))) {
+ // Contribute if the variable does not already come from workspace environment
+ return new BuildEnvVar(Cygwin.ENV_CYGWIN_HOME, homePath.toOSString());
}
- } else if (variableName.equalsIgnoreCase(LANG)) {
+ return null;
+
+ } else if (variableName.equalsIgnoreCase(ENV_LANG)) {
// Workaround for not being able to select encoding for CDT console -> change codeset to Latin1
- String langValue = System.getenv(LANG);
+ String langValue = System.getenv(ENV_LANG);
if (langValue == null || langValue.length() == 0) {
- langValue = System.getenv(LC_ALL);
+ langValue = System.getenv(ENV_LC_ALL);
}
if (langValue == null || langValue.length() == 0) {
- langValue = System.getenv(LC_MESSAGES);
+ langValue = System.getenv(ENV_LC_MESSAGES);
}
if (langValue != null && langValue.length() > 0) {
// langValue is [language[_territory][.codeset][@modifier]], i.e. "en_US.UTF-8@dict"
@@ -61,21 +80,17 @@ public class GnuCygwinConfigurationEnvironmentSupplier implements IConfiguration
} else {
langValue = "C.ISO-8859-1"; //$NON-NLS-1$
}
-
- return new BuildEnvVar(LANG, langValue);
+ return new BuildEnvVar(ENV_LANG, langValue);
}
return null;
}
@Override
public IBuildEnvironmentVariable[] getVariables(IConfiguration configuration, IEnvironmentVariableProvider provider) {
- IBuildEnvironmentVariable varLang = getVariable(LANG, configuration, provider);
- IBuildEnvironmentVariable varPath = getVariable(PATH, configuration, provider);
+ IBuildEnvironmentVariable varHome = getVariable(Cygwin.ENV_CYGWIN_HOME, configuration, provider);
+ IBuildEnvironmentVariable varLang = getVariable(ENV_LANG, configuration, provider);
+ IBuildEnvironmentVariable varPath = getVariable(ENV_PATH, configuration, provider);
- if (varPath != null) {
- return new IBuildEnvironmentVariable[] {varLang, varPath};
- } else {
- return new IBuildEnvironmentVariable[] {varLang};
- }
+ return new IBuildEnvironmentVariable[] {varHome, varLang, varPath};
}
}
diff --git a/build/org.eclipse.cdt.managedbuilder.gnu.ui/src/org/eclipse/cdt/managedbuilder/gnu/cygwin/IsGnuCygwinToolChainSupported.java b/build/org.eclipse.cdt.managedbuilder.gnu.ui/src/org/eclipse/cdt/managedbuilder/gnu/cygwin/IsGnuCygwinToolChainSupported.java
index a2d2050338a..9a2fd648827 100644
--- a/build/org.eclipse.cdt.managedbuilder.gnu.ui/src/org/eclipse/cdt/managedbuilder/gnu/cygwin/IsGnuCygwinToolChainSupported.java
+++ b/build/org.eclipse.cdt.managedbuilder.gnu.ui/src/org/eclipse/cdt/managedbuilder/gnu/cygwin/IsGnuCygwinToolChainSupported.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2005, 2010 Intel Corporation and others.
+ * Copyright (c) 2005, 2013 Intel Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -7,85 +7,28 @@
*
* Contributors:
* Intel Corporation - Initial API and implementation
+ * Andrew Gvozdev - Ability to use different Cygwin versions in different configurations
*******************************************************************************/
package org.eclipse.cdt.managedbuilder.gnu.cygwin;
-import java.io.BufferedReader;
-import java.io.File;
-import java.io.FileNotFoundException;
-import java.io.FileReader;
-import java.io.IOException;
-
-import org.eclipse.cdt.core.settings.model.util.CDataUtil;
+import org.eclipse.cdt.internal.core.Cygwin;
import org.eclipse.cdt.managedbuilder.core.IManagedIsToolChainSupported;
import org.eclipse.cdt.managedbuilder.core.IToolChain;
+import org.eclipse.cdt.managedbuilder.internal.envvar.EnvironmentVariableManagerToolChain;
import org.osgi.framework.Version;
/**
* This class implements the IManagedIsToolChainSupported for the Gnu Cygwin tool-chain
- * The class is NOT used currently, because currently the gnu cygwin tool-chain
- * is intended to be used not only with Cygwin, but with MinGW also, and there is no
- * correct way of determining whether the appropriate packages are installed for MinGW.
- *
- * For the future MBS/CDT versions we might create the separate tool-chain/configuration/project-type
- * for the MinGW and define a set of converters using the tool-chain converter mechanism that MBS will provide,
- * that would convert the CygWin to the MinGW projects/tool-chains, and vice a versa.
*
* @noextend This class is not intended to be subclassed by clients.
*/
public class IsGnuCygwinToolChainSupported implements IManagedIsToolChainSupported {
- private static final String[] CHECKED_NAMES = {"gcc", "binutils", "make"}; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+ private static final String ENV_PATH = "PATH"; //$NON-NLS-1$
- private static String etcCygwinCached = null;
- private static boolean toolchainIsSupported = false;
-
- /**
- * @since 8.0
- */
@Override
public boolean isSupported(IToolChain toolChain, Version version, String instance) {
- String etcCygwin = CygwinPathResolver.getEtcPath();
- if (CDataUtil.objectsEqual(etcCygwin, etcCygwinCached)) {
- return toolchainIsSupported;
- }
-
- toolchainIsSupported = etcCygwin != null && arePackagesInstalled(etcCygwin);
- etcCygwinCached = etcCygwin;
-
- return toolchainIsSupported;
+ String envPath = EnvironmentVariableManagerToolChain.getDefault().getVariableInConfigurationContext(ENV_PATH, toolChain, true);
+ return Cygwin.isAvailable(envPath);
}
- /**
- * Returns true if all required packages are installed, see CHECKED_NAMES for a list of packages. Cygwin
- * maintains a list of packages in /etc/setup/installed.db so we look for packages in this file.
- *
- * @param etcCygwin the absolute path of /etc containing /setup/installed.db
- * @return true if the packages specified in CHECKED_NAMES are installed
- */
- private boolean arePackagesInstalled(String etcCygwin) {
- boolean arePackagesInstalled = false;
- File file = new File(etcCygwin + "/setup/installed.db"); //$NON-NLS-1$
- try {
- BufferedReader data = new BufferedReader(new FileReader(file));
-
- // All required package names should be found
- boolean[] found = new boolean[CHECKED_NAMES.length];
- String s;
- while ((s = data.readLine()) != null ) {
- for (int j = 0; j < CHECKED_NAMES.length; j++) {
- if (s.startsWith(CHECKED_NAMES[j])) {
- found[j] = true;
- }
- }
- }
- arePackagesInstalled = true;
- for (int j = 0; j < CHECKED_NAMES.length; j++) {
- arePackagesInstalled &= found[j];
- }
- data.close();
- } catch (FileNotFoundException e) {
- } catch (IOException e) {
- }
- return arePackagesInstalled;
- }
}
diff --git a/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/internal/core/Cygwin.java b/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/internal/core/Cygwin.java
index e0b770d87c9..bd878b12cd7 100644
--- a/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/internal/core/Cygwin.java
+++ b/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/internal/core/Cygwin.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2012, 2012 Andrew Gvozdev and others.
+ * Copyright (c) 2012, 2013 Andrew Gvozdev 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
@@ -11,24 +11,74 @@
package org.eclipse.cdt.internal.core;
import java.io.BufferedReader;
+import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
+import java.util.Collections;
+import java.util.Map;
+import org.eclipse.cdt.core.CCorePlugin;
+import org.eclipse.cdt.core.envvar.IEnvironmentVariable;
+import org.eclipse.cdt.core.settings.model.util.CDataUtil;
import org.eclipse.cdt.utils.PathUtil;
+import org.eclipse.cdt.utils.WindowsRegistry;
import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.Platform;
/**
* A collection of cygwin-related utilities.
*/
public class Cygwin {
+ public static final String ENV_CYGWIN_HOME = "CYGWIN_HOME"; //$NON-NLS-1$
+ private static final String ENV_PATH = "PATH"; //$NON-NLS-1$
- private static IPath findCygpathLocation(String envPath) {
- return PathUtil.findProgramLocation("cygpath", envPath); //$NON-NLS-1$
+ private static final String CYGPATH = "cygpath"; //$NON-NLS-1$
+ private static final String DEFAULT_ROOT = "C:\\cygwin"; //$NON-NLS-1$
+ private static final String CYGWIN_DLL = "cygwin1.dll"; //$NON-NLS-1$
+ private static final String REGISTRY_KEY_SETUP = "SOFTWARE\\Cygwin\\setup"; //$NON-NLS-1$
+ private static final String REGISTRY_KEY_SETUP_WIN64 = "SOFTWARE\\Wow6432Node\\Cygwin\\setup"; //$NON-NLS-1$
+ // note that in Cygwin 1.7 the mount point storage has been moved out of the registry
+ private static final String REGISTRY_KEY_MOUNTS = "SOFTWARE\\Cygnus Solutions\\Cygwin\\mounts v2\\"; //$NON-NLS-1$
+ private static final String PATH_NAME = "native"; //$NON-NLS-1$
+ private static final String ROOTPATTERN = "/"; //$NON-NLS-1$
+ private static final char SLASH = '/';
+ private static final char BACKSLASH = '\\';
+
+ private static final boolean isWindowsPlatform = Platform.getOS().equals(Platform.OS_WIN32);
+
+ private static String envPathValueCached = null;
+ private static String envCygwinHomeValueCached = null;
+ private static String cygwinLocation = null;
+ private static boolean isCygwinLocationCached = false;
+
+ private final static Map<String/*envPath*/, String /*cygpathLocation*/> cygpathLocationCache = Collections.synchronizedMap(new LRUCache<String, String>(1,20));
+ private final static Map<String/*command*/, String /*translatedPath*/> translatedPathsCache = Collections.synchronizedMap(new LRUCache<String, String>(10,500));
+
+ /**
+ * Find location of "cygpath" utility on the file system.
+ */
+ private static String findCygpathLocation(String envPath) {
+ if (envPath == null) {
+ // $PATH from user preferences
+ IEnvironmentVariable varPath = CCorePlugin.getDefault().getBuildEnvironmentManager().getVariable(ENV_PATH, null, true);
+ if (varPath != null) {
+ envPath = varPath.getValue();
+ }
+ }
+
+ String cygpathLocation = cygpathLocationCache.get(envPath);
+ if (cygpathLocation == null) {
+ IPath loc = PathUtil.findProgramLocation(CYGPATH, envPath);
+ cygpathLocation = loc != null ? loc.toOSString() : null;
+ cygpathLocationCache.put(envPath, cygpathLocation);
+ }
+ return cygpathLocation;
}
/**
* Check if cygwin path conversion utilities are available in the path.
+ * Tells whether cygwin is installed in the path.
*
* @param envPath - list of directories to search for cygwin utilities separated
* by path separator (format of environment variable $PATH)
@@ -36,22 +86,60 @@ public class Cygwin {
* @return {@code true} if cygwin is available, {@code false} otherwise.
*/
public static boolean isAvailable(String envPath) {
- return Platform.getOS().equals(Platform.OS_WIN32) && findCygpathLocation(envPath) != null;
+ return isWindowsPlatform && findCygpathLocation(envPath) != null;
}
/**
* Check if cygwin path conversion utilities are available in $PATH.
+ * Tells whether cygwin is installed in the path.
*
* @return {@code true} if cygwin is available, {@code false} otherwise.
*/
public static boolean isAvailable() {
- return Platform.getOS().equals(Platform.OS_WIN32) && findCygpathLocation(null) != null;
+ return isWindowsPlatform && findCygpathLocation(null) != null;
+ }
+
+ /**
+ * Run program (assuming cygpath) and return the translated path which is the first line of output.
+ */
+ private static String runCygpath(String[] args) throws IOException {
+ String command = getCommand(args);
+ String translatedPath = translatedPathsCache.get(command);
+ if (translatedPath == null) {
+ Process cygpathProcess = Runtime.getRuntime().exec(args);
+ BufferedReader stdout = new BufferedReader(new InputStreamReader(cygpathProcess.getInputStream()));
+ String firstLine = null;
+ try {
+ firstLine = stdout.readLine();
+ } finally {
+ stdout.close();
+ }
+ if (firstLine == null) {
+ throw new IOException("Unable read output from command=[" + command + "]"); //$NON-NLS-1$ //$NON-NLS-2$
+ }
+ translatedPath = firstLine.trim();
+ translatedPathsCache.put(command, translatedPath);
+ }
+
+ return translatedPath;
+ }
+
+ /**
+ * Construct a command from arguments array.
+ */
+ private static String getCommand(String[] args) {
+ String command = ""; //$NON-NLS-1$
+ for (String arg : args) {
+ command = command + arg + ' ';
+ }
+ return command.trim();
}
/**
* Conversion from Cygwin path to Windows path.
+ * Note that there is no need to cache results, they are already cached internally.
*
- * @param cygwinPath - Cygwin path.
+ * @param cygwinPath - cygwin path.
* @param envPath - list of directories to search for cygwin utilities separated
* by path separator (format of environment variable $PATH).
* @return Windows style converted path. Note that that also converts cygwin links to their targets.
@@ -63,31 +151,24 @@ public class Cygwin {
if (cygwinPath == null || cygwinPath.trim().length() == 0)
return cygwinPath;
- if (!Platform.getOS().equals(Platform.OS_WIN32)) {
- // Don't run this on non-windows platforms
+ if (!isWindowsPlatform) {
throw new UnsupportedOperationException("Not a Windows system, Cygwin is unavailable."); //$NON-NLS-1$
}
- IPath cygpathLocation = findCygpathLocation(envPath);
+ String cygpathLocation = findCygpathLocation(envPath);
if (cygpathLocation == null) {
- throw new UnsupportedOperationException("Cygwin utility cygpath is not in the system search path."); //$NON-NLS-1$
+ throw new UnsupportedOperationException(CYGPATH + " is not in the system search path."); //$NON-NLS-1$
}
- String[] args = {cygpathLocation.toOSString(), "-w", cygwinPath}; //$NON-NLS-1$
- Process cygpathProcess = Runtime.getRuntime().exec(args);
- BufferedReader stdout = new BufferedReader(new InputStreamReader(cygpathProcess.getInputStream()));
-
- String windowsPath = stdout.readLine();
- if (windowsPath == null) {
- throw new IOException("Unexpected output from Cygwin utility cygpath."); //$NON-NLS-1$
- }
- return windowsPath.trim();
+ String windowsPath = runCygpath(new String[] {cygpathLocation, "-w", cygwinPath}); //$NON-NLS-1$
+ return windowsPath;
}
/**
* Conversion from Cygwin path to Windows path.
+ * Note that there is no need to cache results, they are already cached internally.
*
- * @param cygwinPath - Cygwin path.
+ * @param cygwinPath - cygwin path.
* @return Windows style converted path. Note that that also converts cygwin links to their targets.
*
* @throws UnsupportedOperationException if Cygwin is unavailable.
@@ -99,6 +180,7 @@ public class Cygwin {
/**
* Conversion from Windows path to Cygwin path.
+ * Note that there is no need to cache results, they are already cached internally.
*
* @param windowsPath - Windows path.
* @param envPath - list of directories to search for cygwin utilities (value of environment variable $PATH).
@@ -111,28 +193,22 @@ public class Cygwin {
if (windowsPath == null || windowsPath.trim().length() == 0)
return windowsPath;
- if (!Platform.getOS().equals(Platform.OS_WIN32)) {
- // Don't run this on non-windows platforms
+ if (!isWindowsPlatform) {
throw new UnsupportedOperationException("Not a Windows system, Cygwin is unavailable."); //$NON-NLS-1$
}
- IPath cygpathLocation = findCygpathLocation(envPath);
+
+ String cygpathLocation = findCygpathLocation(envPath);
if (cygpathLocation == null) {
- throw new UnsupportedOperationException("Cygwin utility cygpath is not in the system search path."); //$NON-NLS-1$
+ throw new UnsupportedOperationException(CYGPATH + " is not in the system search path."); //$NON-NLS-1$
}
- String[] args = {cygpathLocation.toOSString(), "-u", windowsPath}; //$NON-NLS-1$
- Process cygpath = Runtime.getRuntime().exec(args);
- BufferedReader stdout = new BufferedReader(new InputStreamReader(cygpath.getInputStream()));
-
- String cygwinPath = stdout.readLine();
- if (cygwinPath == null) {
- throw new IOException("Unexpected output from Cygwin utility cygpath."); //$NON-NLS-1$
- }
- return cygwinPath.trim();
+ String cygwinPath = runCygpath(new String[] {cygpathLocation, "-u", windowsPath}); //$NON-NLS-1$
+ return cygwinPath;
}
/**
* Conversion from Windows path to Cygwin path.
+ * Note that there is no need to cache results, they are already cached internally.
*
* @param windowsPath - Windows path.
* @return Cygwin style converted path.
@@ -143,4 +219,114 @@ public class Cygwin {
public static String windowsToCygwinPath(String windowsPath) throws IOException, UnsupportedOperationException {
return windowsToCygwinPath(windowsPath, null);
}
+
+ /**
+ * Find location where Cygwin is installed. A number of locations is being checked,
+ * such as environment variable $CYGWIN_HOME, $PATH, Windows registry et al.
+ * <br><br>
+ * If you use this do not cache results to ensure user preferences are accounted for.
+ * Please rely on internal caching.
+ *
+ * @return Location of Cygwin root folder "/" on file system in Windows format.
+ */
+ public static String getCygwinHome() {
+ if (!isWindowsPlatform) {
+ return null;
+ }
+
+ IEnvironmentVariable varPath = CCorePlugin.getDefault().getBuildEnvironmentManager().getVariable(ENV_PATH, null, true);
+ String envPathValue = varPath != null ? varPath.getValue() : null;
+ IEnvironmentVariable varCygwinHome = CCorePlugin.getDefault().getBuildEnvironmentManager().getVariable(ENV_CYGWIN_HOME, null, true);
+ String envCygwinHomeValue = varCygwinHome != null ? varCygwinHome.getValue() : null;
+
+ // isCygwinLocationCached is used to figure fact of caching when all cached objects are null
+ if (isCygwinLocationCached && CDataUtil.objectsEqual(envPathValue, envPathValueCached) && CDataUtil.objectsEqual(envCygwinHomeValue, envCygwinHomeValueCached)) {
+ return cygwinLocation;
+ }
+
+ cygwinLocation = findCygwinRoot(envPathValue, envCygwinHomeValue);
+
+ envPathValueCached = envPathValue;
+ envCygwinHomeValueCached = envCygwinHomeValue;
+ isCygwinLocationCached = true;
+
+ return cygwinLocation;
+ }
+
+ /**
+ * Reads required value from registry. Looks in both
+ * HKEY_CURRENT_USER and HKEY_LOCAL_MACHINE
+ *
+ * @param key Registry key
+ * @param name Registry value to read
+ * @return corresponding string value or null if nothing found
+ */
+ private static String readValueFromRegistry(String key, String name) {
+ WindowsRegistry registry = WindowsRegistry.getRegistry();
+ if (registry != null) {
+ String s = registry.getCurrentUserValue(key, name);
+ if(s == null) {
+ s = registry.getLocalMachineValue(key, name);
+ }
+
+ if (s != null) {
+ return (s.replace(BACKSLASH, SLASH));
+ }
+ }
+ return null;
+ }
+
+ /**
+ * @return The absolute path to cygwin's root or null if not found
+ */
+ private static String findCygwinRoot(String envPathValue, String envCygwinHomeValue) {
+ String rootValue = null;
+
+ // Check $CYGWIN_HOME
+ if (envCygwinHomeValue != null && !envCygwinHomeValue.isEmpty()) {
+ IPath location = new Path(envCygwinHomeValue + "/bin/" + CYGWIN_DLL); //$NON-NLS-1$
+ if (location.toFile().exists()) {
+ // get rootValue from "rootValue\bin\cygwin1.dll"
+ rootValue = location.removeLastSegments(2).toOSString();
+ }
+ }
+
+ // Look in PATH values. Look for cygwin1.dll
+ if(rootValue == null) {
+ IPath location = PathUtil.findProgramLocation(CYGWIN_DLL, envPathValue);
+ if (location != null) {
+ // get rootValue from "rootValue\bin\cygwin1.dll"
+ rootValue = location.removeLastSegments(2).toOSString();
+ }
+ }
+
+ // Try to find the root dir in SOFTWARE\Cygwin\setup
+ if(rootValue == null) {
+ rootValue = readValueFromRegistry(REGISTRY_KEY_SETUP, "rootdir"); //$NON-NLS-1$
+ }
+
+ // Try to find the root dir in SOFTWARE\Wow6432Node\Cygwin\setup
+ if(rootValue == null) {
+ rootValue = readValueFromRegistry(REGISTRY_KEY_SETUP_WIN64, "rootdir"); //$NON-NLS-1$
+ }
+
+ // Try to find the root dir in SOFTWARE\Cygnus Solutions
+ if (rootValue == null) {
+ rootValue = readValueFromRegistry(REGISTRY_KEY_MOUNTS + ROOTPATTERN, PATH_NAME);
+ }
+
+ // Try the default Cygwin install dir
+ if(rootValue == null) {
+ File file = new File(DEFAULT_ROOT);
+ if (file.exists() && file.isDirectory())
+ rootValue = DEFAULT_ROOT;
+ }
+
+ if(rootValue != null) {
+ rootValue = rootValue.replace(BACKSLASH, SLASH);
+ }
+
+ return rootValue;
+ }
+
}
diff --git a/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/internal/core/LRUCache.java b/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/internal/core/LRUCache.java
new file mode 100644
index 00000000000..817613c6406
--- /dev/null
+++ b/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/internal/core/LRUCache.java
@@ -0,0 +1,50 @@
+/*******************************************************************************
+ * Copyright (c) 2013 Andrew Gvozdev and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Andrew Gvozdev - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.cdt.internal.core;
+
+import java.util.LinkedHashMap;
+import java.util.Map.Entry;
+
+/**
+ * A simple cache with limited number of items in the cache. LRUCache discards the Least Recently Used items first.
+ * Based on {@link LinkedHashMap}. Note that {@link LinkedHashMap} has built-in facility to support cache like that
+ * which is described in its JavaDoc.
+ */
+public class LRUCache<K, V> extends LinkedHashMap<K, V> {
+ private int fLimit;
+
+ /**
+ * Constructs an empty LRUCache with the specified limit on the number of items in the cache.
+ *
+ * @param limit - the maximum number of items to keep in the cache.
+ */
+ public LRUCache(int limit) {
+ super(limit, 0.75f, true);
+ fLimit= limit;
+ }
+
+ /**
+ * Constructs an empty LRUCache with the specified initial capacity and limit on the number of items in the cache.
+ *
+ * @param initialCapacity - initial capacity.
+ * @param limit - the maximum number of items to keep in the cache.
+ */
+ public LRUCache(int initialCapacity, int limit) {
+ super(initialCapacity, 0.75f, true);
+ fLimit= limit;
+ }
+
+ @Override
+ protected boolean removeEldestEntry(Entry<K, V> eldest) {
+ return size() >= fLimit;
+ }
+} \ No newline at end of file
diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/newui/AbstractPage.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/newui/AbstractPage.java
index 61270ae07d4..cf9f9f73299 100644
--- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/newui/AbstractPage.java
+++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/newui/AbstractPage.java
@@ -979,8 +979,11 @@ implements
}
protected void cfgChanged(ICConfigurationDescription _cfgd) {
-
CConfigurationStatus st = _cfgd.getConfigurationStatus();
+ if (st.getCode() == CConfigurationStatus.TOOLCHAIN_NOT_SUPPORTED) {
+ // Re-check, maybe user got the problem fixed
+ st = _cfgd.getConfigurationData().getStatus();
+ }
if (errPane != null && errMessage != null) {
if (st.isOK()) {
errPane.setVisible(false);

Back to the top