1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-04-29 19:45:01 +02:00

Cygwin Specs Detector using EFSExtensionProvider

This commit is contained in:
Andrew Gvozdev 2011-07-13 14:20:45 -04:00
parent cf55505f7b
commit 3bf0f468ad
9 changed files with 321 additions and 34 deletions

View file

@ -1026,17 +1026,13 @@ public class GCCBuildCommandParserTest extends TestCase {
// parse line
parser.startup(cfgDescription);
parser.processLine("gcc "
+ " -IC:\\path"
+ " -IX:\\path"
+ " file.cpp");
parser.shutdown();
// check populated entries
IPath path0 = new Path("C:\\path").setDevice(project.getLocation().getDevice());
{
List<ICLanguageSettingEntry> entries = parser.getSettingEntries(cfgDescription, file, languageId);
CIncludePathEntry expected = new CIncludePathEntry(path0, 0);
assertEquals(expected, entries.get(0));
}
List<ICLanguageSettingEntry> entries = parser.getSettingEntries(cfgDescription, file, languageId);
assertEquals(new CIncludePathEntry(new Path("X:\\path"), 0), entries.get(0));
}
/**

View file

@ -242,18 +242,24 @@ public abstract class AbstractLanguageSettingsOutputScanner extends LanguageSett
currentResource = findResource(parsedResourceName);
/**
* URI of directory where the build is happening. This URI could point to a remote filesystem
* for remote builds. Most often it is the same filesystem as for currentResource but
* it can be different filesystem (and different URI schema).
*/
URI buildDirURI = null;
/**
* Where source tree starts if mapped. This kind of mapping is useful for example in cases when
* the absolute path to the source file on the remote system is simulated inside a project in the
* workspace.
* This URI is rooted on the same filesystem where currentResource resides. In general this filesystem
* (or even URI schema) does not have to match that of buildDirURI.
*/
URI mappedRootURI = null;
URI buildDirURI = null;
if (isResolvingPaths) {
if (currentResource!=null) {
mappedRootURI = getMappedRootURI(currentResource, parsedResourceName);
}
mappedRootURI = getMappedRootURI(currentResource, parsedResourceName);
buildDirURI = getBuildDirURI(mappedRootURI);
}
@ -346,7 +352,7 @@ public abstract class AbstractLanguageSettingsOutputScanner extends LanguageSett
ICLanguageSettingEntry entry;
String resolvedPath = null;
URI uri = determineURI(parsedPath, baseURI);
URI uri = determineMappedURI(parsedPath, baseURI);
IResource rc = null;
if (uri != null && uri.isAbsolute()) {
rc = findResourceForLocationURI(uri, optionParser.kind, currentProject);
@ -417,7 +423,7 @@ public abstract class AbstractLanguageSettingsOutputScanner extends LanguageSett
return sourceFile;
}
private URI getBuildDirURI(URI mappedRootURI) {
protected URI getBuildDirURI(URI mappedRootURI) {
URI buildDirURI = null;
URI cwdURI = null;
@ -457,13 +463,13 @@ public abstract class AbstractLanguageSettingsOutputScanner extends LanguageSett
}
/**
* Determine URI appending to baseURI when possible.
* Determine URI on the local filesystem considering possible mapping.
*
* @param pathStr - path to the resource, can be absolute or relative
* @param baseURI - base {@link URI} where path to the resource is rooted
* @return {@link URI} of the resource
*/
private static URI determineURI(String pathStr, URI baseURI) {
private static URI determineMappedURI(String pathStr, URI baseURI) {
URI uri = null;
if (baseURI==null) {
@ -476,9 +482,15 @@ public abstract class AbstractLanguageSettingsOutputScanner extends LanguageSett
// careful not to use Path here but 'pathStr' as String as we want to properly navigate symlinks
uri = resolvePathFromBaseLocation(pathStr, baseLocation);
} else {
// use canonicalized path here, in particular replace all '\' with '/' for Windows paths
Path path = new Path(pathStr);
uri = EFSExtensionManager.getDefault().append(baseURI, path.toString());
// location on a remote filesystem
IPath path = new Path(pathStr); // use canonicalized path here, in particular replace all '\' with '/' for Windows paths
URI remoteUri = EFSExtensionManager.getDefault().append(baseURI, path.toString());
if (remoteUri!=null) {
String localPath = EFSExtensionManager.getDefault().getMappedPath(remoteUri);
if (localPath!=null) {
uri = org.eclipse.core.filesystem.URIUtil.toURI(localPath);
}
}
}
if (uri == null) {
@ -642,7 +654,11 @@ public abstract class AbstractLanguageSettingsOutputScanner extends LanguageSett
* @param parsedResourceName - path as appears in the output
* @return mapped path as URI
*/
private static URI getMappedRootURI(IResource sourceFile, String parsedResourceName) {
protected URI getMappedRootURI(IResource sourceFile, String parsedResourceName) {
if (currentResource==null) {
return null;
}
URI fileURI = sourceFile.getLocationURI();
String mappedRoot = "/"; //$NON-NLS-1$
@ -674,17 +690,19 @@ public abstract class AbstractLanguageSettingsOutputScanner extends LanguageSett
private static URI resolvePathFromBaseLocation(String name, IPath baseLocation) {
String pathName = name;
if (baseLocation != null && !baseLocation.isEmpty()) {
String device = new Path(pathName).getDevice();
if (device != null && device.length() > 0) {
pathName = pathName.substring(device.length());
}
pathName = pathName.replace(File.separatorChar, '/');
baseLocation = baseLocation.addTrailingSeparator();
if (pathName.startsWith("/")) { //$NON-NLS-1$
pathName = pathName.substring(1);
String device = new Path(pathName).getDevice();
if (device==null || device.equals(baseLocation.getDevice())) {
if (device != null && device.length() > 0) {
pathName = pathName.substring(device.length());
}
baseLocation = baseLocation.addTrailingSeparator();
if (pathName.startsWith("/")) { //$NON-NLS-1$
pathName = pathName.substring(1);
}
pathName = baseLocation.toString() + pathName;
}
pathName = baseLocation.toString() + pathName;
}
try {

View file

@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2009 Andrew Gvozdev and others.
* Copyright (c) 2010, 2011 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
@ -33,6 +33,7 @@ import org.eclipse.cdt.core.testplugin.ResourceHelper;
import org.eclipse.cdt.internal.core.XmlUtil;
import org.eclipse.cdt.managedbuilder.internal.scannerconfig.AbstractBuiltinSpecsDetector;
import org.eclipse.cdt.managedbuilder.internal.scannerconfig.GCCBuiltinSpecsDetector;
import org.eclipse.cdt.managedbuilder.internal.scannerconfig.GCCBuiltinSpecsDetectorCygwin;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
@ -280,7 +281,6 @@ public class GCCBuiltinSpecsDetectorTest extends TestCase {
String projectName = getName();
IProject project = ResourceHelper.createCDTProjectWithConfig(projectName);
ICConfigurationDescription[] cfgDescriptions = getConfigurationDescriptions(project);
ICConfigurationDescription cfgDescription = cfgDescriptions[0];
AbstractBuiltinSpecsDetector detector = new GCCBuiltinSpecsDetector() {
@ -684,5 +684,63 @@ public class GCCBuiltinSpecsDetectorTest extends TestCase {
assertEquals(expected, entries.get(0));
assertEquals(1, entries.size());
}
public void testGCCBuiltinSpecsDetector_Cygwin_NoProject() throws Exception {
String windowsLocation;
String cygwinLocation = "/usr/include";
try {
windowsLocation = ResourceHelper.cygwinToWindowsPath(cygwinLocation);
} catch (UnsupportedOperationException e) {
// Skip the test if Cygwin is not available.
return;
}
assertTrue("windowsLocation=["+windowsLocation+"]", new Path(windowsLocation).getDevice()!=null);
AbstractBuiltinSpecsDetector detector = new GCCBuiltinSpecsDetectorCygwin();
detector.startup(null);
detector.processLine("#include <...> search starts here:");
detector.processLine(" /usr/include");
detector.processLine("End of search list.");
detector.shutdown();
// check populated entries
List<ICLanguageSettingEntry> entries = detector.getSettingEntries(null, null, null);
assertEquals(new CIncludePathEntry(new Path(windowsLocation), ICSettingEntry.BUILTIN | ICSettingEntry.READONLY), entries.get(0));
assertEquals(1, entries.size());
}
public void testGCCBuiltinSpecsDetector_Cygwin_Configuration() throws Exception {
String windowsLocation;
String cygwinLocation = "/usr/include";
try {
windowsLocation = ResourceHelper.cygwinToWindowsPath(cygwinLocation);
} catch (UnsupportedOperationException e) {
// Skip the test if Cygwin is not available.
return;
}
assertTrue("windowsLocation=["+windowsLocation+"]", new Path(windowsLocation).getDevice()!=null);
// Create model project and folders to test
String projectName = getName();
IProject project = ResourceHelper.createCDTProjectWithConfig(projectName);
ICConfigurationDescription[] cfgDescriptions = getConfigurationDescriptions(project);
ICConfigurationDescription cfgDescription = cfgDescriptions[0];
AbstractBuiltinSpecsDetector detector = new GCCBuiltinSpecsDetectorCygwin();
detector.startup(cfgDescription);
detector.processLine("#include <...> search starts here:");
detector.processLine(" /usr/include");
detector.processLine("End of search list.");
detector.shutdown();
// check populated entries
List<ICLanguageSettingEntry> entries = detector.getSettingEntries(null, null, null);
assertEquals(new CIncludePathEntry(new Path(windowsLocation), ICSettingEntry.BUILTIN | ICSettingEntry.READONLY), entries.get(0));
assertEquals(1, entries.size());
}
}

View file

@ -609,7 +609,7 @@
<language-scope id="org.eclipse.cdt.core.g++"/>
</provider>
<provider
class="org.eclipse.cdt.managedbuilder.internal.scannerconfig.GCCBuiltinSpecsDetector"
class="org.eclipse.cdt.managedbuilder.internal.scannerconfig.GCCBuiltinSpecsDetectorCygwin"
id="org.eclipse.cdt.managedbuilder.core.cygwin.gcc.specs.detector"
name="CDT GCC Builtin Compiler Settings Cygwin"
parameter="sh -c &quot;${COMMAND} -E -P -v -dD ${INPUTS}&quot;">

View file

@ -13,6 +13,7 @@ package org.eclipse.cdt.managedbuilder.internal.scannerconfig;
import java.io.IOException;
import java.io.OutputStream;
import java.net.URI;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
@ -79,6 +80,9 @@ public abstract class AbstractBuiltinSpecsDetector extends AbstractLanguageSetti
protected java.io.File specFile = null;
protected boolean preserveSpecFile = false;
protected URI mappedRootURI = null;
protected URI buildDirURI = null;
/**
* TODO
*/
@ -151,6 +155,22 @@ public abstract class AbstractBuiltinSpecsDetector extends AbstractLanguageSetti
return currentLanguageId;
}
@Override
protected URI getMappedRootURI(IResource sourceFile, String parsedResourceName) {
if (mappedRootURI==null) {
mappedRootURI = super.getMappedRootURI(sourceFile, parsedResourceName);
}
return mappedRootURI;
}
@Override
protected URI getBuildDirURI(URI mappedRootURI) {
if (buildDirURI==null) {
buildDirURI = super.getBuildDirURI(mappedRootURI);
}
return buildDirURI;
}
@Override
public void startup(ICConfigurationDescription cfgDescription) throws CoreException {
// for workspace provider cfgDescription is used to figure out the current project for build console
@ -165,10 +185,16 @@ public abstract class AbstractBuiltinSpecsDetector extends AbstractLanguageSetti
specFile = null;
currentCommandResolved = resolveCommand(currentLanguageId);
mappedRootURI = null;
buildDirURI = null;
}
@Override
public void shutdown() {
buildDirURI = null;
mappedRootURI = null;
if (detectedSettingEntries!=null && detectedSettingEntries.size()>0) {
groupEntries(detectedSettingEntries);
setSettingEntries(currentCfgDescription, currentResource, currentLanguageId, detectedSettingEntries);

View file

@ -29,10 +29,10 @@ public class GCCBuiltinSpecsDetector extends AbstractBuiltinSpecsDetector implem
private static final String GCC_TOOLCHAIN_ID = "cdt.managedbuild.toolchain.gnu.base"; //$NON-NLS-1$
private enum State {NONE, EXPECTING_LOCAL_INCLUDE, EXPECTING_SYSTEM_INCLUDE, EXPECTING_FRAMEWORKS}
State state = State.NONE;
private State state = State.NONE;
@SuppressWarnings("nls")
static final AbstractOptionParser[] optionParsers = {
private static final AbstractOptionParser[] optionParsers = {
new IncludePathOptionParser("#include \"(\\S.*)\"", "$1", ICSettingEntry.BUILTIN | ICSettingEntry.READONLY | ICSettingEntry.LOCAL),
new IncludePathOptionParser("#include <(\\S.*)>", "$1", ICSettingEntry.BUILTIN | ICSettingEntry.READONLY),
new IncludePathOptionParser("#framework <(\\S.*)>", "$1", ICSettingEntry.BUILTIN | ICSettingEntry.READONLY | ICSettingEntry.FRAMEWORKS_MAC),

View file

@ -0,0 +1,81 @@
/*******************************************************************************
* Copyright (c) 2009, 2011 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.scannerconfig;
import java.net.URI;
import java.net.URISyntaxException;
import org.eclipse.cdt.core.settings.model.ICSettingEntry;
import org.eclipse.core.resources.IResource;
/**
* Class to detect built-in compiler settings.
* The paths are converted to cygwin "filesystem" representation. Then
*
*/
public class GCCBuiltinSpecsDetectorCygwin extends GCCBuiltinSpecsDetector {
private static final URI CYGWIN_ROOT;
static {
try {
CYGWIN_ROOT = new URI("cygwin:/"); //$NON-NLS-1$
} catch (URISyntaxException e) {
// hey we know this works
throw new IllegalStateException(e);
}
}
@SuppressWarnings("nls")
private static final AbstractOptionParser[] optionParsers = {
new IncludePathOptionParser("#include \"(\\S.*)\"", "$1", ICSettingEntry.BUILTIN | ICSettingEntry.READONLY | ICSettingEntry.LOCAL),
new IncludePathOptionParser("#include <(\\S.*)>", "$1", ICSettingEntry.BUILTIN | ICSettingEntry.READONLY),
new MacroOptionParser("#define (\\S*\\(.*?\\)) *(.*)", "$1", "$2", ICSettingEntry.BUILTIN | ICSettingEntry.READONLY),
new MacroOptionParser("#define (\\S*) *(.*)", "$1", "$2", ICSettingEntry.BUILTIN | ICSettingEntry.READONLY),
};
@Override
protected AbstractOptionParser[] getOptionParsers() {
return optionParsers;
}
@Override
protected URI getMappedRootURI(IResource sourceFile, String parsedResourceName) {
if (mappedRootURI==null) {
mappedRootURI = super.getMappedRootURI(sourceFile, parsedResourceName);
if (mappedRootURI==null) {
mappedRootURI = CYGWIN_ROOT;
}
}
return mappedRootURI;
}
@Override
protected URI getBuildDirURI(URI mappedRootURI) {
if (buildDirURI==null) {
buildDirURI = super.getBuildDirURI(mappedRootURI);
if (buildDirURI==null) {
buildDirURI = CYGWIN_ROOT;
}
}
return buildDirURI;
}
@Override
public GCCBuiltinSpecsDetectorCygwin cloneShallow() throws CloneNotSupportedException {
return (GCCBuiltinSpecsDetectorCygwin) super.cloneShallow();
}
@Override
public GCCBuiltinSpecsDetectorCygwin clone() throws CloneNotSupportedException {
return (GCCBuiltinSpecsDetectorCygwin) super.clone();
}
}

View file

@ -751,5 +751,12 @@
factoryClass="org.eclipse.cdt.internal.core.resources.ResourceExclusionFactory">
</exclusionFactory>
</extension>
<extension
point="org.eclipse.cdt.core.EFSExtensionProvider">
<EFSExtensionProvider
class="org.eclipse.cdt.internal.core.resources.CygwinEFSExtensionProvider"
scheme="cygwin">
</EFSExtensionProvider>
</extension>
</plugin>

View file

@ -0,0 +1,101 @@
/*******************************************************************************
* Copyright (c) 2011, 2011 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.resources;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.URI;
import org.eclipse.cdt.core.CCorePlugin;
import org.eclipse.cdt.core.EFSExtensionProvider;
import org.eclipse.core.runtime.Platform;
public class CygwinEFSExtensionProvider extends EFSExtensionProvider {
@Override
public String getMappedPath(URI locationURI) {
String cygwinPath = getPathFromURI(locationURI);
String windowsPath = null;
try {
windowsPath = cygwinToWindowsPath(cygwinPath);
} catch (Exception e) {
CCorePlugin.log(e);
}
return windowsPath;
}
/**
* Conversion from Windows path to Cygwin path.
*
* @param windowsPath - Windows path.
* @return Cygwin style converted path.
* @throws UnsupportedOperationException if Cygwin is unavailable.
* @throws IOException on IO problem.
*
* See ResourceHelper.windowsToCygwinPath(...)
*/
public static String windowsToCygwinPath(String windowsPath) throws IOException, UnsupportedOperationException {
if (!Platform.getOS().equals(Platform.OS_WIN32)) {
// Don't run this on non-windows platforms
throw new UnsupportedOperationException("Not a Windows system, Cygwin is unavailable.");
}
@SuppressWarnings("nls")
String[] args = {"cygpath", "-u", windowsPath};
Process cygpath;
try {
cygpath = Runtime.getRuntime().exec(args);
} catch (IOException ioe) {
throw new UnsupportedOperationException("Cygwin utility cygpath is not in the system search path.");
}
BufferedReader stdout = new BufferedReader(new InputStreamReader(cygpath.getInputStream()));
String cygwinPath = stdout.readLine();
if (cygwinPath == null) {
throw new UnsupportedOperationException("Cygwin utility cygpath is not available.");
}
return cygwinPath.trim();
}
/**
* Conversion from Cygwin path to Windows path.
*
* @param cygwinPath - Cygwin path.
* @return Windows style converted path.
* @throws UnsupportedOperationException if Cygwin is unavailable.
* @throws IOException on IO problem.
*
* * See ResourceHelper.cygwinToWindowsPath(...)
*/
public static String cygwinToWindowsPath(String cygwinPath) throws IOException, UnsupportedOperationException {
if (!Platform.getOS().equals(Platform.OS_WIN32)) {
// Don't run this on non-windows platforms
throw new UnsupportedOperationException("Not a Windows system, Cygwin is unavailable.");
}
@SuppressWarnings("nls")
String[] args = {"cygpath", "-w", cygwinPath};
Process cygpath;
try {
cygpath = Runtime.getRuntime().exec(args);
} catch (IOException ioe) {
throw new UnsupportedOperationException("Cygwin utility cygpath is not in the system search path.");
}
BufferedReader stdout = new BufferedReader(new InputStreamReader(cygpath.getInputStream()));
String windowsPath = stdout.readLine();
if (windowsPath == null) {
throw new UnsupportedOperationException("Cygwin utility cygpath is not available.");
}
return windowsPath.trim();
}
}