/******************************************************************************* * Copyright (c) 2004, 2015 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 * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM - Initial API and implementation * Anton Leherbauer (Wind River Systems) * Hans-Erik Floryd (hef-cdt@rt-labs.com) - http://bugs.eclipse.org/245692 *******************************************************************************/ package org.eclipse.cdt.make.internal.core.scannerconfig.util; import java.io.File; import java.io.IOException; import java.util.ArrayList; import java.util.Iterator; 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; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.Path; 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 { 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 = 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); 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, (ICConfigurationDescription) 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; } }