1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-04-23 22:52:11 +02:00

bug 357442: Added $CYGWIN_HOME to cygwin toolchain detection algorithm

This commit is contained in:
Andrew Gvozdev 2012-07-11 17:56:33 -04:00
parent b5807e9b29
commit d960fff7dd
8 changed files with 815 additions and 408 deletions

View file

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

View file

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

View file

@ -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));
}
return null;
}
/**
* Returns the absolute path of the pattern by
* simply appending the pattern to the root
*
* @param pattern The pattern to find
* @return The absolute path to the pattern or null if pattern is not found
*/
private static String getValueFromRoot(String pattern) {
if (rootCygwin != null) {
String path = rootCygwin + pattern;
File file = new File(path);
if (file.exists() && file.isDirectory())
return (path.replaceAll(BSLASH, SSLASH));
else
return null;
}
return null;
}
/**
* Returns the absolute path to cygwin's root
*
* @return The absolute path to cygwin's root or null if not found
*/
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;
}
if(rootValue != null)
rootValue = rootValue.replaceAll(BSLASH, SSLASH);
return rootValue;
}
/**
* Finds Cygwin's paths and sets corresponding properties.
*/
private static synchronized void findPaths() {
if (!isWindows()) {
return;
}
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;
}
private static String[] exec(String cmd, IConfiguration cfg) {
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;
if (registry != null) {
String value = registry.getCurrentUserValue(key, name);
if (value == null) {
value = registry.getLocalMachineValue(key, name);
}
Process proc = ProcessFactory.getFactory().exec(cmd.split(SP), env);
if (proc != null) {
if (value != null) {
return value.replace(BACKSLASH, SLASH);
}
}
return 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);
/**
* Returns the absolute path of the pattern by simply appending the relativePath to the root.
*
* @param relativePath - the pattern to find.
* @return The absolute path to the pattern or {@code null} if path does not exist.
*/
private static String getPathFromRoot(String relativePath) {
String rootCygwin = Cygwin.getCygwinHome();
if (rootCygwin != null) {
String path = rootCygwin + relativePath;
File file = new File(path);
if (file.exists() && file.isDirectory()) {
return path.replace(BACKSLASH, SLASH);
}
}
return null;
}
/**
* Resolve and return full path to program in context of configuration.
*
* @param program - program to resolve.
* @param cfg - configuration context.
* @return absolute path to program.
*/
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));
}
return program;
}
/**
* 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 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;
}
return envp;
}
/**
* 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 {
String[] envp = getEnvp(cfg);
Process proc = ProcessFactory.getFactory().exec(args, envp);
if (proc != null) {
InputStream ein = proc.getInputStream();
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)

View file

@ -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$
}
} else if (variableName.equalsIgnoreCase(LANG)) {
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());
}
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};
}
}

View file

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

View file

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

View file

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

View file

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