Skip to main content

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [List Home]
[cdt-patch] Scanner Interface for Managed and Standard Build Models


Hi All,
I will follow this up with a fairly detailed discussion about the changes I have made to the standard build model and why, but I want to submit this patch to unblock some of the indexing work that is about to start. The change logs contain an overview of what has been done to implement a new interface between a build model (any build model) and clients of the model that need to extract include search paths and defined symbols. For the most part, I have tried to leave the old build system as unchanged as possible. For example, project properties like the make search path, and whether or not to continue on build failures are still stored as persistent properties on the project through the CNature (ugh). The new information I have added is managed by a new build manager on a per-project basis and is associated with a project as a session property. The information is persisted in the 'cdtbuild' file introduced by the new managed build system.

I smoke-tested the changes on Windows and Solaris.

Next week I will be removing all associations between the managed and standard project natures, so you won't have both C/C++ Build and C/C++ Project property pages for managed projects.

Sean Evoy
Rational Software - IBM Software Group
Ottawa, Ontario, Canada

Attachment: NewBuildManager.zip
Description: Zip archive

Index: ChangeLog
===================================================================
RCS file: /home/tools/org.eclipse.cdt.ui/ChangeLog,v
retrieving revision 1.114
diff -u -r1.114 ChangeLog
--- ChangeLog	28 Jun 2003 19:56:52 -0000	1.114
+++ ChangeLog	3 Jul 2003 20:08:33 -0000
@@ -1,3 +1,9 @@
+2003-07-03 Sean Evoy
+	Changed property/wizard tab to use the new StandardBuildManager and 
+	the improved IStandardBuildInfo interface to set and retrieve 
+	the include and defined symbol information for a standard make project.
+	* src/org/eclipse/cdt/ui/wizards/BuildPathInfoBlock.java
+
 2003-06-27 Andrew Niefer
 	Changes for C/C++ Search:
 	Added:
Index: src/org/eclipse/cdt/ui/wizards/BuildPathInfoBlock.java
===================================================================
RCS file: /home/tools/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/wizards/BuildPathInfoBlock.java,v
retrieving revision 1.1
diff -u -r1.1 BuildPathInfoBlock.java
--- src/org/eclipse/cdt/ui/wizards/BuildPathInfoBlock.java	26 Jun 2003 17:43:36 -0000	1.1
+++ src/org/eclipse/cdt/ui/wizards/BuildPathInfoBlock.java	3 Jul 2003 20:08:34 -0000
@@ -1,9 +1,7 @@
 package org.eclipse.cdt.ui.wizards;
 
-import java.util.StringTokenizer;
-
-import org.eclipse.cdt.core.CProjectNature;
-import org.eclipse.cdt.core.resources.IBuildInfo;
+import org.eclipse.cdt.core.build.standard.StandardBuildManager;
+import org.eclipse.cdt.core.resources.IStandardBuildInfo;
 import org.eclipse.cdt.internal.ui.util.SWTUtil;
 import org.eclipse.cdt.ui.CUIPlugin;
 import org.eclipse.cdt.utils.ui.controls.ControlFactory;
@@ -263,23 +261,19 @@
 	 * @see org.eclipse.cdt.ui.wizards.IWizardTab#doRun(org.eclipse.core.resources.IProject, org.eclipse.core.runtime.IProgressMonitor)
 	 */
 	public void doRun(IProject project, IProgressMonitor monitor) {
-		try {
-			if (monitor == null) {
-				monitor = new NullProgressMonitor();
-			}
-			// Store the paths and symbols as comma-separated lists in the project's nature
-			CProjectNature nature = (CProjectNature) project.getNature(CProjectNature.C_NATURE_ID);
+		if (monitor == null) {
+			monitor = new NullProgressMonitor();
+		}
+		if (project != null) {
+			// Store the paths and symbols 
 			monitor.beginTask("Setting Include Paths", 1);
-			String paths = getPathListContents();
-			nature.setIncludePaths(paths, monitor);
+			StandardBuildManager.setIncludePaths(project, getPathListContents());
+
 			monitor.beginTask("Setting Defined Symbols", 1);
-			String symbols = getSymbolListContents();
-			nature.setDefinedSymbols(symbols, monitor);
-			
-		}				
-		catch (CoreException e) {
+			StandardBuildManager.setPreprocessorSymbols(project, getSymbolListContents());
+		
+			StandardBuildManager.saveBuildInfo(project);
 		}
-
 	}
 
 	/*
@@ -418,33 +412,15 @@
 	/**
 	 * @return
 	 */
-	private String getPathListContents() {
-		// Convert the contents of the path list into a comma-separated list
-		StringBuffer buffer = new StringBuffer();
-		if (pathList != null) {
-			String[] paths = pathList.getItems();
-			for (int i = 0; i < paths.length; i++) {
-				String string = paths[i];
-				buffer.append(string + IBuildInfo.SEPARATOR);
-			} 
-		}
-		return buffer.toString();
+	private String[] getPathListContents() {
+		return pathList.getItems();
 	}
 
 	/**
 	 * @return
 	 */
-	private String getSymbolListContents() {
-		// Convert the contents of the symbol list into a comma-separated list
-		StringBuffer buffer = new StringBuffer();
-		if (symbolList != null) {
-			String[] symbols = symbolList.getItems();
-			for (int i = 0; i < symbols.length; i++) {
-				String symbol = symbols[i];
-				buffer.append(symbol + IBuildInfo.SEPARATOR);
-			} 
-		}
-		return buffer.toString();
+	private String[] getSymbolListContents() {
+		return symbolList.getItems();
 	}
 
 	/**
@@ -613,35 +589,15 @@
 
 	private void setPathListContents() {
 		if (project != null) {
-			try {
-				CProjectNature nature = (CProjectNature)project.getNature(CProjectNature.C_NATURE_ID);
-				if (nature != null) {
-					String paths = nature.getIncludePaths();
-					StringTokenizer tokens = new StringTokenizer(paths, IBuildInfo.SEPARATOR);
-					while (tokens.hasMoreTokens()) {
-						pathList.add(tokens.nextToken());
-					}
-				}
-			} catch (CoreException e) {
-				// Just have an empty list
-			}
+			IStandardBuildInfo info = StandardBuildManager.getBuildInfo(project);
+			pathList.setItems(info.getIncludePaths());
 		}
 	}
 	
 	private void setSymbolListContents() {
 		if (project != null) {
-			try {
-				CProjectNature nature = (CProjectNature)project.getNature(CProjectNature.C_NATURE_ID);
-				if (nature != null) {
-					String symbols = nature.getDefinedSymbols();
-					StringTokenizer tokens = new StringTokenizer(symbols, IBuildInfo.SEPARATOR);
-					while (tokens.hasMoreTokens()) {
-						symbolList.add(tokens.nextToken());
-					}
-				}
-			} catch (CoreException e) {
-				// Just have an empty list
-			}
+			IStandardBuildInfo info = StandardBuildManager.getBuildInfo(project);
+			symbolList.setItems(info.getPreprocessorSymbols());
 		}
 	}
 
Index: ChangeLog
===================================================================
RCS file: /home/tools/org.eclipse.cdt.core.tests/ChangeLog,v
retrieving revision 1.12
diff -u -r1.12 ChangeLog
--- ChangeLog	3 Jul 2003 18:44:40 -0000	1.12
+++ ChangeLog	3 Jul 2003 20:51:09 -0000
@@ -1,3 +1,13 @@
+2003-07-03 Sean Evoy
+	New test suite that exercises the standard make build system including the new
+	IScannerInfoListener and IScannerInfoProvider interfaces.
+
+	Changes to the existing managed build test suite include tests of the new
+	IScannerInfoxxx interface discovery, subscription, and change notification methods. 
+	
+	* build/org/eclipse/cdt/core/build/managed/tests/StandardBuildTests.java
+	* build/org/eclipse/cdt/core/build/managed/tests/AllBuildTests.java
+
 2003-07-02 Victor Mozgin
 	Added DOMTests::testBug39501().
 	Improved filtering of expected failures/inconclusives in TortureTest.
Index: build/org/eclipse/cdt/core/build/managed/tests/AllBuildTests.java
===================================================================
RCS file: /home/tools/org.eclipse.cdt.core.tests/build/org/eclipse/cdt/core/build/managed/tests/AllBuildTests.java,v
retrieving revision 1.2
diff -u -r1.2 AllBuildTests.java
--- build/org/eclipse/cdt/core/build/managed/tests/AllBuildTests.java	23 Jun 2003 14:36:28 -0000	1.2
+++ build/org/eclipse/cdt/core/build/managed/tests/AllBuildTests.java	3 Jul 2003 20:51:09 -0000
@@ -12,36 +12,40 @@
 
 import java.util.Arrays;
 import java.util.List;
+import java.util.Map;
 
 import junit.framework.Test;
 import junit.framework.TestCase;
 import junit.framework.TestSuite;
 
+import org.eclipse.cdt.core.CCorePlugin;
 import org.eclipse.cdt.core.build.managed.BuildException;
 import org.eclipse.cdt.core.build.managed.IConfiguration;
-import org.eclipse.cdt.core.build.managed.IManagedBuildPathInfo;
 import org.eclipse.cdt.core.build.managed.IOption;
 import org.eclipse.cdt.core.build.managed.IOptionCategory;
-import org.eclipse.cdt.core.build.managed.IResourceBuildInfo;
+import org.eclipse.cdt.core.build.managed.IManagedBuildInfo;
 import org.eclipse.cdt.core.build.managed.ITarget;
 import org.eclipse.cdt.core.build.managed.ITool;
 import org.eclipse.cdt.core.build.managed.ManagedBuildManager;
+import org.eclipse.cdt.core.parser.IScannerInfo;
+import org.eclipse.cdt.core.parser.IScannerInfoChangeListener;
+import org.eclipse.cdt.core.parser.IScannerInfoProvider;
 import org.eclipse.cdt.internal.core.build.managed.ToolReference;
 import org.eclipse.core.resources.IProject;
 import org.eclipse.core.resources.IResource;
 import org.eclipse.core.resources.IWorkspaceRoot;
 import org.eclipse.core.resources.ResourcesPlugin;
 import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IConfigurationElement;
+import org.eclipse.core.runtime.IExtension;
+import org.eclipse.core.runtime.IExtensionPoint;
 
-/**
- * 
- */
 public class AllBuildTests extends TestCase {
 	private static final boolean boolVal = true;
 	private static final String testConfigName = "test.config.override";
 	private static final String enumVal = "Another Enum";
 	private static final String[] listVal = {"_DEBUG", "/usr/include", "libglade.a"};
-	private static final String projectName = "BuildTest";
+	private static final String projectName = "ManagedBuildTest";
 	private static final String rootExt = "toor";
 	private static final String stringVal = "-c -Wall";
 	private static final String subExt = "bus";
@@ -57,7 +61,7 @@
 		suite.addTest(new AllBuildTests("testProject"));
 		suite.addTest(new AllBuildTests("testConfigurations"));
 		suite.addTest(new AllBuildTests("testTargetArtifacts"));
-		suite.addTest(new AllBuildTests("testBuildPathInfoInterface"));
+		suite.addTest(new AllBuildTests("testScannerInfoInterface"));
 		suite.addTest(new AllBuildTests("cleanup"));
 		
 		return suite;
@@ -98,7 +102,7 @@
 	 *  
 	 * @throws CoreException
 	 */
-	public void testBuildPathInfoInterface(){
+	public void testScannerInfoInterface(){
 		// Open the test project
 		IProject project = null;
 		try {
@@ -126,25 +130,55 @@
 		// Change the default configuration to the sub config
 		IConfiguration[] configs = newTarget.getConfigurations();
 		assertEquals(3, configs.length);
-		IResourceBuildInfo buildInfo = ManagedBuildManager.getBuildInfo(project);
+		IManagedBuildInfo buildInfo = ManagedBuildManager.getBuildInfo(project);
 		buildInfo.setDefaultConfiguration(newTarget.getConfiguration("sub.config.2"));
-		// Get the path information for the project
-		IManagedBuildPathInfo info = ManagedBuildManager.getBuildPathInfo(project);
-		assertNotNull(info);
-		
-		// Test the interface for include paths. It is important that the build model
-		// return the contents of all options flagged as containing include paths
-		String[] expectedPaths = {"/usr/include", "/opt/gnome/include", "/home/tester/include"};
-		String[] actualPaths = info.getIncludePaths();
-		assertTrue(Arrays.equals(expectedPaths, actualPaths));
-		
-		// Test the interface for defined symbols (there are none but it should not return null)
-		String[] definedSymbols = info.getDefinedSymbols();
-		assertNotNull(definedSymbols);
-		assertEquals(0, definedSymbols.length);
 
+		// Use the plugin mechanism to discover the supplier of the path information
+		IExtensionPoint extensionPoint = CCorePlugin.getDefault().getDescriptor().getExtensionPoint("ScannerInfoProvider");
+		if (extensionPoint == null) {
+			fail("Failed to retrieve the extension point ScannerInfoProvider.");
+		}
+		IExtension[] extensions = extensionPoint.getExtensions();
+		IScannerInfoProvider provider = null;
+		// Find the first IScannerInfoProvider that supplies build info for the project
+		for (int i = 0; i < extensions.length && provider == null; i++) {
+			IExtension extension = extensions[i];
+			IConfigurationElement[] elements = extension.getConfigurationElements();
+			for (int j = 0; j < elements.length; ++j) {
+				IConfigurationElement element = elements[j];
+				if (element.getName().equals("provider")) { 
+					// Check if it handles the info for the project
+					try {
+						IScannerInfoProvider temp = (IScannerInfoProvider)element.createExecutableExtension("class");
+						if (temp.managesResource(project)) {
+							provider = temp;
+							break;
+						}
+					} catch (CoreException e) {
+						fail("Failed retrieving scanner info provider from plugin: " + e.getLocalizedMessage());
+					}
+				}
+			}
+		}
+		assertNotNull(provider);
+		provider.subscribe(project, new IScannerInfoChangeListener () {
+			public void changeNotification(IResource project, IScannerInfo info) {
+				// Test the symbols 
+				Map definedSymbols = info.getDefinedSymbols();
+				assertTrue(definedSymbols.containsKey("DEBUG"));
+				assertTrue(definedSymbols.containsKey("GNOME"));
+				assertTrue(definedSymbols.containsValue("ME"));
+				assertEquals((String)definedSymbols.get("DEBUG"), "");
+				assertEquals((String)definedSymbols.get("GNOME"), "ME");
+				// Test the includes path
+				String[] expectedPaths = {"/usr/include", "/opt/gnome/include", "/home/tester/include"};
+				String[] actualPaths = info.getIncludePaths();
+				assertTrue(Arrays.equals(expectedPaths, actualPaths));
+			}
+		});
+		
 		// Add some defined symbols programmatically
-		String[] expectedSymbols = {"DEBUG", "GNOME"};
+		String[] expectedSymbols = {"DEBUG", "GNOME = ME "};
 		IConfiguration defaultConfig = buildInfo.getDefaultConfiguration(newTarget);
 		ITool[] tools = defaultConfig.getTools();
 		ITool subTool = null;
@@ -167,10 +201,6 @@
 		}
 		assertNotNull(symbolOpt);
 		ManagedBuildManager.setOption(defaultConfig, symbolOpt, expectedSymbols);
-		
-		// Retest
-		definedSymbols = info.getDefinedSymbols();
-		assertTrue(Arrays.equals(expectedSymbols, definedSymbols));
 	}
 	
 	/**
@@ -302,7 +332,7 @@
 		}
 		
 		// Test that the default config was remembered
-		IResourceBuildInfo info = ManagedBuildManager.getBuildInfo(project);
+		IManagedBuildInfo info = ManagedBuildManager.getBuildInfo(project);
 		assertEquals(defaultConfig.getId(), info.getDefaultConfiguration(target).getId());
 
 		// Get the targets
@@ -324,7 +354,7 @@
 	 * 
 	 * @param project
 	 */
-	private void checkBuildTestSettings(IResourceBuildInfo info) {
+	private void checkBuildTestSettings(IManagedBuildInfo info) {
 		String ext1 = "foo";
 		String ext2 = "bar";
 		String badExt = "cpp";
@@ -332,7 +362,7 @@
 		String expectedCmd = "doIt";
 		
 		assertNotNull(info);
-		assertEquals(info.getBuildArtifactName(), "BuildTest.toor");
+		assertEquals(info.getBuildArtifactName(), projectName + "." + rootExt);
 		
 		// There should be a default configuration defined for the project
 		ITarget buildTarget = info.getDefaultTarget();
Index: build/org/eclipse/cdt/core/build/managed/tests/StandardBuildTests.java
===================================================================
RCS file: build/org/eclipse/cdt/core/build/managed/tests/StandardBuildTests.java
diff -N build/org/eclipse/cdt/core/build/managed/tests/StandardBuildTests.java
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ build/org/eclipse/cdt/core/build/managed/tests/StandardBuildTests.java	3 Jul 2003 20:51:09 -0000
@@ -0,0 +1,374 @@
+package org.eclipse.cdt.core.build.managed.tests;
+
+import java.util.Arrays;
+import java.util.Map;
+
+import junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+
+import org.eclipse.cdt.core.CCProjectNature;
+import org.eclipse.cdt.core.CCorePlugin;
+import org.eclipse.cdt.core.CProjectNature;
+import org.eclipse.cdt.core.build.standard.StandardBuildManager;
+import org.eclipse.cdt.core.parser.IScannerInfo;
+import org.eclipse.cdt.core.parser.IScannerInfoChangeListener;
+import org.eclipse.cdt.core.parser.IScannerInfoProvider;
+import org.eclipse.cdt.core.resources.IStandardBuildInfo;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.IWorkspaceRoot;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IConfigurationElement;
+import org.eclipse.core.runtime.IExtension;
+import org.eclipse.core.runtime.IExtensionPoint;
+import org.eclipse.core.runtime.NullProgressMonitor;
+
+/**********************************************************************
+ * Copyright (c) 2002,2003 Rational Software Corporation and others.
+ * All rights reserved.   This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ * 
+ * Contributors: 
+ * IBM Rational Software - Initial API and implementation
+***********************************************************************/
+
+public class StandardBuildTests extends TestCase {
+	private static final String DEFAULT_MAKE_CMD = "make";
+	private static final String EMPTY_STRING = "";
+	private static final boolean OFF = false;
+	private static final boolean ON = true;
+	private static final String OVR_BUILD_ARGS = "all";
+	private static final String OVR_BUILD_LOCATION = "/home/tester/bin/nmake";
+	private static final String[] OVR_INC_PATHS = {"/test", "C:\\windows", "//dev/home/include"};
+	private static final String[] OVR_PREPROC_SYMS = {"_RELEASE", "NO ", " YES=1"};
+	private static final String PROJECT_NAME = "StandardBuildTest";
+
+	private class ScannerListener implements IScannerInfoChangeListener {
+		private final String[] expectedPaths = {"/usr/include", "/home/tester/include", "/opt/gnome/include"};
+		private final String[] expectedSymbols = {"_DEBUG", "TRUE=1", "FALSE ", ""};
+
+		public void changeNotification(IResource project, IScannerInfo info) {
+			// Are there any symbols
+			Map definedSymbols = info.getDefinedSymbols();
+			if (!definedSymbols.isEmpty()) {
+				assertTrue(definedSymbols.containsKey(expectedSymbols[0]));
+				assertEquals(EMPTY_STRING, (String)definedSymbols.get(expectedSymbols[0]));
+				assertTrue(definedSymbols.containsKey("TRUE"));
+				assertEquals("1", (String)definedSymbols.get("TRUE"));
+				assertFalse(definedSymbols.containsKey(expectedSymbols[2]));
+				assertTrue(definedSymbols.containsKey(expectedSymbols[2].trim()));
+				assertEquals(EMPTY_STRING, (String)definedSymbols.get(expectedSymbols[2].trim()));
+				// We should have discarded the empty string
+				assertFalse(definedSymbols.containsKey(""));
+			}
+			
+			// What paths have been set
+			String[] paths = info.getIncludePaths();
+			if (paths.length > 0) {
+				assertTrue(Arrays.equals(expectedPaths, paths));
+			}
+		}
+		/**
+		 * @return
+		 */
+		public String[] getExpectedPaths() {
+			return expectedPaths;
+		}
+
+		/**
+		 * @return
+		 */
+		public String[] getExpectedSymbols() {
+			return expectedSymbols;
+		}
+
+	}
+	/**
+	 * @param name
+	 */
+	public StandardBuildTests(String name) {
+		super(name);
+	}
+
+	public static Test suite() {
+		TestSuite suite = new TestSuite(StandardBuildTests.class.getName());
+		
+		// Add the relevant tests to the suite
+		suite.addTest(new StandardBuildTests("testProjectCreation"));
+		suite.addTest(new StandardBuildTests("testProjectSettings"));
+		suite.addTest(new StandardBuildTests("testProjectConversion"));
+		suite.addTest(new StandardBuildTests("testScannerListenerInterface"));
+		suite.addTest(new StandardBuildTests("testProjectCleanup"));
+		
+		return suite;
+	}
+	
+	private void checkDefaultProjectSettings(IProject project) {
+		assertNotNull(project);
+
+		// There should not be any include path or defined symbols for the project
+		IStandardBuildInfo info = StandardBuildManager.getBuildInfo(project);
+		assertNotNull(info);
+		String[] includePaths = info.getIncludePaths();
+		assertNotNull(includePaths);
+		assertEquals(0, includePaths.length);
+		String[] definedSymbols = info.getPreprocessorSymbols();
+		assertNotNull(definedSymbols);
+		assertEquals(0, definedSymbols.length);
+		
+		// Check the rest of the project information
+		assertEquals(ON, info.isDefaultBuildCmd());
+		assertEquals(OFF,info.isStopOnError());
+		assertEquals(DEFAULT_MAKE_CMD, info.getBuildLocation());
+		assertEquals(EMPTY_STRING, info.getFullBuildArguments());
+		assertEquals(EMPTY_STRING, info.getIncrementalBuildArguments()); 
+	}
+	
+	private void checkOverriddenProjectSettings(IProject project) {
+		assertNotNull(project);
+
+		// Check that the new stuff is there
+		IStandardBuildInfo info = StandardBuildManager.getBuildInfo(project);
+		assertNotNull(info);
+		String[] includePaths = info.getIncludePaths();
+		assertNotNull(includePaths);
+		assertEquals(3, includePaths.length);
+		assertTrue(Arrays.equals(includePaths, OVR_INC_PATHS));
+		String[] definedSymbols = info.getPreprocessorSymbols();
+		assertNotNull(definedSymbols);
+		assertEquals(3, definedSymbols.length);
+		assertTrue(Arrays.equals(definedSymbols, OVR_PREPROC_SYMS));
+		
+		// Check the rest of the project information
+		assertEquals(OFF, info.isDefaultBuildCmd());
+		assertEquals(ON, info.isStopOnError());
+		assertEquals(OVR_BUILD_LOCATION, info.getBuildLocation());
+		assertEquals(OVR_BUILD_ARGS, info.getFullBuildArguments());
+		assertEquals(EMPTY_STRING, info.getIncrementalBuildArguments()); 
+	}
+
+	/**
+	 * Create a new project named <code>name</code> or return the project in 
+	 * the workspace of the same name if it exists.
+	 * 
+	 * @param name The name of the project to create or retrieve.
+	 * @return 
+	 * @throws CoreException
+	 */
+	private IProject createProject(String name) throws CoreException {
+		IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot();
+		IProject project = root.getProject(name);
+		if (!project.exists()) {
+			project.create(null);
+		} else {
+			project.refreshLocal(IResource.DEPTH_INFINITE, null);
+		}
+        
+		if (!project.isOpen()) {
+			project.open(null);
+		}
+
+		return project;	
+	}
+
+	private IScannerInfoProvider findInfoProvider(IProject project) { 
+		// Use the plugin mechanism to discover the supplier of the path information
+		IExtensionPoint extensionPoint = CCorePlugin.getDefault().getDescriptor().getExtensionPoint("ScannerInfoProvider");
+		if (extensionPoint == null) {
+			fail("StandardBuildTest testScannerListernerInterface failed to retrieve the extension point ScannerInfoProvider.");
+		}
+		IExtension[] extensions = extensionPoint.getExtensions();
+		IScannerInfoProvider provider = null;
+
+		// Find the first IScannerInfoProvider that supplies build info for the project
+		for (int i = 0; i < extensions.length && provider == null; i++) {
+			IExtension extension = extensions[i];
+			IConfigurationElement[] elements = extension.getConfigurationElements();
+			for (int j = 0; j < elements.length; ++j) {
+				IConfigurationElement element = elements[j];
+				if (element.getName().equals("provider")) { 
+					// Check if it handles the info for the project
+					try {
+						IScannerInfoProvider temp = (IScannerInfoProvider)element.createExecutableExtension("class");
+						if (temp.managesResource(project)) {
+							provider = temp;
+							break;
+						}
+					} catch (CoreException e) {
+						fail("Failed retrieving scanner info provider from plugin: " + e.getLocalizedMessage());
+					}
+				}
+			}
+		}
+		return provider;
+	}
+	
+	/**
+	 * Remove the <code>IProject</code> with the name specified in the argument from the 
+	 * receiver's workspace.
+	 *  
+	 * @param name
+	 */
+	private void removeProject(String name) {
+		IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot();
+		IProject project = root.getProject(name);
+		if (project.exists()) {
+			try {
+				project.delete(true, false, null);
+			} catch (CoreException e) {
+				assertTrue(false);
+			}
+		}
+	}
+
+	/**
+	 * Remove all the project information associated with the project used during test.
+	 */
+	public void testProjectCleanup() {
+		removeProject(PROJECT_NAME);
+	}
+
+	public void testProjectConversion() {
+		// Open the project
+		IProject project = null;
+		try {
+			project = createProject(PROJECT_NAME);
+		} catch (CoreException e) {
+			fail("StandardBuildTest testProjectConversion failed opening project: " + e.getLocalizedMessage());
+		}
+		assertNotNull(project);
+		
+		// Check the settings (they should be the override values)
+		checkOverriddenProjectSettings(project);
+		
+		// Now convert the project
+		try {
+			CCorePlugin.getDefault().convertProjectFromCtoCC(project, new NullProgressMonitor());
+		} catch (CoreException e) {
+			fail("StandardBuildTest testProjectConversion failed to convert project: " + e.getLocalizedMessage());
+		}
+
+		// Save, Close, and Reopen the project
+		StandardBuildManager.saveBuildInfo(project);
+		try {
+			project.close(new NullProgressMonitor());
+		} catch (CoreException e) {
+			fail("StandardBuildTest testProjectConversion failed to close project " + e.getLocalizedMessage());
+		}
+		StandardBuildManager.removeBuildInfo(project);
+		try {
+			project.open(new NullProgressMonitor());
+		} catch (CoreException e) {
+			fail ("StandardBuildTest testProjectConversion failed to open project " + e.getLocalizedMessage());
+		}
+
+		// Make sure it has a CCNature
+		try {
+			project.hasNature(CCProjectNature.CC_NATURE_ID);
+		} catch (CoreException e) {
+			fail("StandardBuildTest testProjectConversion failed getting nature: " + e.getLocalizedMessage());
+		}
+		
+		// Nothing should have changed in the settings
+		checkOverriddenProjectSettings(project);
+	}
+
+	/**
+	 * 
+	 */
+	public void testProjectCreation () {
+		// Create a new project
+		IProject project = null;
+		try {
+			project = createProject(PROJECT_NAME); 
+			// Convert the new project to a standard make project
+			CCorePlugin.getDefault().convertProjectToCC(project, new NullProgressMonitor(), CCorePlugin.PLUGIN_ID + ".make");
+		} catch (CoreException e) {
+			fail("StandardBuildTest testProjectCreation failed creating project: " + e.getLocalizedMessage());
+		}
+		assertNotNull(project);
+
+		// Make sure it has a CNature
+		try {
+			project.hasNature(CProjectNature.C_NATURE_ID);
+		} catch (CoreException e) {
+			fail("StandardBuildTest testProjectCreation failed getting nature: " + e.getLocalizedMessage());
+		}
+		
+		// Check the default settings
+		checkDefaultProjectSettings(project);
+	}
+	
+	public void testProjectSettings() {
+		// Get the project
+		IProject project = null;
+		try {
+			project = createProject(PROJECT_NAME);
+		} catch (CoreException e) {
+			fail("StandardBuildTest testProjectSettings failed opening project: " + e.getLocalizedMessage());
+		}
+		assertNotNull(project);
+		
+		// Change the settings
+		StandardBuildManager.setIncludePaths(project, OVR_INC_PATHS);
+		StandardBuildManager.setPreprocessorSymbols(project, OVR_PREPROC_SYMS);
+		
+		// Use the build info for the rest of the settings
+		IStandardBuildInfo info = StandardBuildManager.getBuildInfo(project);
+		info.setStopOnError(ON);
+		info.setUseDefaultBuildCmd(OFF);
+		info.setBuildLocation(OVR_BUILD_LOCATION);
+		info.setFullBuildArguments(OVR_BUILD_ARGS);
+		
+		// Save, Close, and Reopen the project
+		StandardBuildManager.saveBuildInfo(project);
+		try {
+			project.close(new NullProgressMonitor());
+		} catch (CoreException e) {
+			fail("StandardBuildTest testProjectSettings failed to close project " + e.getLocalizedMessage());
+		}
+		StandardBuildManager.removeBuildInfo(project);
+		try {
+			project.open(new NullProgressMonitor());
+		} catch (CoreException e) {
+			fail ("StandardBuildTest testProjectSettings failed to open project " + e.getLocalizedMessage());
+		}
+		
+		// Retest
+		checkOverriddenProjectSettings(project);
+	}
+
+	public void testScannerListenerInterface() {
+		// Get the project
+		IProject project = null;
+		try {
+			project = createProject(PROJECT_NAME);
+		} catch (CoreException e) {
+			fail("StandardBuildTest testScannerListernerInterface failed opening project: " + e.getLocalizedMessage());
+		}
+		assertNotNull(project);
+
+		// Find the scanner info provider for this project
+		IScannerInfoProvider provider = findInfoProvider(project);
+		assertNotNull(provider);
+		
+		// Remove what's there
+		StandardBuildManager.setIncludePaths(project, new String[0]);
+		StandardBuildManager.setPreprocessorSymbols(project, new String[0]);
+
+		// Subscribe
+		ScannerListener listener = new ScannerListener();
+		provider.subscribe(project, listener);
+		
+		// Change the settings
+		StandardBuildManager.setIncludePaths(project, listener.getExpectedPaths());
+		StandardBuildManager.setPreprocessorSymbols(project, listener.getExpectedSymbols());
+		
+		// Unsubscribe
+		provider.unsubscribe(project, listener);
+	}
+}
Index: ChangeLog
===================================================================
RCS file: /home/tools/org.eclipse.cdt.core/ChangeLog,v
retrieving revision 1.107
diff -u -r1.107 ChangeLog
--- ChangeLog	27 Jun 2003 14:31:27 -0000	1.107
+++ ChangeLog	3 Jul 2003 20:48:34 -0000
@@ -1,3 +1,57 @@
+2003-07-03 Sean Evoy
+	New schema and extension point for registering an interface
+	between the build system (managed and standard) and the scanner 
+	clients that need it (like the indexer).
+	* plugin.xml
+	* schema/ScannerInfoProvider.exsd
+	
+	Added some documentation to the schema for managed build information
+	* schema/ManagedBuildTools.exsd
+	
+	Added three new interfaces for getting build information for the scanner. 
+	IScannerInfo contains the actual information the scanner needs and is passed
+	to the scanner by the build model. IScannerInfoChangeListener is the interface
+	that must be implemented by the scanner client that uses the IScannerInfo. 
+	IScannerInfoProvider is the interface implemented by the build model. It is
+	registered through an extension point so clients can discover providers at
+	run time. IScannerInfoListener implementors subscribe and unsubscribe with the 
+	provider and the provider passes them the IScannerInfo when it changes.
+	* parser/org/eclipse/cdt/core/parser/IScannerInfo.java
+	* parser/org/eclipse/cdt/core/parser/IScannerInfoChangeListener.java
+	* parser/org/eclipse/cdt/core/parser/IScannerInfoProvider.java
+	
+	Changed the name of some of the managed build system elements.
+	* build/org/eclipse/cdt/core/build/managed/IManagedBuildInfo.java
+	
+	This resulted in superficial changes to the Target and ManagedBuildManager
+	* build/org/eclipse/cdt/internal/core/build/managed/Target.java
+
+	Implemented the new scanner interfaces in the managed system
+	* build/org/eclipse/cdt/internal/core/build/managed/ManagedBuildInfo.java
+	* build/org/eclipse/cdt/core/build/managed/ManagedBuildManager.java
+	
+	Added a new manager for the standard make system that implements the new
+	scanner interfaces. This manager uses the .cdtbuild file to persist 
+	include path and symbol information (in otherwords, real build information).
+	Like the managed build manager, it also gives clients access to the build 
+	information associated with a project. It does not effect the older preferences
+	which are still managed by the CNature.
+	* build/org/eclipse/cdt/core/build/standard/StandardBuildManager.java
+	
+	Removed the responsibiolity for includes paths and symbols from CNature 
+	added in last patch.
+	* src/org/eclipse/cdt/core/CProjectNature.java
+	
+	Added code for persisting the standard build information for includes paths and 
+	symbols in a file, and implemented the IScannerInfo interface in the BuildInfoFactory.
+	Did not rename it, although ...
+	* src/org/eclipse/cdt/core/BuildInfoFactory.java
+	
+	I did rename the interface it implements since it was the only reference
+	* src/org/eclipse/cdt/core/resources/IStandardBuildInfo.java
+	
+	
+	
 2003-06-26 Sean Evoy
 	Added methods to add and extract include paths and preprocessor 
 	symbols from standard make C and C++ projects.
Index: plugin.xml
===================================================================
RCS file: /home/tools/org.eclipse.cdt.core/plugin.xml,v
retrieving revision 1.24
diff -u -r1.24 plugin.xml
--- plugin.xml	28 Jun 2003 19:48:12 -0000	1.24
+++ plugin.xml	3 Jul 2003 20:48:34 -0000
@@ -33,6 +33,7 @@
    <extension-point id="CBuildVariable" name="C/C++ Build Variable" schema="schema/CBuildVariable.exsd"/>
    <extension-point id="CToolType" name="C/C++ Tool Type" schema="schema/CToolType.exsd"/>
    <extension-point id="ManagedBuildInfo" name="Managed Build Tools" schema="schema/ManagedBuildTools.exsd"/>
+   <extension-point id="ScannerInfoProvider" name="Scanner Information Provider" schema="schema/ScannerInfoProvider.exsd"/>
 
    <extension
          point="org.eclipse.cdt.core.CToolType">
@@ -278,6 +279,19 @@
             enabled="true"
             pattern="*.exe">
       </ignore>
+   </extension>
+   <extension
+         id="org.eclipse.cdt.core.ScannerInfoProvider"
+         name="Scanner Information Provider"
+         point="org.eclipse.cdt.core.ScannerInfoProvider">
+      <provider
+            class="org.eclipse.cdt.core.build.managed.ManagedBuildManager"
+            id="org.eclipse.cdt.core.provider.managed">
+      </provider>
+      <provider
+      		class="org.eclipse.cdt.core.build.standard.StandardBuildManager"
+            id="org.eclipse.cdt.core.provider.standard">
+      </provider>
    </extension>
 
     <extension id="task" name="%CTaskName" point="org.eclipse.core.resources.markers">
Index: build/org/eclipse/cdt/core/build/managed/IManagedBuildInfo.java
===================================================================
RCS file: build/org/eclipse/cdt/core/build/managed/IManagedBuildInfo.java
diff -N build/org/eclipse/cdt/core/build/managed/IManagedBuildInfo.java
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ build/org/eclipse/cdt/core/build/managed/IManagedBuildInfo.java	3 Jul 2003 20:48:34 -0000
@@ -0,0 +1,124 @@
+package org.eclipse.cdt.core.build.managed;
+
+import java.util.List;
+
+/**********************************************************************
+ * Copyright (c) 2002,2003 Rational Software Corporation and others.
+ * All rights reserved.   This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ * 
+ * Contributors: 
+ * IBM Rational Software - Initial API and implementation
+***********************************************************************/
+
+public interface IManagedBuildInfo {
+
+	/**
+	 * Add a new target to the build information for the receiver
+	 * 
+	 * @param target
+	 */
+	public void addTarget(ITarget target);
+		
+	/**
+	 * Returns the name of the artifact to build for the receiver.
+	 * 
+	 * @return
+	 */
+	public String getBuildArtifactName();
+
+	/**
+	 * Get the default configuration associated with the receiver
+	 * 
+	 * @return
+	 */
+	public IConfiguration getDefaultConfiguration(ITarget target);
+	
+	
+	/**
+	 * Returns the default target in the receiver.
+	 * 
+	 * @return
+	 */
+	public ITarget getDefaultTarget();
+	
+	/**
+	 * Answers the extension that will be built by the current configuration
+	 * for the extension passed in the argument or <code>null</code>.
+	 * 
+	 * @param resourceName
+	 * @return
+	 */
+	public String getOutputExtension(String resourceExtension);
+	
+	/**
+	 * Get the target specified in the argument.
+	 * 
+	 * @param id
+	 * @return
+	 */
+	public ITarget getTarget(String id);
+	
+	/**
+	 * Get all of the targets associated with the receiver.
+	 * 
+	 * @return
+	 */
+	public List getTargets();
+	
+	/**
+	 * Returns a <code>String</code> containing the flags, including 
+	 * those overridden by the user, for the tool that handles the 
+	 * type of source file defined by the argument.
+	 * 
+	 * @param extension
+	 * @return
+	 */
+	public String getFlagsForSource(String extension);
+
+	/**
+	 * Returns a <code>String</code> containing the flags, including 
+	 * those overridden by the user, for the tool that handles the 
+	 * type of target defined by the argument.
+	 * 
+	 * @param extension
+	 * @return
+	 */
+	public String getFlagsForTarget(String extension);
+
+	/**
+	 * Returns a <code>String</code> containing the command-line invocation 
+	 * for the tool associated with the source extension.
+	 * 
+	 * @param extension
+	 * @return
+	 */
+	public String getToolForSource(String extension);
+
+	/**
+	 * Returns a <code>String</code> containing the command-line invocation 
+	 * for the tool associated with the target extension.
+	 * 
+	 * @param extension
+	 * @return
+	 */
+	public String getToolForTarget(String extension);
+	
+	/**
+	 * Set the primary configuration for the receiver.
+	 * 
+	 * @param configuration The <code>IConfiguration</code> that will be used as the default
+	 * for all building.
+	 */
+	public void setDefaultConfiguration(IConfiguration configuration);
+	
+	/**
+	 * Set the primary target for the receiver.
+	 * 
+	 * @param target
+	 */
+	public void setDefaultTarget(ITarget target);
+	
+}
Index: build/org/eclipse/cdt/core/build/managed/IManagedBuildPathInfo.java
===================================================================
RCS file: build/org/eclipse/cdt/core/build/managed/IManagedBuildPathInfo.java
diff -N build/org/eclipse/cdt/core/build/managed/IManagedBuildPathInfo.java
--- build/org/eclipse/cdt/core/build/managed/IManagedBuildPathInfo.java	23 Jun 2003 14:36:31 -0000	1.1
+++ /dev/null	1 Jan 1970 00:00:00 -0000
@@ -1,32 +0,0 @@
-package org.eclipse.cdt.core.build.managed;
-
-/**********************************************************************
- * Copyright (c) 2002,2003 Rational Software Corporation and others.
- * All rights reserved.   This program and the accompanying materials
- * are made available under the terms of the Common Public License v0.5
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/cpl-v05.html
- * 
- * Contributors: 
- * IBM Rational Software - Initial API and implementation
-***********************************************************************/
-
-public interface IManagedBuildPathInfo {
-	/**
-	 * Answers a <code>String</code> array containing all the defined  
-	 * preprocessor symbols. If there are no defined symbols, the receiver 
-	 * will return an empty array, never <code>null</code>
-	 * 
-	 * @return
-	 */
-	public String[] getDefinedSymbols();
-
-	/**
-	 * Answers a <code>String</code> array containing all the known include 
-	 * search paths. If there are no paths defined, the receiver will 
-	 * return an empty array, never <code>null</code>
-	 * 
-	 * @return
-	 */
-	public String[] getIncludePaths();
-}
Index: build/org/eclipse/cdt/core/build/managed/IResourceBuildInfo.java
===================================================================
RCS file: build/org/eclipse/cdt/core/build/managed/IResourceBuildInfo.java
diff -N build/org/eclipse/cdt/core/build/managed/IResourceBuildInfo.java
--- build/org/eclipse/cdt/core/build/managed/IResourceBuildInfo.java	9 Jun 2003 19:22:15 -0000	1.1
+++ /dev/null	1 Jan 1970 00:00:00 -0000
@@ -1,124 +0,0 @@
-package org.eclipse.cdt.core.build.managed;
-
-import java.util.List;
-
-/**********************************************************************
- * Copyright (c) 2002,2003 Rational Software Corporation and others.
- * All rights reserved.   This program and the accompanying materials
- * are made available under the terms of the Common Public License v0.5
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/cpl-v05.html
- * 
- * Contributors: 
- * IBM Rational Software - Initial API and implementation
-***********************************************************************/
-
-public interface IResourceBuildInfo {
-
-	/**
-	 * Add a new target to the build information for the receiver
-	 * 
-	 * @param target
-	 */
-	public void addTarget(ITarget target);
-		
-	/**
-	 * Returns the name of the artifact to build for the receiver.
-	 * 
-	 * @return
-	 */
-	public String getBuildArtifactName();
-
-	/**
-	 * Get the default configuration associated with the receiver
-	 * 
-	 * @return
-	 */
-	public IConfiguration getDefaultConfiguration(ITarget target);
-	
-	
-	/**
-	 * Returns the default target in the receiver.
-	 * 
-	 * @return
-	 */
-	public ITarget getDefaultTarget();
-	
-	/**
-	 * Answers the extension that will be built by the current configuration
-	 * for the extension passed in the argument or <code>null</code>.
-	 * 
-	 * @param resourceName
-	 * @return
-	 */
-	public String getOutputExtension(String resourceExtension);
-	
-	/**
-	 * Get the target specified in the argument.
-	 * 
-	 * @param id
-	 * @return
-	 */
-	public ITarget getTarget(String id);
-	
-	/**
-	 * Get all of the targets associated with the receiver.
-	 * 
-	 * @return
-	 */
-	public List getTargets();
-	
-	/**
-	 * Returns a <code>String</code> containing the flags, including 
-	 * those overridden by the user, for the tool that handles the 
-	 * type of source file defined by the argument.
-	 * 
-	 * @param extension
-	 * @return
-	 */
-	public String getFlagsForSource(String extension);
-
-	/**
-	 * Returns a <code>String</code> containing the flags, including 
-	 * those overridden by the user, for the tool that handles the 
-	 * type of target defined by the argument.
-	 * 
-	 * @param extension
-	 * @return
-	 */
-	public String getFlagsForTarget(String extension);
-
-	/**
-	 * Returns a <code>String</code> containing the command-line invocation 
-	 * for the tool associated with the source extension.
-	 * 
-	 * @param extension
-	 * @return
-	 */
-	public String getToolForSource(String extension);
-
-	/**
-	 * Returns a <code>String</code> containing the command-line invocation 
-	 * for the tool associated with the target extension.
-	 * 
-	 * @param extension
-	 * @return
-	 */
-	public String getToolForTarget(String extension);
-	
-	/**
-	 * Set the primary configuration for the receiver.
-	 * 
-	 * @param configuration The <code>IConfiguration</code> that will be used as the default
-	 * for all building.
-	 */
-	public void setDefaultConfiguration(IConfiguration configuration);
-	
-	/**
-	 * Set the primary target for the receiver.
-	 * 
-	 * @param target
-	 */
-	public void setDefaultTarget(ITarget target);
-	
-}
Index: build/org/eclipse/cdt/core/build/managed/ManagedBuildManager.java
===================================================================
RCS file: /home/tools/org.eclipse.cdt.core/build/org/eclipse/cdt/core/build/managed/ManagedBuildManager.java,v
retrieving revision 1.9
diff -u -r1.9 ManagedBuildManager.java
--- build/org/eclipse/cdt/core/build/managed/ManagedBuildManager.java	23 Jun 2003 14:36:31 -0000	1.9
+++ build/org/eclipse/cdt/core/build/managed/ManagedBuildManager.java	3 Jul 2003 20:48:35 -0000
@@ -17,6 +17,7 @@
 import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.List;
+import java.util.ListIterator;
 import java.util.Map;
 
 import javax.xml.parsers.DocumentBuilder;
@@ -28,7 +29,8 @@
 import org.apache.xml.serialize.Serializer;
 import org.apache.xml.serialize.SerializerFactory;
 import org.eclipse.cdt.core.CCorePlugin;
-import org.eclipse.cdt.internal.core.build.managed.ResourceBuildInfo;
+import org.eclipse.cdt.core.parser.*;
+import org.eclipse.cdt.internal.core.build.managed.ManagedBuildInfo;
 import org.eclipse.cdt.internal.core.build.managed.Target;
 import org.eclipse.core.resources.IFile;
 import org.eclipse.core.resources.IProject;
@@ -46,11 +48,12 @@
  * This is the main entry point for getting at the build information
  * for the managed build system. 
  */
-public class ManagedBuildManager {
+public class ManagedBuildManager implements IScannerInfoProvider {
 
 	private static final QualifiedName buildInfoProperty
-		= new QualifiedName(CCorePlugin.PLUGIN_ID, "buildInfo");
-
+		= new QualifiedName(CCorePlugin.PLUGIN_ID, "managedBuildInfo");
+	private static final String ROOT_ELEM_NAME = "ManagedProjectBuildInfo";
+	private static final String FILE_NAME = ".cdtbuild";
 	private static final ITarget[] emptyTargets = new ITarget[0];
 
 	// Targets defined by extensions (i.e., not associated with a resource)
@@ -58,6 +61,9 @@
 	private static List extensionTargets;
 	private static Map extensionTargetMap;
 
+	// Listeners interested in build model changes
+	private static Map buildModelListeners; 
+
 	/**
 	 * Returns the list of targets that are defined by this project,
 	 * projects referenced by this project, and by the extensions. 
@@ -108,7 +114,7 @@
 	 * @return
 	 */
 	public static ITarget[] getTargets(IResource resource) {
-		IResourceBuildInfo buildInfo = getBuildInfo(resource);
+		IManagedBuildInfo buildInfo = getBuildInfo(resource);
 		
 		if (buildInfo != null) {
 			List targets = buildInfo.getTargets();
@@ -131,7 +137,7 @@
 		ITarget target = null;
 		// Check if the target is spec'd in the build info for the resource
 		if (resource != null) {
-			IResourceBuildInfo buildInfo = getBuildInfo(resource);
+			IManagedBuildInfo buildInfo = getBuildInfo(resource);
 			if (buildInfo != null)
 				target = buildInfo.getTarget(id);
 		}
@@ -187,13 +193,35 @@
 			return;
 		}
 		// Set the default in build information for the project 
-		IResourceBuildInfo info = getBuildInfo(project);
+		IManagedBuildInfo info = getBuildInfo(project);
 		if (info != null) {
 			info.setDefaultConfiguration(newDefault);
 		}
 	}
 	
 	/**
+	 * @param config
+	 * @param option
+	 */
+	private static void setDirty(IConfiguration config, IOption option) {
+		// Don't bother unless this is something that effect the 
+		if (!(option.getValueType() == IOption.INCLUDE_PATH 
+			|| option.getValueType() == IOption.PREPROCESSOR_SYMBOLS)) {
+			return;
+		}
+		// Figure out if there is a listener for this change
+		IResource resource = config.getOwner();
+		List listeners = (List) getBuildModelListeners().get(resource);
+		if (listeners == null) {
+			return;
+		}
+		ListIterator iter = listeners.listIterator();
+		while (iter.hasNext()) {
+			((IScannerInfoChangeListener)iter.next()).changeNotification(resource, getScannerInfo(resource));
+		}
+	}
+
+	/**
 	 * Set the string value for an option for a given config.
 	 * 
 	 * @param config The configuration the option belongs to.
@@ -203,6 +231,7 @@
 	public static void setOption(IConfiguration config, IOption option, boolean value) {
 		try {
 			config.setOption(option, value);
+			setDirty(config, option);
 		} catch (BuildException e) {
 			return;
 		}
@@ -218,6 +247,7 @@
 	public static void setOption(IConfiguration config, IOption option, String value) {
 		try {
 			config.setOption(option, value);
+			setDirty(config, option);
 		} catch (BuildException e) {
 			return;
 		}
@@ -233,6 +263,7 @@
 	public static void setOption(IConfiguration config, IOption option, String[] value) {
 		try {
 			config.setOption(option, value);
+			setDirty(config, option);
 		} catch (BuildException e) {
 			return;
 		}
@@ -247,11 +278,11 @@
 	public static void saveBuildInfo(IProject project) {
 		// Create document
 		Document doc = new DocumentImpl();
-		Element rootElement = doc.createElement("buildInfo");
+		Element rootElement = doc.createElement(ROOT_ELEM_NAME);
 		doc.appendChild(rootElement);
 
 		// Save the build info
-		ResourceBuildInfo buildInfo = (ResourceBuildInfo) getBuildInfo(project);
+		ManagedBuildInfo buildInfo = (ManagedBuildInfo) getBuildInfo(project);
 		if (buildInfo != null)
 			buildInfo.serialize(doc, rootElement);
 		
@@ -266,7 +297,7 @@
 				= SerializerFactory.getSerializerFactory(Method.XML).makeSerializer(new OutputStreamWriter(s, "UTF8"), format);
 			serializer.asDOMSerializer().serialize(doc);
 			xml = s.toString("UTF8"); //$NON-NLS-1$		
-			IFile rscFile = project.getFile(".cdtbuild");
+			IFile rscFile = project.getFile(FILE_NAME);
 			InputStream inputStream = new ByteArrayInputStream(xml.getBytes());
 			// update the resource content
 			if (rscFile.exists()) {
@@ -316,9 +347,9 @@
 		}
 	}
 
-	private static ResourceBuildInfo loadBuildInfo(IProject project) {
-		ResourceBuildInfo buildInfo = null;
-		IFile file = project.getFile(".cdtbuild");
+	private static ManagedBuildInfo loadBuildInfo(IProject project) {
+		ManagedBuildInfo buildInfo = null;
+		IFile file = project.getFile(FILE_NAME);
 		if (!file.exists())
 			return null;
 	
@@ -327,8 +358,8 @@
 			DocumentBuilder parser = DocumentBuilderFactory.newInstance().newDocumentBuilder();
 			Document document = parser.parse(stream);
 			Node rootElement = document.getFirstChild();
-			if (rootElement.getNodeName().equals("buildInfo")) {
-				buildInfo = new ResourceBuildInfo(project, (Element)rootElement);
+			if (rootElement.getNodeName().equals(ROOT_ELEM_NAME)) {
+				buildInfo = new ManagedBuildInfo(project, (Element)rootElement);
 				project.setSessionProperty(buildInfoProperty, buildInfo);
 			}
 		} catch (Exception e) {
@@ -338,13 +369,14 @@
 		return buildInfo;
 	}
 
-	private static ResourceBuildInfo findBuildInfo(IResource resource, boolean create) {
+	private static ManagedBuildInfo findBuildInfo(IResource resource, boolean create) {
 		// Make sure the extension information is loaded first
 		loadExtensions();
-		ResourceBuildInfo buildInfo = null;
+		ManagedBuildInfo buildInfo = null;
 		try {
-			buildInfo = (ResourceBuildInfo)resource.getSessionProperty(buildInfoProperty);
+			buildInfo = (ManagedBuildInfo)resource.getSessionProperty(buildInfoProperty);
 		} catch (CoreException e) {
+			return buildInfo;
 		}
 		
 		if (buildInfo == null && resource instanceof IProject) {
@@ -353,7 +385,7 @@
 		
 		if (buildInfo == null && create) {
 			try {
-				buildInfo = new ResourceBuildInfo();
+				buildInfo = new ManagedBuildInfo();
 				resource.setSessionProperty(buildInfoProperty, buildInfo);
 			} catch (CoreException e) {
 				buildInfo = null;
@@ -363,12 +395,22 @@
 		return buildInfo;
 	}
 	
-	public static IResourceBuildInfo getBuildInfo(IResource resource, boolean create) {
-		return (IResourceBuildInfo) findBuildInfo(resource, create);
+	public static IManagedBuildInfo getBuildInfo(IResource resource, boolean create) {
+		return (IManagedBuildInfo) findBuildInfo(resource, create);
+	}
+
+	public static IManagedBuildInfo getBuildInfo(IResource resource) {
+		return (IManagedBuildInfo) findBuildInfo(resource, false);
 	}
 
-	public static IResourceBuildInfo getBuildInfo(IResource resource) {
-		return (IResourceBuildInfo) findBuildInfo(resource, false);
+	/*
+	 * @return
+	 */
+	private static Map getBuildModelListeners() {
+		if (buildModelListeners == null) {
+			buildModelListeners = new HashMap();
+		}
+		return buildModelListeners;
 	}
 
 	/**
@@ -378,8 +420,88 @@
 	 * @param resource
 	 * @return
 	 */
-	public static IManagedBuildPathInfo getBuildPathInfo(IResource resource) {
-		return (IManagedBuildPathInfo) getBuildInfo(resource, false);
+	private static IScannerInfo getScannerInfo(IResource resource) {
+		return (IScannerInfo) getBuildInfo(resource, false);
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.cdt.core.parser.IScannerInfoProvider#subscribe(org.eclipse.cdt.core.parser.IScannerInfoChangeListener)
+	 */
+	public synchronized void subscribe(IResource resource, IScannerInfoChangeListener listener) {
+		IResource project = null;
+		if (resource instanceof IProject) {
+			project = resource;
+		} else if (resource instanceof IFile) {
+			project = ((IFile)resource).getProject();
+		} else {
+			return;
+		}
+		// Get listeners for this resource
+		Map map = getBuildModelListeners();
+		List list = (List) map.get(project);
+		if (list == null) {
+			// Create a new list
+			list = new ArrayList();
+		}
+		if (!list.contains(listener)) {
+			// Add the new listener for the resource
+			list.add(listener);
+			map.put(project, list);
+		}
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.cdt.core.parser.IScannerInfoProvider#managesResource(org.eclipse.core.resources.IResource)
+	 */
+	public boolean managesResource(IResource resource) {
+		// The managed build manager manages build information for the 
+		// resource IFF it it is a project and has a build file with the proper
+		// root element
+		IProject project = null;
+		if (resource instanceof IProject){
+			project = (IProject)resource;
+		} else if (resource instanceof IFile) {
+			project = ((IFile)resource).getProject();
+		} else {
+			return false;
+		}
+		IFile file = project.getFile(FILE_NAME);
+		if (file.exists()) {
+			try {
+				InputStream stream = file.getContents();
+				DocumentBuilder parser = DocumentBuilderFactory.newInstance().newDocumentBuilder();
+				Document document = parser.parse(stream);
+				Node rootElement = document.getFirstChild();
+				if (rootElement.getNodeName().equals(ROOT_ELEM_NAME)) {
+					return true;
+				} 
+			} catch (Exception e) {
+				return false;
+			}
+		}
+		return false;
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.cdt.core.parser.IScannerInfoProvider#unsubscribe(org.eclipse.cdt.core.parser.IScannerInfoChangeListener)
+	 */
+	public synchronized void unsubscribe(IResource resource, IScannerInfoChangeListener listener) {
+		IResource project = null;
+		if (resource instanceof IProject) {
+			project = resource;
+		} else if (resource instanceof IFile) {
+			project = ((IFile)resource).getProject();
+		} else {
+			return;
+		}
+		// Remove the listener
+		Map map = getBuildModelListeners();
+		List list = (List) map.get(project);
+		if (list != null && !list.isEmpty()) {
+			// The list is not empty so try to remove listener
+			list.remove(listener);
+			map.put(project, list);
+		}
 	}
 
 }
Index: build/org/eclipse/cdt/internal/core/build/managed/ManagedBuildInfo.java
===================================================================
RCS file: build/org/eclipse/cdt/internal/core/build/managed/ManagedBuildInfo.java
diff -N build/org/eclipse/cdt/internal/core/build/managed/ManagedBuildInfo.java
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ build/org/eclipse/cdt/internal/core/build/managed/ManagedBuildInfo.java	3 Jul 2003 20:48:35 -0000
@@ -0,0 +1,349 @@
+package org.eclipse.cdt.internal.core.build.managed;
+
+/**********************************************************************
+ * Copyright (c) 2002,2003 Rational Software Corporation and others.
+ * All rights reserved.   This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ * 
+ * Contributors: 
+ * IBM Rational Software - Initial API and implementation
+ * **********************************************************************/
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.ListIterator;
+import java.util.Map;
+
+import org.eclipse.cdt.core.build.managed.BuildException;
+import org.eclipse.cdt.core.build.managed.IConfiguration;
+import org.eclipse.cdt.core.build.managed.IOption;
+import org.eclipse.cdt.core.build.managed.IManagedBuildInfo;
+import org.eclipse.cdt.core.build.managed.ITarget;
+import org.eclipse.cdt.core.build.managed.ITool;
+import org.eclipse.cdt.core.parser.IScannerInfo;
+import org.eclipse.core.resources.IResource;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+
+public class ManagedBuildInfo implements IManagedBuildInfo, IScannerInfo {
+
+	private IResource owner;
+	private Map targetMap;
+	private List targets;
+	private Map defaultConfigurations;
+	private ITarget defaultTarget;
+	
+	public ManagedBuildInfo() {
+		targetMap = new HashMap();
+		targets = new ArrayList();
+		defaultConfigurations = new HashMap();
+	}
+	
+	public ManagedBuildInfo(IResource owner, Element element) {
+		this();
+		// The id of the default configuration
+		String defaultTargetId = null;
+		List configIds = new ArrayList();
+		Node child = element.getFirstChild();
+		while (child != null) {
+			if (child.getNodeName().equals("target")) {
+				new Target(this, (Element)child);
+			} else if (child.getNodeName().equals("defaultConfig")) {
+				// We may not have read the config in yet, so just cache it
+				configIds.add(((Element)child).getAttribute("id"));
+			} else if (child.getNodeName().equals("defaultTarget")) {
+				defaultTargetId = ((Element)child).getAttribute("id");
+			}
+			child = child.getNextSibling();
+		}
+		// All the available targets have been read in
+		defaultTarget = (ITarget) targetMap.get(defaultTargetId);
+		// Now we have a misserable O(N^2) operation (oh well, the data sets are small)
+		ListIterator stringIter = configIds.listIterator();
+		while (stringIter.hasNext()){
+			String confId = (String) stringIter.next();
+			ListIterator targIter = targets.listIterator();
+			while (targIter.hasNext()) {
+				Target targ = (Target) targIter.next();
+				IConfiguration conf = targ.getConfiguration(confId);
+				if (conf != null) {
+					defaultConfigurations.put(targ.getId(), conf);
+					break;
+				}				
+			}
+		}
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.cdt.core.build.managed.IResourceBuildInfo#addTarget(org.eclipse.cdt.core.build.managed.ITarget)
+	 */
+	public void addTarget(ITarget target) {
+		targetMap.put(target.getId(), target);
+		targets.add(target);
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.cdt.core.build.managed.IResourceBuildInfo#getBuildArtifactName()
+	 */
+	public String getBuildArtifactName() {
+		// Get the default target and use its value
+		String name = getDefaultTarget().getArtifactName();
+		return name == null ? new String() : name;
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.cdt.core.build.managed.IResourceBuildInfo#getDefaultConfiguration()
+	 */
+	public IConfiguration getDefaultConfiguration(ITarget target) {
+		// Get the default config associated with the defalt target
+		IConfiguration config = (IConfiguration) defaultConfigurations.get(target.getId());
+
+		// If null, look up the first configuration associated with the target
+		if (config == null) {
+			IConfiguration[] configs = getDefaultTarget().getConfigurations();
+			if (configs.length > 0) {
+				config = configs[0];
+			}
+		}
+		return config;
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.cdt.core.build.managed.IResourceBuildInfo#getDefaultTarget()
+	 */
+	public ITarget getDefaultTarget() {
+		if (defaultTarget == null) {
+			defaultTarget = (ITarget) targets.get(0);
+		}
+		return defaultTarget;
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.cdt.core.build.managed.IResourceBuildInfo#getFlagsForSource(java.lang.String)
+	 */
+	public String getFlagsForSource(String extension) {
+		// Get all the tools for the current config
+		IConfiguration config = getDefaultConfiguration(getDefaultTarget());
+		ITool[] tools = config.getTools();
+		for (int index = 0; index < tools.length; index++) {
+			ITool tool = tools[index];
+			if (tool.buildsFileType(extension)) {
+				String flags = new String();
+				try {
+					flags = tool.getToolFlags();
+				} catch (BuildException e) {
+					// Give it your best shot with the next tool
+					continue;
+				}
+				return flags;
+			}
+		}
+		return null;
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.cdt.core.build.managed.IResourceBuildInfo#getToolFlags(java.lang.String)
+	 */
+	public String getFlagsForTarget(String extension) {
+		// Get all the tools for the current config
+		IConfiguration config = getDefaultConfiguration(getDefaultTarget());
+		ITool[] tools = config.getTools();
+		for (int index = 0; index < tools.length; index++) {
+			ITool tool = tools[index];
+			if (tool.producesFileType(extension)) {
+				String flags = new String();
+				try {
+					flags = tool.getToolFlags();
+				} catch (BuildException e) {
+					// TODO: handle exception
+				}
+				return flags;
+			}
+		}
+		return null;
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.cdt.core.build.managed.IResourceBuildInfo#getOutputExtension(java.lang.String)
+	 */
+	public String getOutputExtension(String resourceExtension) {
+		// Get all the tools for the current config
+		IConfiguration config = getDefaultConfiguration(getDefaultTarget());
+		ITool[] tools = config.getTools();
+		for (int index = 0; index < tools.length; index++) {
+			ITool tool = tools[index];
+			String output = tool.getOutputExtension(resourceExtension);
+			if (output != null) {
+				return output;
+			}
+		}
+		return null;
+	}
+
+	public IResource getOwner() {
+		return owner;
+	}
+	/* (non-Javadoc)
+	 * @see org.eclipse.cdt.core.build.managed.IResourceBuildInfo#getTarget(org.eclipse.cdt.core.build.managed.IConfiguration)
+	 */
+	public ITarget getTarget(String id) {
+		return (ITarget) targetMap.get(id);
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.cdt.core.build.managed.IResourceBuildInfo#getTargets(org.eclipse.cdt.core.build.managed.IConfiguration)
+	 */
+	public List getTargets() {
+		return targets;	
+	}
+	
+	/* (non-Javadoc)
+	 * @see org.eclipse.cdt.core.build.managed.IResourceBuildInfo#getToolForSource(java.lang.String)
+	 */
+	public String getToolForSource(String extension) {
+		// Get all the tools for the current config
+		IConfiguration config = getDefaultConfiguration(getDefaultTarget());
+		ITool[] tools = config.getTools();
+		for (int index = 0; index < tools.length; index++) {
+			ITool tool = tools[index];
+			if (tool.buildsFileType(extension)) {
+				return tool.getToolCommand();
+			}
+		}
+		return null;
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.cdt.core.build.managed.IResourceBuildInfo#getToolInvocation(java.lang.String)
+	 */
+	public String getToolForTarget(String extension) {
+		// Get all the tools for the current config
+		IConfiguration config = getDefaultConfiguration(getDefaultTarget());
+		ITool[] tools = config.getTools();
+		for (int index = 0; index < tools.length; index++) {
+			ITool tool = tools[index];
+			if (tool.producesFileType(extension)) {
+				return tool.getToolCommand();
+			}
+		}
+		return null;
+	}
+
+	public void serialize(Document doc, Element element) {
+		// Write out each target and their default config
+		for (int i = 0; i < targets.size(); ++i) {
+			Element targetElement = doc.createElement("target");
+			element.appendChild(targetElement);
+			((Target)targets.get(i)).serialize(doc, targetElement);
+			IConfiguration config = getDefaultConfiguration((ITarget)targets.get(i));
+			if (config != null) {
+				Element configEl = doc.createElement("defaultConfig");
+				element.appendChild(configEl);
+				configEl.setAttribute("id", config.getId());
+			}
+		}
+		// Persist the default target
+		if (getDefaultTarget() != null){
+			Element targEl = doc.createElement("defaultTarget");
+			element.appendChild(targEl);
+			targEl.setAttribute("id", getDefaultTarget().getId());
+		}
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.cdt.core.build.managed.IResourceBuildInfo#setDefaultConfiguration(org.eclipse.cdt.core.build.managed.IConfiguration)
+	 */
+	public void setDefaultConfiguration(IConfiguration configuration) {
+		// Get the target associated with the argument
+		ITarget target = configuration.getTarget();
+		// Make sure it is the default
+		setDefaultTarget(target);
+		defaultConfigurations.put(target.getId(), configuration);
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.cdt.core.build.managed.IResourceBuildInfo#setDefaultTarget(org.eclipse.cdt.core.build.managed.ITarget)
+	 */
+	public void setDefaultTarget(ITarget target) {
+		if (defaultTarget != null && defaultTarget.getId().equals(target.getId())) {
+			return;
+		}
+		defaultTarget = target;		
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.cdt.core.build.managed.IScannerInfo#getDefinedSymbols()
+	 */
+	public Map getDefinedSymbols() {
+		// Return the defined symbols for the default configuration
+		HashMap symbols = new HashMap();
+		IConfiguration config = getDefaultConfiguration(getDefaultTarget());
+		ITool[] tools = config.getTools();
+		for (int i = 0; i < tools.length; i++) {
+			ITool tool = tools[i];
+			IOption[] opts = tool.getOptions();
+			for (int j = 0; j < opts.length; j++) {
+				IOption option = opts[j];
+				if (option.getValueType() == IOption.PREPROCESSOR_SYMBOLS) {
+					try {
+						String[] symbolList = option.getDefinedSymbols();
+						for (int k = 0; k < symbolList.length; k++) {
+							String symbol = symbolList[k];
+							if (symbol.length() == 0){
+								continue;
+							}
+							String key = new String();
+							String value = new String();
+							int index = symbol.indexOf("=");
+							if (index != -1) {
+								key = symbol.substring(0, index).trim();
+								value = symbol.substring(index + 1).trim();
+							} else {
+								key = symbol.trim();
+							}
+							symbols.put(key, value);
+						}
+
+					} catch (BuildException e) {
+						// we should never get here
+						continue;
+					}
+				}
+			}
+		}
+		return symbols; 
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.cdt.core.build.managed.IScannerInfo#getIncludePaths()
+	 */
+	public String[] getIncludePaths() {
+		// Return the include paths for the default configuration
+		ArrayList paths = new ArrayList();
+		IConfiguration config = getDefaultConfiguration(getDefaultTarget());
+		ITool[] tools = config.getTools();
+		for (int i = 0; i < tools.length; i++) {
+			ITool tool = tools[i];
+			IOption[] opts = tool.getOptions();
+			for (int j = 0; j < opts.length; j++) {
+				IOption option = opts[j];
+				if (option.getValueType() == IOption.INCLUDE_PATH) {
+					try {
+						paths.addAll(Arrays.asList(option.getIncludePaths()));
+					} catch (BuildException e) {
+						// we should never get here
+						continue;
+					}
+				}
+			}
+		}
+		paths.trimToSize();
+		return (String[])paths.toArray(new String[paths.size()]); 
+	}
+
+}
Index: build/org/eclipse/cdt/internal/core/build/managed/ResourceBuildInfo.java
===================================================================
RCS file: build/org/eclipse/cdt/internal/core/build/managed/ResourceBuildInfo.java
diff -N build/org/eclipse/cdt/internal/core/build/managed/ResourceBuildInfo.java
--- build/org/eclipse/cdt/internal/core/build/managed/ResourceBuildInfo.java	23 Jun 2003 14:36:31 -0000	1.4
+++ /dev/null	1 Jan 1970 00:00:00 -0000
@@ -1,333 +0,0 @@
-package org.eclipse.cdt.internal.core.build.managed;
-
-/**********************************************************************
- * Copyright (c) 2002,2003 Rational Software Corporation and others.
- * All rights reserved.   This program and the accompanying materials
- * are made available under the terms of the Common Public License v0.5
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/cpl-v05.html
- * 
- * Contributors: 
- * IBM Rational Software - Initial API and implementation
- * **********************************************************************/
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.HashMap;
-import java.util.List;
-import java.util.ListIterator;
-import java.util.Map;
-
-import org.eclipse.cdt.core.build.managed.BuildException;
-import org.eclipse.cdt.core.build.managed.IManagedBuildPathInfo;
-import org.eclipse.cdt.core.build.managed.IConfiguration;
-import org.eclipse.cdt.core.build.managed.IOption;
-import org.eclipse.cdt.core.build.managed.IResourceBuildInfo;
-import org.eclipse.cdt.core.build.managed.ITarget;
-import org.eclipse.cdt.core.build.managed.ITool;
-import org.eclipse.core.resources.IResource;
-import org.w3c.dom.Document;
-import org.w3c.dom.Element;
-import org.w3c.dom.Node;
-
-public class ResourceBuildInfo implements IResourceBuildInfo, IManagedBuildPathInfo {
-
-	private IResource owner;
-	private Map targetMap;
-	private List targets;
-	private Map defaultConfigurations;
-	private ITarget defaultTarget;
-	
-	public ResourceBuildInfo() {
-		targetMap = new HashMap();
-		targets = new ArrayList();
-		defaultConfigurations = new HashMap();
-	}
-	
-	public ResourceBuildInfo(IResource owner, Element element) {
-		this();
-		// The id of the default configuration
-		String defaultTargetId = null;
-		List configIds = new ArrayList();
-		Node child = element.getFirstChild();
-		while (child != null) {
-			if (child.getNodeName().equals("target")) {
-				new Target(this, (Element)child);
-			} else if (child.getNodeName().equals("defaultConfig")) {
-				// We may not have read the config in yet, so just cache it
-				configIds.add(((Element)child).getAttribute("id"));
-			} else if (child.getNodeName().equals("defaultTarget")) {
-				defaultTargetId = ((Element)child).getAttribute("id");
-			}
-			child = child.getNextSibling();
-		}
-		// All the available targets have been read in
-		defaultTarget = (ITarget) targetMap.get(defaultTargetId);
-		// Now we have a misserable O(N^2) operation (oh well, the data sets are small)
-		ListIterator stringIter = configIds.listIterator();
-		while (stringIter.hasNext()){
-			String confId = (String) stringIter.next();
-			ListIterator targIter = targets.listIterator();
-			while (targIter.hasNext()) {
-				Target targ = (Target) targIter.next();
-				IConfiguration conf = targ.getConfiguration(confId);
-				if (conf != null) {
-					defaultConfigurations.put(targ.getId(), conf);
-					break;
-				}				
-			}
-		}
-	}
-
-	/* (non-Javadoc)
-	 * @see org.eclipse.cdt.core.build.managed.IResourceBuildInfo#addTarget(org.eclipse.cdt.core.build.managed.ITarget)
-	 */
-	public void addTarget(ITarget target) {
-		targetMap.put(target.getId(), target);
-		targets.add(target);
-	}
-
-	/* (non-Javadoc)
-	 * @see org.eclipse.cdt.core.build.managed.IResourceBuildInfo#getBuildArtifactName()
-	 */
-	public String getBuildArtifactName() {
-		// Get the default target and use its value
-		String name = getDefaultTarget().getArtifactName();
-		return name == null ? new String() : name;
-	}
-
-	/* (non-Javadoc)
-	 * @see org.eclipse.cdt.core.build.managed.IResourceBuildInfo#getDefaultConfiguration()
-	 */
-	public IConfiguration getDefaultConfiguration(ITarget target) {
-		// Get the default config associated with the defalt target
-		IConfiguration config = (IConfiguration) defaultConfigurations.get(target.getId());
-
-		// If null, look up the first configuration associated with the target
-		if (config == null) {
-			IConfiguration[] configs = getDefaultTarget().getConfigurations();
-			if (configs.length > 0) {
-				config = configs[0];
-			}
-		}
-		return config;
-	}
-
-	/* (non-Javadoc)
-	 * @see org.eclipse.cdt.core.build.managed.IResourceBuildInfo#getDefaultTarget()
-	 */
-	public ITarget getDefaultTarget() {
-		if (defaultTarget == null) {
-			defaultTarget = (ITarget) targets.get(0);
-		}
-		return defaultTarget;
-	}
-
-	/* (non-Javadoc)
-	 * @see org.eclipse.cdt.core.build.managed.IResourceBuildInfo#getFlagsForSource(java.lang.String)
-	 */
-	public String getFlagsForSource(String extension) {
-		// Get all the tools for the current config
-		IConfiguration config = getDefaultConfiguration(getDefaultTarget());
-		ITool[] tools = config.getTools();
-		for (int index = 0; index < tools.length; index++) {
-			ITool tool = tools[index];
-			if (tool.buildsFileType(extension)) {
-				String flags = new String();
-				try {
-					flags = tool.getToolFlags();
-				} catch (BuildException e) {
-					// Give it your best shot with the next tool
-					continue;
-				}
-				return flags;
-			}
-		}
-		return null;
-	}
-
-	/* (non-Javadoc)
-	 * @see org.eclipse.cdt.core.build.managed.IResourceBuildInfo#getToolFlags(java.lang.String)
-	 */
-	public String getFlagsForTarget(String extension) {
-		// Get all the tools for the current config
-		IConfiguration config = getDefaultConfiguration(getDefaultTarget());
-		ITool[] tools = config.getTools();
-		for (int index = 0; index < tools.length; index++) {
-			ITool tool = tools[index];
-			if (tool.producesFileType(extension)) {
-				String flags = new String();
-				try {
-					flags = tool.getToolFlags();
-				} catch (BuildException e) {
-					// TODO: handle exception
-				}
-				return flags;
-			}
-		}
-		return null;
-	}
-
-	/* (non-Javadoc)
-	 * @see org.eclipse.cdt.core.build.managed.IResourceBuildInfo#getOutputExtension(java.lang.String)
-	 */
-	public String getOutputExtension(String resourceExtension) {
-		// Get all the tools for the current config
-		IConfiguration config = getDefaultConfiguration(getDefaultTarget());
-		ITool[] tools = config.getTools();
-		for (int index = 0; index < tools.length; index++) {
-			ITool tool = tools[index];
-			String output = tool.getOutputExtension(resourceExtension);
-			if (output != null) {
-				return output;
-			}
-		}
-		return null;
-	}
-
-	public IResource getOwner() {
-		return owner;
-	}
-	/* (non-Javadoc)
-	 * @see org.eclipse.cdt.core.build.managed.IResourceBuildInfo#getTarget(org.eclipse.cdt.core.build.managed.IConfiguration)
-	 */
-	public ITarget getTarget(String id) {
-		return (ITarget) targetMap.get(id);
-	}
-
-	/* (non-Javadoc)
-	 * @see org.eclipse.cdt.core.build.managed.IResourceBuildInfo#getTargets(org.eclipse.cdt.core.build.managed.IConfiguration)
-	 */
-	public List getTargets() {
-		return targets;	
-	}
-	
-	/* (non-Javadoc)
-	 * @see org.eclipse.cdt.core.build.managed.IResourceBuildInfo#getToolForSource(java.lang.String)
-	 */
-	public String getToolForSource(String extension) {
-		// Get all the tools for the current config
-		IConfiguration config = getDefaultConfiguration(getDefaultTarget());
-		ITool[] tools = config.getTools();
-		for (int index = 0; index < tools.length; index++) {
-			ITool tool = tools[index];
-			if (tool.buildsFileType(extension)) {
-				return tool.getToolCommand();
-			}
-		}
-		return null;
-	}
-
-	/* (non-Javadoc)
-	 * @see org.eclipse.cdt.core.build.managed.IResourceBuildInfo#getToolInvocation(java.lang.String)
-	 */
-	public String getToolForTarget(String extension) {
-		// Get all the tools for the current config
-		IConfiguration config = getDefaultConfiguration(getDefaultTarget());
-		ITool[] tools = config.getTools();
-		for (int index = 0; index < tools.length; index++) {
-			ITool tool = tools[index];
-			if (tool.producesFileType(extension)) {
-				return tool.getToolCommand();
-			}
-		}
-		return null;
-	}
-
-	public void serialize(Document doc, Element element) {
-		// Write out each target and their default config
-		for (int i = 0; i < targets.size(); ++i) {
-			Element targetElement = doc.createElement("target");
-			element.appendChild(targetElement);
-			((Target)targets.get(i)).serialize(doc, targetElement);
-			IConfiguration config = getDefaultConfiguration((ITarget)targets.get(i));
-			if (config != null) {
-				Element configEl = doc.createElement("defaultConfig");
-				element.appendChild(configEl);
-				configEl.setAttribute("id", config.getId());
-			}
-		}
-		// Persist the default target
-		if (getDefaultTarget() != null){
-			Element targEl = doc.createElement("defaultTarget");
-			element.appendChild(targEl);
-			targEl.setAttribute("id", getDefaultTarget().getId());
-		}
-	}
-
-	/* (non-Javadoc)
-	 * @see org.eclipse.cdt.core.build.managed.IResourceBuildInfo#setDefaultConfiguration(org.eclipse.cdt.core.build.managed.IConfiguration)
-	 */
-	public void setDefaultConfiguration(IConfiguration configuration) {
-		// Get the target associated with the argument
-		ITarget target = configuration.getTarget();
-		// Make sure it is the default
-		setDefaultTarget(target);
-		defaultConfigurations.put(target.getId(), configuration);
-	}
-
-	/* (non-Javadoc)
-	 * @see org.eclipse.cdt.core.build.managed.IResourceBuildInfo#setDefaultTarget(org.eclipse.cdt.core.build.managed.ITarget)
-	 */
-	public void setDefaultTarget(ITarget target) {
-		if (defaultTarget != null && defaultTarget.getId().equals(target.getId())) {
-			return;
-		}
-		defaultTarget = target;		
-	}
-
-	/* (non-Javadoc)
-	 * @see org.eclipse.cdt.core.build.managed.IBuildParseInfo#getDefinedSymbols()
-	 */
-	public String[] getDefinedSymbols() {
-		// Return the include paths for the default configuration
-		ArrayList paths = new ArrayList();
-		IConfiguration config = getDefaultConfiguration(getDefaultTarget());
-		ITool[] tools = config.getTools();
-		for (int i = 0; i < tools.length; i++) {
-			ITool tool = tools[i];
-			IOption[] opts = tool.getOptions();
-			for (int j = 0; j < opts.length; j++) {
-				IOption option = opts[j];
-				if (option.getValueType() == IOption.PREPROCESSOR_SYMBOLS) {
-					try {
-						paths.addAll(Arrays.asList(option.getDefinedSymbols()));
-					} catch (BuildException e) {
-						// we should never get here
-						continue;
-					}
-				}
-			}
-		}
-		paths.trimToSize();
-		return (String[])paths.toArray(new String[paths.size()]); 
-	}
-
-	/* (non-Javadoc)
-	 * @see org.eclipse.cdt.core.build.managed.IBuildParseInfo#getIncludePaths()
-	 */
-	public String[] getIncludePaths() {
-		// Return the include paths for the default configuration
-		ArrayList paths = new ArrayList();
-		IConfiguration config = getDefaultConfiguration(getDefaultTarget());
-		ITool[] tools = config.getTools();
-		for (int i = 0; i < tools.length; i++) {
-			ITool tool = tools[i];
-			IOption[] opts = tool.getOptions();
-			for (int j = 0; j < opts.length; j++) {
-				IOption option = opts[j];
-				if (option.getValueType() == IOption.INCLUDE_PATH) {
-					try {
-						paths.addAll(Arrays.asList(option.getIncludePaths()));
-					} catch (BuildException e) {
-						// we should never get here
-						continue;
-					}
-				}
-			}
-		}
-		paths.trimToSize();
-		return (String[])paths.toArray(new String[paths.size()]); 
-	}
-
-}
Index: build/org/eclipse/cdt/internal/core/build/managed/Target.java
===================================================================
RCS file: /home/tools/org.eclipse.cdt.core/build/org/eclipse/cdt/internal/core/build/managed/Target.java,v
retrieving revision 1.9
diff -u -r1.9 Target.java
--- build/org/eclipse/cdt/internal/core/build/managed/Target.java	9 Jun 2003 19:22:15 -0000	1.9
+++ build/org/eclipse/cdt/internal/core/build/managed/Target.java	3 Jul 2003 20:48:35 -0000
@@ -16,7 +16,7 @@
 import java.util.Map;
 
 import org.eclipse.cdt.core.build.managed.IConfiguration;
-import org.eclipse.cdt.core.build.managed.IResourceBuildInfo;
+import org.eclipse.cdt.core.build.managed.IManagedBuildInfo;
 import org.eclipse.cdt.core.build.managed.ITarget;
 import org.eclipse.cdt.core.build.managed.ITool;
 import org.eclipse.cdt.core.build.managed.ManagedBuildManager;
@@ -68,7 +68,7 @@
 		this.isTest = parent.isTestTarget();
 
 		// Hook me up
-		IResourceBuildInfo buildInfo = ManagedBuildManager.getBuildInfo(owner, true);
+		IManagedBuildInfo buildInfo = ManagedBuildManager.getBuildInfo(owner, true);
 		buildInfo.addTarget(this);
 	}
 
@@ -129,7 +129,7 @@
 	 * @param buildInfo
 	 * @param element
 	 */
-	public Target(ResourceBuildInfo buildInfo, Element element) {
+	public Target(ManagedBuildInfo buildInfo, Element element) {
 		this(buildInfo.getOwner());
 		
 		// id
Index: parser/org/eclipse/cdt/core/parser/IScannerInfo.java
===================================================================
RCS file: parser/org/eclipse/cdt/core/parser/IScannerInfo.java
diff -N parser/org/eclipse/cdt/core/parser/IScannerInfo.java
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ parser/org/eclipse/cdt/core/parser/IScannerInfo.java	3 Jul 2003 20:48:35 -0000
@@ -0,0 +1,39 @@
+package org.eclipse.cdt.core.parser;
+
+import java.util.Map;
+
+/**********************************************************************
+ * Copyright (c) 2002,2003 Rational Software Corporation and others.
+ * All rights reserved.   This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ * 
+ * Contributors: 
+ * IBM Rational Software - Initial API and implementation
+***********************************************************************/
+
+public interface IScannerInfo {
+	/**
+	 * Answers a <code>Map</code> containing all the defined preprocessor 
+	 * symbols and their values as string tuples, (symbol_name, symbol_value).
+	 * Symbols defined without values have an empty string for a value. For 
+	 * example,-Dsymbol=value would have a map entry (symbol,value). A symbol
+	 * defined as -Dsymbol would have a map entry of (symbol,"").
+	 * 
+	 * If there are no defined symbols, the receiver will return 
+	 * an empty Map, never <code>null</code>. 
+	 *  
+	 * @return
+	 */
+	public Map getDefinedSymbols();
+
+	/**
+	 * Answers a <code>String</code> array containing all the known include 
+	 * search paths. If there are no paths defined, the receiver will 
+	 * return an empty array, never <code>null</code>
+	 * 
+	 * @return
+	 */
+	public String[] getIncludePaths();
+}
Index: parser/org/eclipse/cdt/core/parser/IScannerInfoChangeListener.java
===================================================================
RCS file: parser/org/eclipse/cdt/core/parser/IScannerInfoChangeListener.java
diff -N parser/org/eclipse/cdt/core/parser/IScannerInfoChangeListener.java
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ parser/org/eclipse/cdt/core/parser/IScannerInfoChangeListener.java	3 Jul 2003 20:48:35 -0000
@@ -0,0 +1,26 @@
+package org.eclipse.cdt.core.parser;
+
+import org.eclipse.core.resources.IResource;
+
+/**********************************************************************
+ * Copyright (c) 2002,2003 Rational Software Corporation and others.
+ * All rights reserved.   This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ * 
+ * Contributors: 
+ * IBM Rational Software - Initial API and implementation
+***********************************************************************/
+
+public interface IScannerInfoChangeListener {
+	
+	/**
+	 * The listener must implement this method in order to receive the new 
+	 * information from the provider.
+	 * 
+	 * @param info
+	 */
+	public void changeNotification(IResource project, IScannerInfo info);
+
+}
Index: parser/org/eclipse/cdt/core/parser/IScannerInfoProvider.java
===================================================================
RCS file: parser/org/eclipse/cdt/core/parser/IScannerInfoProvider.java
diff -N parser/org/eclipse/cdt/core/parser/IScannerInfoProvider.java
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ parser/org/eclipse/cdt/core/parser/IScannerInfoProvider.java	3 Jul 2003 20:48:35 -0000
@@ -0,0 +1,44 @@
+package org.eclipse.cdt.core.parser;
+
+import org.eclipse.core.resources.IResource;
+
+/**********************************************************************
+ * Copyright (c) 2002,2003 Rational Software Corporation and others.
+ * All rights reserved.   This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ * 
+ * Contributors: 
+ * IBM Rational Software - Initial API and implementation
+***********************************************************************/
+
+public interface IScannerInfoProvider {
+	
+	/**
+	 * The receiver will register the listener specified in the argument
+	 * to receive change notifications when the information for the 
+	 * <code>IResource</code> it is responsible for changes. 
+	 *  
+	 * @param listener
+	 */
+	public void subscribe(IResource resource, IScannerInfoChangeListener listener);
+	
+	/**
+	 * Answers <code>true</code> if the receiver has information for
+	 * the resource specified in the argument, else <code>false</code>. 
+	 * 
+	 * @param resource
+	 * @return
+	 */
+	public boolean managesResource(IResource resource);
+	
+	/**
+	 * The receiver will no longer notify the listener specified in 
+	 * the argument when information about the reource it is responsible 
+	 * for changes.
+	 * 
+	 * @param listener
+	 */
+	public void unsubscribe(IResource resource, IScannerInfoChangeListener listener);
+}
Index: schema/ManagedBuildTools.exsd
===================================================================
RCS file: /home/tools/org.eclipse.cdt.core/schema/ManagedBuildTools.exsd,v
retrieving revision 1.7
diff -u -r1.7 ManagedBuildTools.exsd
--- schema/ManagedBuildTools.exsd	23 Jun 2003 14:36:31 -0000	1.7
+++ schema/ManagedBuildTools.exsd	3 Jul 2003 20:48:36 -0000
@@ -118,8 +118,8 @@
          <attribute name="valueType" use="default" value="string">
             <annotation>
                <documentation>
-                  General options can be one of the following types; &apos;string&apos; for catch-all entries for options that cannot be easily defined any other way, &apos;string list&apos; for entries that consist of a list of values such as defined symbols or paths, &apos;boolean&apos; for options that have two values, and &apos;enumerated&apos; for options that are one-of a list of values.
-
+                  General options can be one of the following types; &apos;string&apos; for catch-all entries for options that cannot be easily defined any other way, &apos;string list&apos; for entries that consist of a list of values such as defined symbols or paths, &apos;boolean&apos; for options that have two values, and &apos;enumerated&apos; for options that are one-of a list of values.
+
 Two additional types exist to flag options of special relevance to the build model; &apos;include&apos;, and &apos;definedSymbols&apos;. You can pre-populate with optionValues, and they will display in the UI the same way the &apos;StringList&apos; options do. The build model will look specifically for these value types when clients query for include paths and preprocessor defines.
                </documentation>
             </annotation>
@@ -393,7 +393,7 @@
          <meta.section type="since"/>
       </appInfo>
       <documentation>
-         CDT 1.1
+         1.2
       </documentation>
    </annotation>
 
Index: schema/ScannerInfoProvider.exsd
===================================================================
RCS file: schema/ScannerInfoProvider.exsd
diff -N schema/ScannerInfoProvider.exsd
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ schema/ScannerInfoProvider.exsd	3 Jul 2003 20:48:36 -0000
@@ -0,0 +1,121 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<!-- Schema file written by PDE -->
+<schema targetNamespace="org.eclipse.cdt.core">
+<annotation>
+      <appInfo>
+         <meta.schema plugin="org.eclipse.cdt.core" id="ScannerInfoProvider" name="Scanner Information Provider"/>
+      </appInfo>
+      <documentation>
+         This extension point provides a mechanism for the clients of the scanner to discover providers of information the scanner requires to function properly. This information is usually provided by a build system.
+      </documentation>
+   </annotation>
+
+   <element name="extension">
+      <complexType>
+         <sequence>
+            <element ref="provider" minOccurs="1" maxOccurs="unbounded"/>
+         </sequence>
+         <attribute name="point" type="string" use="required">
+            <annotation>
+               <documentation>
+                  
+               </documentation>
+            </annotation>
+         </attribute>
+         <attribute name="id" type="string">
+            <annotation>
+               <documentation>
+                  
+               </documentation>
+            </annotation>
+         </attribute>
+         <attribute name="name" type="string">
+            <annotation>
+               <documentation>
+                  
+               </documentation>
+            </annotation>
+         </attribute>
+      </complexType>
+   </element>
+
+   <element name="provider">
+      <complexType>
+         <attribute name="id" type="string" use="required">
+            <annotation>
+               <documentation>
+                  A unique name that will be used to reference this parser.
+               </documentation>
+            </annotation>
+         </attribute>
+         <attribute name="class" type="string">
+            <annotation>
+               <documentation>
+                  A fully qualified name of the Java class that implements &lt;samp&gt;org.eclipse.cdt.core.parser.IScannerProviderInfo&lt;/samp&gt; interface
+               </documentation>
+               <appInfo>
+                  <meta.attribute kind="java" basedOn="org.eclipse.cdt.core.parser.IScannerProviderInfo"/>
+               </appInfo>
+            </annotation>
+         </attribute>
+      </complexType>
+   </element>
+
+   <annotation>
+      <appInfo>
+         <meta.section type="since"/>
+      </appInfo>
+      <documentation>
+         1.2
+      </documentation>
+   </annotation>
+
+   <annotation>
+      <appInfo>
+         <meta.section type="examples"/>
+      </appInfo>
+      <documentation>
+         [Enter extension point usage example here.]
+      </documentation>
+   </annotation>
+
+   <annotation>
+      <appInfo>
+         <meta.section type="apiInfo"/>
+      </appInfo>
+      <documentation>
+         The following is an example of the extension point usage:
+&lt;p&gt;
+&lt;pre&gt;
+&lt;extension
+	id=&quot;org.eclipse.cdt.core.ScannerInfoProvider&quot;
+    name=&quot;Scanner Information Provider&quot;
+    point=&quot;org.eclipse.cdt.core.ScannerInfoProvider&quot;&gt;
+    &lt;provider
+    	id=&quot;org.eclipse.cdt.core.provider.managed&quot;
+    	class=&quot;org.eclipse.cdt.core.build.managed.ManagedBuildManager&quot;&gt;
+	&lt;/provider&gt;
+&lt;/extension&gt;
+&lt;/pre&gt;
+      </documentation>
+   </annotation>
+
+   <annotation>
+      <appInfo>
+         <meta.section type="implementation"/>
+      </appInfo>
+      <documentation>
+         [Enter information about supplied implementation of this extension point.]
+      </documentation>
+   </annotation>
+
+   <annotation>
+      <appInfo>
+         <meta.section type="copyright"/>
+      </appInfo>
+      <documentation>
+         
+      </documentation>
+   </annotation>
+
+</schema>
Index: src/org/eclipse/cdt/core/BuildInfoFactory.java
===================================================================
RCS file: /home/tools/org.eclipse.cdt.core/src/org/eclipse/cdt/core/BuildInfoFactory.java,v
retrieving revision 1.4
diff -u -r1.4 BuildInfoFactory.java
--- src/org/eclipse/cdt/core/BuildInfoFactory.java	26 Jun 2003 17:43:32 -0000	1.4
+++ src/org/eclipse/cdt/core/BuildInfoFactory.java	3 Jul 2003 20:48:36 -0000
@@ -6,6 +6,15 @@
  */
 
 
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.ListIterator;
+import java.util.Map;
+
+import org.eclipse.cdt.core.parser.IScannerInfo;
+import org.eclipse.cdt.core.resources.IStandardBuildInfo;
 import org.eclipse.core.resources.IProject;
 import org.eclipse.core.resources.IResource;
 import org.eclipse.core.runtime.CoreException;
@@ -15,8 +24,9 @@
 import org.eclipse.core.runtime.Plugin;
 import org.eclipse.core.runtime.Preferences;
 import org.eclipse.core.runtime.QualifiedName;
-
-import org.eclipse.cdt.core.resources.IBuildInfo;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
 
 public class BuildInfoFactory {
 	public static final String LOCATION = "buildLocation";
@@ -25,10 +35,17 @@
 	public static final String STOP_ON_ERROR = "stopOnError";
 //	public static final String CLEAR_CONSOLE = "clearConsole";
 	public static final String DEFAULT_BUILD_CMD = "useDefaultBuildCmd";
-	public static final String INCLUDE_PATHS = "includePaths";
-	public static final String DEFINED_SYMBOLS = "definedSymbols";
+	public static final String PROJECT_NAME = "projectName";
+	public static final String INCLUDE_PATH = "includePath";
+	public static final String PATH = "path";
+	public static final String DEFINED_SYMBOL = "definedSymbol";
+	public static final String SYMBOL = "symbol";
 	
-	public static abstract class Store implements IBuildInfo {
+	public static abstract class Store implements IStandardBuildInfo, IScannerInfo {
+		// List of include paths
+		protected List pathList;
+		protected List symbolList;
+		
     	public String getBuildLocation() {
     		if ( isDefaultBuildCmd() ) {
 				Plugin plugin = CCorePlugin.getDefault();
@@ -51,16 +68,41 @@
 			return getString(LOCATION);
     	}
     	
-    	public String getDefinedSymbols() {
-    		return getString(DEFINED_SYMBOLS);
+		/* (non-Javadoc)
+		 * @see org.eclipse.cdt.core.build.managed.IScannerInfo#getIncludePaths()
+		 */
+    	public Map getDefinedSymbols() {
+			// Return the defined symbols for the default configuration
+			HashMap symbols = new HashMap();
+			String[] symbolList = getPreprocessorSymbols();
+			for (int i = 0; i < symbolList.length; ++i) {
+				String symbol = symbolList[i];
+				if (symbol.length() == 0) {
+					continue;
+				}
+				String key = new String();
+				String value = new String();
+				int index = symbol.indexOf("=");
+				if (index != -1) {
+					key = symbol.substring(0, index).trim();
+					value = symbol.substring(index + 1).trim();
+				} else {
+					key = symbol.trim();
+				}
+				symbols.put(key, value);
+			}
+			return symbols; 
     	}
     	
         public String getFullBuildArguments() {
         	return getString(FULL_ARGUMENTS);
         }
         
-        public String getIncludePaths() {
-        	return getString(INCLUDE_PATHS);
+		/* (non-Javadoc)
+		 * @see org.eclipse.cdt.core.build.managed.IScannerInfo#getIncludePaths()
+		 */
+        public String[] getIncludePaths() {
+        	return (String[]) getPathList().toArray(new String[getPathList().size()]);
         }
         
         public String getIncrementalBuildArguments() {
@@ -75,16 +117,20 @@
 	    	putValue(LOCATION, location);
 	    }
 	    
-	    public void setDefinedSymbols(String argument) {
-	    	putValue(DEFINED_SYMBOLS, argument);
+	    public void setPreprocessorSymbols(String[] symbols) {
+	    	// Clear out any existing symbols and add the new stuff
+	    	getSymbolList().clear();
+	    	getSymbolList().addAll(Arrays.asList(symbols));
 	    }
 	    
         public void setFullBuildArguments(String arguments) {
         	putValue(FULL_ARGUMENTS, arguments);
         }
         
-		public void setIncludePaths(String arguments) {
-			putValue(INCLUDE_PATHS, arguments);	        
+		public void setIncludePaths(String[] paths) {
+			// Clear the existing list and add the paths
+			getPathList().clear();
+			getPathList().addAll(Arrays.asList(paths));
 		}
 		
         public void setIncrementalBuildArguments(String arguments) {
@@ -117,10 +163,48 @@
 	    public void putValue(String name, String value) {
 	    }
 
+		/* (non-Javadoc)
+		 * @see org.eclipse.cdt.core.resources.IBuildInfo#serialize(org.w3c.dom.Document, org.w3c.dom.Element)
+		 */
+		public void serialize(Document doc, Element rootElement) {
+			// Serialize the include paths
+			ListIterator iter = getPathList().listIterator();
+			while (iter.hasNext()){
+				Element pathElement = doc.createElement(INCLUDE_PATH);
+				pathElement.setAttribute(PATH, (String)iter.next());
+				rootElement.appendChild(pathElement);
+			}
+			// Now do the same for the symbols
+			iter = getSymbolList().listIterator();
+			while (iter.hasNext()) {
+				Element symbolElement = doc.createElement(DEFINED_SYMBOL);
+				symbolElement.setAttribute(SYMBOL, (String)iter.next());
+				rootElement.appendChild(symbolElement);
+			}
+		}
+
+		protected List getPathList() {
+			if (pathList == null) {
+				pathList = new ArrayList();
+			}
+			return pathList;
+		}
+
 	    public String getString(String property) {
 	    	return null;
 	    }
 
+		public String[] getPreprocessorSymbols() {
+			return (String[]) getSymbolList().toArray(new String[getSymbolList().size()]);
+		}
+    	
+		protected List getSymbolList() {
+			if (symbolList == null) {
+				symbolList = new ArrayList();
+			}
+			return symbolList;
+		}
+
 	}
 	
 	public static class Preference extends Store {
@@ -169,18 +253,41 @@
 		
 		public void setDefault(String name, String def) {
 		}
-		
+
+
 //		public boolean isClearBuildConsole() {
 //			return (new Preference()).isClearBuildConsole();
 //		}
 	}
     
-    public static IBuildInfo create() {
+    public static IStandardBuildInfo create() {
     	return new BuildInfoFactory.Preference();
     }
     
-    public static IBuildInfo create(IProject project) {
+    public static IStandardBuildInfo create(IProject project) {
     	return new BuildInfoFactory.Property(project);
     }
+
+	/**
+	 * @param project
+	 * @param element
+	 * @return
+	 */
+	public static IStandardBuildInfo create(IProject project, Element element) {
+		// Create a new info property object
+		Property buildProperties = new Property(project);
+		Node child = element.getFirstChild();
+		while (child != null) {
+			if (child.getNodeName().equals(INCLUDE_PATH)) {
+				// Add the path to the property list
+				buildProperties.getPathList().add(((Element)child).getAttribute(PATH));
+			} else if (child.getNodeName().equals(DEFINED_SYMBOL)) {
+				// Add the symbol to the symbol list
+				buildProperties.getSymbolList().add(((Element)child).getAttribute(SYMBOL));
+			}
+			child = child.getNextSibling();
+		}
+		return (IStandardBuildInfo)buildProperties;
+	}
 }
 
Index: src/org/eclipse/cdt/core/CProjectNature.java
===================================================================
RCS file: /home/tools/org.eclipse.cdt.core/src/org/eclipse/cdt/core/CProjectNature.java,v
retrieving revision 1.4
diff -u -r1.4 CProjectNature.java
--- src/org/eclipse/cdt/core/CProjectNature.java	26 Jun 2003 17:43:33 -0000	1.4
+++ src/org/eclipse/cdt/core/CProjectNature.java	3 Jul 2003 20:48:36 -0000
@@ -9,7 +9,8 @@
 import java.util.Arrays;
 import java.util.List;
 
-import org.eclipse.cdt.core.resources.IBuildInfo;
+import org.eclipse.cdt.core.build.standard.StandardBuildManager;
+import org.eclipse.cdt.core.resources.IStandardBuildInfo;
 import org.eclipse.core.resources.ICommand;
 import org.eclipse.core.resources.IProject;
 import org.eclipse.core.resources.IProjectDescription;
@@ -30,7 +31,7 @@
     public static final String C_NATURE_ID= CCorePlugin.PLUGIN_ID + ".cnature";
 
     private IProject fProject;
-    private IBuildInfo fBuildInfo;
+    private IStandardBuildInfo fBuildInfo;
 
     public CProjectNature() {
     }
@@ -106,30 +107,6 @@
 	    return new Path(buildLocation);
     }
 
-	/**
-	 * Answers a comma-separated list of defined preprocessor symbols
-	 * for the project, or an empty string if there are none.
-	 * 
-	 * @return
-	 * @throws CoreException
-	 */
-	public String getDefinedSymbols() throws CoreException {
-		String symbols = fBuildInfo.getDefinedSymbols();
-		return symbols == null ? new String() : symbols;
-	}
-	
-	/**
-	 * Sets the defined symbols for the project.
-	 * 
-	 * @param symbols
-	 */
-	public void setDefinedSymbols(String symbols, IProgressMonitor monitor) throws CoreException {
-		String oldSymbols = fBuildInfo.getDefinedSymbols();
-		if (symbols != null && !symbols.equals(oldSymbols)) {
-			fBuildInfo.setDefinedSymbols(symbols);
-		}
-	}
-	
     /**
      * Sets the arguments for the full build.
      */
@@ -152,32 +129,6 @@
     }
     
     /**
-     * Answers a comma-separated list of include paths defined for
-     * the project, or an empty string if there are none.
-     * 
-	 * @return
-	 * @throws CoreException
-	 */
-	public String getIncludePaths() throws CoreException {
-    	String paths = fBuildInfo.getIncludePaths();
-    	return paths == null ? new String() : paths;
-    }
-
-	/**
-	 * Sets the include path information for the project.
-	 * 
-	 * @param paths
-	 * @param monitor
-	 * @throws CoreException
-	 */
-	public void setIncludePaths(String paths, IProgressMonitor monitor) throws CoreException {
-		String oldPaths = fBuildInfo.getIncludePaths();
-		if (paths != null && !paths.equals(oldPaths)) {
-			fBuildInfo.setIncludePaths(paths);
-		}
-	}
-	
-    /**
      * Sets the arguments for the incremental build.
      */
     public void setIncrBuildArguments(String arguments, IProgressMonitor monitor) throws CoreException {
@@ -318,7 +269,7 @@
      */
     public void configure() throws CoreException {
 		addToBuildSpec(getBuilderID(), null);
-		IBuildInfo info = BuildInfoFactory.create();
+		IStandardBuildInfo info = BuildInfoFactory.create();
 		fBuildInfo.setBuildLocation(info.getBuildLocation());
 		fBuildInfo.setFullBuildArguments("");
 		fBuildInfo.setIncrementalBuildArguments("");
@@ -346,6 +297,7 @@
      */
     public void setProject(IProject project) {
 		fProject= project;
-		fBuildInfo = BuildInfoFactory.create(fProject);
+		fBuildInfo = StandardBuildManager.getBuildInfo(fProject, true);
     }
+    
 }
Index: src/org/eclipse/cdt/core/resources/IBuildInfo.java
===================================================================
RCS file: src/org/eclipse/cdt/core/resources/IBuildInfo.java
diff -N src/org/eclipse/cdt/core/resources/IBuildInfo.java
--- src/org/eclipse/cdt/core/resources/IBuildInfo.java	26 Jun 2003 17:43:33 -0000	1.3
+++ /dev/null	1 Jan 1970 00:00:00 -0000
@@ -1,30 +0,0 @@
-package org.eclipse.cdt.core.resources;
-
-/*
- * (c) Copyright QNX Software Systems Ltd. 2002.
- * All Rights Reserved.
- */
-
-public interface IBuildInfo {
-	public static final String SEPARATOR = ",";
-	
-	String getBuildLocation();
-	String getDefinedSymbols();
-    String getFullBuildArguments();
-    String getIncludePaths();
-    String getIncrementalBuildArguments();
-    boolean isStopOnError();
-
-	void setBuildLocation(String location);
-	void setDefinedSymbols(String symbols);
-    void setFullBuildArguments(String arguments);
-    void setIncludePaths(String paths);
-    void setIncrementalBuildArguments(String arguments);
-    void setStopOnError(boolean on);
-
-//    boolean isClearBuildConsole();
-
-    boolean isDefaultBuildCmd();
-    void setUseDefaultBuildCmd(boolean on);
-}
-
Index: src/org/eclipse/cdt/core/resources/IStandardBuildInfo.java
===================================================================
RCS file: src/org/eclipse/cdt/core/resources/IStandardBuildInfo.java
diff -N src/org/eclipse/cdt/core/resources/IStandardBuildInfo.java
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/org/eclipse/cdt/core/resources/IStandardBuildInfo.java	3 Jul 2003 20:48:36 -0000
@@ -0,0 +1,38 @@
+package org.eclipse.cdt.core.resources;
+
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+
+
+/*
+ * (c) Copyright QNX Software Systems Ltd. 2002.
+ * All Rights Reserved.
+ */
+
+public interface IStandardBuildInfo {
+	String getBuildLocation();
+	public String[] getPreprocessorSymbols();
+    String getFullBuildArguments();
+    public String[] getIncludePaths();
+    String getIncrementalBuildArguments();
+    boolean isStopOnError();
+    
+	void setBuildLocation(String location);
+	public void setPreprocessorSymbols(String[] symbols);
+    void setFullBuildArguments(String arguments);
+	public void setIncludePaths(String[] paths);
+	void setIncrementalBuildArguments(String arguments);
+    void setStopOnError(boolean on);
+
+//    boolean isClearBuildConsole();
+
+    boolean isDefaultBuildCmd();
+    void setUseDefaultBuildCmd(boolean on);
+
+	/**
+	 * @param doc
+	 * @param rootElement
+	 */
+	void serialize(Document doc, Element rootElement);
+}
+
Index: src/org/eclipse/cdt/internal/core/GeneratedMakefileBuilder.java
===================================================================
RCS file: /home/tools/org.eclipse.cdt.core/src/org/eclipse/cdt/internal/core/GeneratedMakefileBuilder.java,v
retrieving revision 1.2
diff -u -r1.2 GeneratedMakefileBuilder.java
--- src/org/eclipse/cdt/internal/core/GeneratedMakefileBuilder.java	9 Jun 2003 19:22:15 -0000	1.2
+++ src/org/eclipse/cdt/internal/core/GeneratedMakefileBuilder.java	3 Jul 2003 20:48:36 -0000
@@ -14,7 +14,7 @@
 import java.io.ByteArrayInputStream;
 import java.util.Map;
 import org.eclipse.cdt.core.CCorePlugin;
-import org.eclipse.cdt.core.build.managed.IResourceBuildInfo;
+import org.eclipse.cdt.core.build.managed.IManagedBuildInfo;
 import org.eclipse.cdt.core.build.managed.ManagedBuildManager;
 import org.eclipse.cdt.core.resources.ACBuilder;
 import org.eclipse.cdt.core.resources.MakeUtil;
@@ -72,14 +72,14 @@
 	 * 
 	 * @param buffer
 	 */
-	private void addMacros(StringBuffer buffer, IResourceBuildInfo info) {
+	private void addMacros(StringBuffer buffer, IManagedBuildInfo info) {
 		// TODO this should come from the build model
 		buffer.append("RM = rm -f" + NEWLINE);
 		buffer.append("MAKE = make" + NEWLINE);
 		buffer.append(NEWLINE);
 	}
 
-	private void addRule(StringBuffer buffer, IPath sourcePath, String outputName, IResourceBuildInfo info) {
+	private void addRule(StringBuffer buffer, IPath sourcePath, String outputName, IManagedBuildInfo info) {
 		// Add the rule to the makefile
 		buffer.append(outputName + COLON + " " + sourcePath.toString());
 		// Add all of the dependencies on the source file
@@ -96,7 +96,7 @@
 	 *  
 	 * @param buffer
 	 */
-	private void addSources(StringBuffer buffer, IResourceBuildInfo info) throws CoreException {
+	private void addSources(StringBuffer buffer, IManagedBuildInfo info) throws CoreException {
 		// Add the list of project files to be built
 		buffer.append("OBJS = \\" + NEWLINE);
 		
@@ -133,7 +133,7 @@
 	/**
 	 * @param buffer
 	 */
-	private void addTargets(StringBuffer buffer, IResourceBuildInfo info) {
+	private void addTargets(StringBuffer buffer, IManagedBuildInfo info) {
 		// Generate a rule per source
 
 		// This is the top build rule
@@ -270,9 +270,7 @@
 		monitor.subTask(statusMsg);
 
 		// Get a filehandle for the makefile
-		IPath filePath = getWorkingDirectory();
-		filePath.addTrailingSeparator();
-		filePath.append(FILENAME);
+		IPath filePath = getWorkingDirectory().append(IPath.SEPARATOR + FILENAME);
 		IFile fileHandle = getMakefile(filePath, monitor);
 
 		// Now populate it
@@ -289,7 +287,7 @@
 	private void populateMakefile(IFile fileHandle, IProgressMonitor monitor) throws CoreException {
 		// Write out the contents of the build model
 		StringBuffer buffer = new StringBuffer();
-		IResourceBuildInfo info = ManagedBuildManager.getBuildInfo(getProject());
+		IManagedBuildInfo info = ManagedBuildManager.getBuildInfo(getProject());
 		
 		// Add the macro definitions
 		addMacros(buffer, info);

Back to the top