diff options
Diffstat (limited to 'org.rtems.cdt/src/org/rtems/cdt/Storage.java')
-rw-r--r-- | org.rtems.cdt/src/org/rtems/cdt/Storage.java | 347 |
1 files changed, 347 insertions, 0 deletions
diff --git a/org.rtems.cdt/src/org/rtems/cdt/Storage.java b/org.rtems.cdt/src/org/rtems/cdt/Storage.java new file mode 100644 index 0000000..2e0aee7 --- /dev/null +++ b/org.rtems.cdt/src/org/rtems/cdt/Storage.java @@ -0,0 +1,347 @@ +/* + * Copyright (c) 2008 Embedded Brains GmbH and others. + * + * Embedded Brains GmbH + * Obere Lagerstr. 30 + * D-82178 Puchheim + * Germany + * rtems@embedded-brains.de + * + * All rights reserved. This program and the accompanying materials are made + * available under the terms of the Eclipse Public License Version 1.0 ("EPL") + * which accompanies this distribution and is available at + * + * http://www.eclipse.org/legal/epl-v10.html + * + * For purposes of the EPL, "Program" will mean the Content. + * + * Contributors: + * + * Sebastian Huber (Embedded Brains GmbH) - Initial API and implementation. + */ + +package org.rtems.cdt; + +import java.io.BufferedReader; +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; + +import org.eclipse.cdt.build.core.scannerconfig.CfgInfoContext; +import org.eclipse.cdt.build.internal.core.scannerconfig.CfgDiscoveredPathManager; +import org.eclipse.cdt.core.model.CoreModel; +import org.eclipse.cdt.core.settings.model.ICConfigurationDescription; +import org.eclipse.cdt.core.settings.model.ICProjectDescription; +import org.eclipse.cdt.managedbuilder.core.IConfiguration; +import org.eclipse.cdt.managedbuilder.core.ManagedBuildManager; +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; +import org.eclipse.core.runtime.QualifiedName; + +public class Storage { + private static final String OPTION_SEPARATOR = "\0"; + + private static final String VALUE_START_TOKEN = "\t"; + + private static final int EXPECT_OPTION = 0; + + private static final int EXPECT_COMMAND = 1; + + private static final int EXPECT_KEY = 2; + + private static final int TOOL_COMPLETE = 3; + + public static String getPreference( String key) { + return Activator.getDefault().getPreferenceStore().getString( key); + } + + public static String getPristineProperty( IProject project, String key) { + String value = null; + + try { + value = project.getPersistentProperty( new QualifiedName( "", key)); + } catch (CoreException e) { + e.printStackTrace(); + } + + return value; + } + + public static String getProperty( IProject project, String key) { + String value = getPristineProperty( project, key); + + if (value == null) { + if (key.startsWith( Constants.TOOL_KEY_PREFIX)) { + changePlatform( project, Constants.PLATFORM_DEFAULT); + } else { + value = getPreference( key); + setProperty( project, key, value); + } + } + + return value; + } + + public static void setProperty( IProject project, String key, String value) { + try { + project.setPersistentProperty( new QualifiedName( "", key), value); + } catch (CoreException e) { + e.printStackTrace(); + } + } + + public static IConfiguration [] getConfigurations( IProject project) { + ICProjectDescription pd = CoreModel.getDefault().getProjectDescription( project); + + ICConfigurationDescription cds [] = pd.getConfigurations(); + IConfiguration cfgs [] = new IConfiguration [cds.length]; + for (int i = 0; i < cds.length; ++i) { + cfgs [i] = ManagedBuildManager.getConfigurationForDescription( cds [i]); + } + + return cfgs; + } + + public static IConfiguration getActiveConfiguration( IProject project) { + ICProjectDescription pd = CoreModel.getDefault().getProjectDescription( project); + + ICConfigurationDescription cd = pd.getActiveConfiguration(); + IConfiguration cfg = ManagedBuildManager.getConfigurationForDescription( cd); + + return cfg; + } + + public static String prependToPath( String path, String part) { + if (path == null || path.isEmpty()) { + return part; + } else { + return part + Constants.PATH_SEPARATOR + path; + } + } + + public static String prependToPathByPreference( String path, String key) { + String basePath = getPreference( key); + + if (basePath != null) { + IPath part = new Path( basePath).append( "bin"); + + return prependToPath( path, part.toOSString()); + } + + return path; + } + + public static String prependToPathByProperty( IProject project, String path, String key) { + String basePath = getProperty( project, key); + + if (basePath != null) { + IPath part = new Path( basePath).append( "bin"); + + return prependToPath( path, part.toOSString()); + } + + return path; + } + + public static void clearPlatform( IProject project) { + setProperty( project, Constants.PLATFORM_KEY, null); + + // Delete discovered paths for all configurations of the project + for (IConfiguration cfg : getConfigurations( project)) { + CfgDiscoveredPathManager.getInstance().removeDiscoveredInfo( + project, + new CfgInfoContext( cfg) + ); + } + } + + public static String getPlatform( IProject project) { + return getPristineProperty( project, Constants.PLATFORM_KEY); + } + + public static void changePlatform( IProject project, String newPlatform) { + String platform = getPlatform( project); + + // Check if we have already the requested platform + if (platform != null && platform == newPlatform) { + // Nothing to do + return; + } + + // Set new platform + setProperty( project, Constants.PLATFORM_KEY, newPlatform); + + // Update path prepends + String path = null; + if (Platform.getOS().equals( Platform.OS_WIN32)) { + if (newPlatform.equals( Constants.PLATFORM_CYGWIN)) { + path = prependToPathByPreference( path, Constants.CYGWIN_PATH_KEY); + } else { + path = prependToPathByPreference( path, Constants.MINGW_PATH_KEY); + path = prependToPathByPreference( path, Constants.MSYS_PATH_KEY); + } + } + path = prependToPathByProperty( project, path, Constants.BASE_PATH_KEY); + setProperty( project, Constants.PATH_PREPEND_KEY, path); + + // Update tools + updateTools( project, newPlatform); + } + + private static void updateTools( IProject project, String platform) { + String bspPath = getProperty( project, Constants.BSP_PATH_KEY); + IPath make = new Path( "make"); + + // Translate path if necessary + if (Platform.getOS().equals( Platform.OS_WIN32)) { + if (platform.equals( Constants.PLATFORM_CYGWIN)) { + String s [] = bspPath.split( ":"); + if (s.length > 0) { + bspPath = bspPath.replaceFirst( "^" + s [0] + ":", "/cygdrive/" + s [0]); + } + } + bspPath = bspPath.replaceAll( "\\\\", "/"); + } + + // Create make process builder + ProcessBuilder pb = new ProcessBuilder(); + + // Change working directory to the Makefile location + pb.directory( Activator.getDefault().getMakefileLocation().toFile()); + + // Update path environment variable + Map<String, String> env = pb.environment(); + String path = env.get( Constants.PATH_VARIABLE_NAME); + String part = getProperty( project, Constants.PATH_PREPEND_KEY); + path = Storage.prependToPath( path, part); + env.put( Constants.PATH_VARIABLE_NAME, path); + + // On windows we have to search for the make program in the new path environment + if (Platform.getOS().equals( Platform.OS_WIN32)) { + String parts [] = path.split( Constants.PATH_SEPARATOR); + for (String p : parts) { + IPath makeCandidate = new Path( p).append( "make.exe"); + File file = new File( makeCandidate.toOSString()); + if (file.exists()) { + make = makeCandidate; + break; + } + } + } + + // Set command line + pb.command( + make.toOSString(), + Constants.BSP_PATH_MAKE_VARIABLE + "=" + bspPath + ); + + // Start make process and parse its output + Process p = null; + try { + p = pb.start(); + InputStream is = p.getInputStream(); + BufferedReader br = new BufferedReader( new InputStreamReader( is)); + String line = br.readLine(); + String key = null; + String command = null; + List<String> options = new LinkedList<String>(); + int state = EXPECT_KEY; + while (line != null) { + switch (state) { + case EXPECT_OPTION: + if (line.startsWith( VALUE_START_TOKEN)) { + options.add( line.substring( 1)); + } else { + state = TOOL_COMPLETE; + continue; + } + break; + case EXPECT_COMMAND: + if (line.startsWith( VALUE_START_TOKEN)) { + command = line.substring( 1); + state = EXPECT_OPTION; + } else { + throw new IOException( "Unexpected line format"); + } + break; + case EXPECT_KEY: + if (line.length() > Constants.TOOL_KEY_PREFIX.length()) { + key = line; + state = EXPECT_COMMAND; + } else { + throw new IOException( "Unexpected line format"); + } + break; + case TOOL_COMPLETE: + updateTool( project, key, command, options); + options.clear(); + state = EXPECT_KEY; + continue; + default: + throw new IOException( "Unexpected state"); + } + line = br.readLine(); + } + if (state == EXPECT_OPTION) { + updateTool( project, key, command, options); + } + } catch (IOException e) { + e.printStackTrace(); + } finally { + while (true) { + try { + p.waitFor(); + break; + } catch (InterruptedException e) { + continue; + } + } + } + } + + private static void updateTool( IProject project, String toolKey, String command, List<String> options) { + List<String> filteredOptions = new LinkedList<String>(); + + // Filter options + if (toolKey.startsWith( Constants.COMPILER_KEY_PREFIX) || toolKey.startsWith( Constants.LINKER_KEY_PREFIX)) { + for (String option : options) { + if (!(option.isEmpty() || option.trim().matches( "^-c|-O[0123s]|-g|-W[\\w-]*$"))) { + filteredOptions.add( option); + } + } + } else { + filteredOptions = options; + } + + // Transform filtered option list into option string value + String optionsValue = new String(); + if (!options.isEmpty()) { + optionsValue = filteredOptions.get( 0); + filteredOptions.remove( 0); + } + for (String option : filteredOptions) { + optionsValue += OPTION_SEPARATOR + option; + } + + // Set properties + setProperty( project, toolKey, command); + setProperty( project, toolKey + Constants.TOOL_OPTIONS_KEY_POSTFIX, optionsValue); + } + + public static String [] getToolOptions( IProject project, String toolKey) { + String optionsValue = getProperty( project, toolKey + Constants.TOOL_OPTIONS_KEY_POSTFIX); + + return optionsValue.split( OPTION_SEPARATOR); + } + + private Storage() { + // Do nothing + } +} |