diff --git a/core/org.eclipse.cdt.core.tests/ChangeLog b/core/org.eclipse.cdt.core.tests/ChangeLog index 456787d5a45..6d8fcbed5de 100644 --- a/core/org.eclipse.cdt.core.tests/ChangeLog +++ b/core/org.eclipse.cdt.core.tests/ChangeLog @@ -1,3 +1,9 @@ +2003-09-10 Sean Evoy + Added a test for resetting the value of a configuration to the defaults defined in the + plugin file. Work completed to resolve [Bug 41412] Restore Default in Managed Build + project's settings Not Working. + * build/org/eclipse/cdt/core/build/managed/tests/ManagedBuildTests.java + 2003-09-09 Hoda Amer Moved three failed tests (bugs #42822, #42823, & #42822B) from FailedCompleteParseASTExpressionTest to CompleteParseASTExpressionTest diff --git a/core/org.eclipse.cdt.core.tests/build/org/eclipse/cdt/core/build/managed/tests/ManagedBuildTests.java b/core/org.eclipse.cdt.core.tests/build/org/eclipse/cdt/core/build/managed/tests/ManagedBuildTests.java index 1f83ecd6458..320a4b72bf4 100644 --- a/core/org.eclipse.cdt.core.tests/build/org/eclipse/cdt/core/build/managed/tests/ManagedBuildTests.java +++ b/core/org.eclipse.cdt.core.tests/build/org/eclipse/cdt/core/build/managed/tests/ManagedBuildTests.java @@ -64,6 +64,7 @@ public class ManagedBuildTests extends TestCase { suite.addTest(new ManagedBuildTests("testExtensions")); suite.addTest(new ManagedBuildTests("testProjectCreation")); suite.addTest(new ManagedBuildTests("testConfigurations")); + suite.addTest(new ManagedBuildTests("testConfigurationReset")); suite.addTest(new ManagedBuildTests("testTargetArtifacts")); suite.addTest(new ManagedBuildTests("testScannerInfoInterface")); suite.addTest(new ManagedBuildTests("cleanup")); @@ -266,6 +267,39 @@ public class ManagedBuildTests extends TestCase { checkOptionReferences(project); } + public void testConfigurationReset() { + // Open the test project + IProject project = null; + try { + project = createProject(projectName); + } catch (CoreException e) { + fail("Failed to open project: " + e.getLocalizedMessage()); + } + + // Get the default configuration + IManagedBuildInfo info = ManagedBuildManager.getBuildInfo(project); + assertNotNull(info); + ITarget defaultTarget = info.getDefaultTarget(); + assertNotNull(defaultTarget); + IConfiguration defaultConfig = info.getDefaultConfiguration(defaultTarget); + assertNotNull(defaultConfig); + + // See if it still contains the overridden values (see testProjectCreation()) + try { + checkRootTarget(defaultTarget, "z"); + } catch (BuildException e1) { + fail("Overridden root target check failed: " + e1.getLocalizedMessage()); + } + + // Reset the config and retest + ManagedBuildManager.resetConfiguration(project, defaultConfig); + try { + checkRootTarget(defaultTarget, "x"); + } catch (BuildException e2) { + fail("Reset root target check failed: " + e2.getLocalizedMessage()); + } + } + /** * @throws CoreException * @throws BuildException diff --git a/core/org.eclipse.cdt.core/ChangeLog b/core/org.eclipse.cdt.core/ChangeLog index 5b3b5df1376..11440cd1411 100644 --- a/core/org.eclipse.cdt.core/ChangeLog +++ b/core/org.eclipse.cdt.core/ChangeLog @@ -1,3 +1,34 @@ +2003-09-10 Sean Evoy + Work completed to resolve [Bug 41412] "Restore Default in Managed Build project's + settings Not Working". The configuration now has a reset method that removes + any user settings and replaces them with the values defined in the plugin + manifest. The Configuration class also has a new, safe accessor for getting + at the defined tool references. Replaced all the checks for null with the accessor. + Added some string constants to the IConfiguration and ITarget interfaces + so manifest element lookup will be easier to maintain should the element names change. + Switched the Target class to use the new string constants during element lookup. + Added back a method in IConfiguration to lookup the parent configuration (which is the + plugin element I need to do the reset). + * build/org/eclipse/cdt/internal/core/build/managed/Configuration.java + * build/org/eclipse/cdt/core/build/managed/IConfiguration.java + * build/org/eclipse/cdt/core/build/managed/ITarget.java + * build/org/eclipse/cdt/core/build/managed/ITool.java + * build/org/eclipse/cdt/internal/core/build/managed/Target.java + + Work to resolve [Bug 42735] "Manage Make will try to generate makefile for Release or + Debug directory". Added a new method to return all the configuration names so + the generator will know that the directory / should be ignored. + * build/org/eclipse/cdt/internal/core/build/managed/ManagedBuildInfo.java + * build/org/eclipse/cdt/core/build/managed/IManagedBuildInfo.java + + Work to partially implement incremental build. New incremental build logic in the + incrementalBuild() method in the GeneratedMakefileBuilder class. It now calls a + specialized method in the makefile generator that calculates and generates the + needed makefiles and fragments. It then calls build if there are any changes worthy + of a build. + * src/org/eclipse/cdt/internal/core/GeneratedMakefileBuilder.java + * src/org/eclipse/cdt/internal/core/MakefileGenerator.java + 2003-09-05 Bogdan Gheorghe Hooked in the dependency checking on file changes in Delta diff --git a/core/org.eclipse.cdt.core/build/org/eclipse/cdt/core/build/managed/IConfiguration.java b/core/org.eclipse.cdt.core/build/org/eclipse/cdt/core/build/managed/IConfiguration.java index 84cf2f187cb..f61c9143137 100644 --- a/core/org.eclipse.cdt.core/build/org/eclipse/cdt/core/build/managed/IConfiguration.java +++ b/core/org.eclipse.cdt.core/build/org/eclipse/cdt/core/build/managed/IConfiguration.java @@ -14,8 +14,9 @@ import org.eclipse.core.resources.IResource; public interface IConfiguration extends IBuildObject { // Schema element names - public static final String TOOL_REF = "toolReference"; - public static final String PARENT = "parent"; + public static final String CONFIGURATION_ELEMENT_NAME = "configuration"; //$NON-NLS-1$ + public static final String TOOL_REF = "toolReference"; //$NON-NLS-1$ + public static final String PARENT = "parent"; //$NON-NLS-1$ /** * Returns the target for this configuration. @@ -30,6 +31,13 @@ public interface IConfiguration extends IBuildObject { */ public IResource getOwner(); + /** + * Answers the configuration that the receiver is based on. + * + * @return + */ + public IConfiguration getParent(); + /** * Returns the tools that are used in this configuration. * diff --git a/core/org.eclipse.cdt.core/build/org/eclipse/cdt/core/build/managed/IManagedBuildInfo.java b/core/org.eclipse.cdt.core/build/org/eclipse/cdt/core/build/managed/IManagedBuildInfo.java index dd3640b0d65..c60e45474e1 100644 --- a/core/org.eclipse.cdt.core/build/org/eclipse/cdt/core/build/managed/IManagedBuildInfo.java +++ b/core/org.eclipse.cdt.core/build/org/eclipse/cdt/core/build/managed/IManagedBuildInfo.java @@ -52,6 +52,14 @@ public interface IManagedBuildInfo { * @return */ public String getConfigurationName(); + + /** + * Answers a String array containing the names of all the configurations + * defined for the project's current target. + * + * @return + */ + public String[] getConfigurationNames(); /** * Get the default configuration associated with the receiver diff --git a/core/org.eclipse.cdt.core/build/org/eclipse/cdt/core/build/managed/ITarget.java b/core/org.eclipse.cdt.core/build/org/eclipse/cdt/core/build/managed/ITarget.java index 163d2d9cc17..d22f5a56109 100644 --- a/core/org.eclipse.cdt.core/build/org/eclipse/cdt/core/build/managed/ITarget.java +++ b/core/org.eclipse.cdt.core/build/org/eclipse/cdt/core/build/managed/ITarget.java @@ -17,6 +17,7 @@ import org.eclipse.core.resources.IResource; * is some type of resource built using a given collection of tools. */ public interface ITarget extends IBuildObject { + public static final String TARGET_ELEMENT_NAME = "target"; //$NON-NLS-1$ /** * Creates a configuration for the target populated with the tools and diff --git a/core/org.eclipse.cdt.core/build/org/eclipse/cdt/core/build/managed/ITool.java b/core/org.eclipse.cdt.core/build/org/eclipse/cdt/core/build/managed/ITool.java index d7002965208..85f0be6c3d6 100644 --- a/core/org.eclipse.cdt.core/build/org/eclipse/cdt/core/build/managed/ITool.java +++ b/core/org.eclipse.cdt.core/build/org/eclipse/cdt/core/build/managed/ITool.java @@ -15,15 +15,16 @@ package org.eclipse.cdt.core.build.managed; */ public interface ITool extends IBuildObject { // Schema element names - public static final String COMMAND = "command"; - public static final String OPTION = "option"; - public static final String OPTION_CAT = "optionCategory"; - public static final String OPTION_REF = "optionReference"; - public static final String OUTPUT_FLAG = "outputFlag"; - public static final String OUTPUT_PREFIX = "outputPrefix"; - public static final String OUTPUTS = "outputs"; - public static final String SOURCES = "sources"; - public static final String WHITE_SPACE = " "; + public static final String TOOL_ELEMENT_NAME = "tool"; //$NON-NLS-1$ + public static final String COMMAND = "command"; //$NON-NLS-1$ + public static final String OPTION = "option"; //$NON-NLS-1$ + public static final String OPTION_CAT = "optionCategory"; //$NON-NLS-1$ + public static final String OPTION_REF = "optionReference"; //$NON-NLS-1$ + public static final String OUTPUT_FLAG = "outputFlag"; //$NON-NLS-1$ + public static final String OUTPUT_PREFIX = "outputPrefix"; //$NON-NLS-1$ + public static final String OUTPUTS = "outputs"; //$NON-NLS-1$ + public static final String SOURCES = "sources"; //$NON-NLS-1$ + public static final String WHITE_SPACE = " "; //$NON-NLS-1$ /** * Return true if the receiver builds files with the diff --git a/core/org.eclipse.cdt.core/build/org/eclipse/cdt/core/build/managed/ManagedBuildManager.java b/core/org.eclipse.cdt.core/build/org/eclipse/cdt/core/build/managed/ManagedBuildManager.java index 89f72cddd68..c99e26dde34 100644 --- a/core/org.eclipse.cdt.core/build/org/eclipse/cdt/core/build/managed/ManagedBuildManager.java +++ b/core/org.eclipse.cdt.core/build/org/eclipse/cdt/core/build/managed/ManagedBuildManager.java @@ -31,6 +31,7 @@ import org.apache.xml.serialize.SerializerFactory; import org.eclipse.cdt.core.AbstractCExtension; import org.eclipse.cdt.core.CCorePlugin; import org.eclipse.cdt.core.parser.*; +import org.eclipse.cdt.internal.core.build.managed.Configuration; import org.eclipse.cdt.internal.core.build.managed.ManagedBuildInfo; import org.eclipse.cdt.internal.core.build.managed.Target; import org.eclipse.core.resources.IFile; @@ -52,11 +53,12 @@ import org.w3c.dom.Node; public class ManagedBuildManager extends AbstractCExtension implements IScannerInfoProvider { private static final QualifiedName buildInfoProperty = new QualifiedName(CCorePlugin.PLUGIN_ID, "managedBuildInfo"); - private static final String ROOT_ELEM_NAME = "ManagedProjectBuildInfo"; - private static final String FILE_NAME = ".cdtbuild"; + private static final String ROOT_ELEM_NAME = "ManagedProjectBuildInfo"; //$NON-NLS-1$ + private static final String FILE_NAME = ".cdtbuild"; //$NON-NLS-1$ private static final ITarget[] emptyTargets = new ITarget[0]; - public static final String INTERFACE_IDENTITY = CCorePlugin.PLUGIN_ID + "." + "ManagedBuildManager"; - + public static final String INTERFACE_IDENTITY = CCorePlugin.PLUGIN_ID + "." + "ManagedBuildManager"; //$NON-NLS-1$ + public static final String EXTENSION_POINT_ID = "ManagedBuildInfo"; //$NON-NLS-1$ + // Targets defined by extensions (i.e., not associated with a resource) private static boolean extensionTargetsLoaded = false; private static List extensionTargets; @@ -311,12 +313,56 @@ public class ManagedBuildManager extends AbstractCExtension implements IScannerI } } + /** + * @param resource + */ public static void removeBuildInfo(IResource resource) { try { resource.setSessionProperty(buildInfoProperty, null); } catch (CoreException e) { } } + + /** + * Resets the build information for the project and configuration specified in the arguments. + * The build information will contain the settings defined in the plugin manifest. + * + * @param project + * @param configuration + */ + public static void resetConfiguration(IProject project, IConfiguration configuration) { + // Make sure the extensions are loaded + loadExtensions(); + + // Find out the parent of the configuration + IConfiguration parentConfig = configuration.getParent(); + // Find the parent target the configuration + ITarget parentTarget = parentConfig.getTarget(); + + // Get the extension point information + IExtensionPoint extensionPoint = CCorePlugin.getDefault().getDescriptor().getExtensionPoint(EXTENSION_POINT_ID); + IExtension[] extensions = extensionPoint.getExtensions(); + for (int i = 0; i < extensions.length; ++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(ITarget.TARGET_ELEMENT_NAME) && + element.getAttribute(ITarget.ID).equals(parentTarget.getId())) { + // We have the parent target so get the definition for the parent config + IConfigurationElement[] targetElements = element.getChildren(); + for (int k = 0; k < targetElements.length; ++k) { + IConfigurationElement targetElement = targetElements[k]; + if (targetElement.getName().equals(IConfiguration.CONFIGURATION_ELEMENT_NAME) && + targetElement.getAttribute(IConfiguration.ID).equals(parentConfig.getId())) { + // We now have the plugin element the target was originally based on + ((Configuration)configuration).reset(targetElement); + } + } + } + } + } + } // Private stuff @@ -356,14 +402,14 @@ public class ManagedBuildManager extends AbstractCExtension implements IScannerI return; extensionTargetsLoaded = true; - IExtensionPoint extensionPoint = CCorePlugin.getDefault().getDescriptor().getExtensionPoint("ManagedBuildInfo"); + IExtensionPoint extensionPoint = CCorePlugin.getDefault().getDescriptor().getExtensionPoint(EXTENSION_POINT_ID); IExtension[] extensions = extensionPoint.getExtensions(); for (int i = 0; i < extensions.length; ++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("target")) { + if (element.getName().equals(ITarget.TARGET_ELEMENT_NAME)) { new Target(element); } } @@ -516,4 +562,5 @@ public class ManagedBuildManager extends AbstractCExtension implements IScannerI map.put(project, list); } } + } diff --git a/core/org.eclipse.cdt.core/build/org/eclipse/cdt/internal/core/build/managed/Configuration.java b/core/org.eclipse.cdt.core/build/org/eclipse/cdt/internal/core/build/managed/Configuration.java index 7ce09b79128..a4ce7cccb18 100644 --- a/core/org.eclipse.cdt.core/build/org/eclipse/cdt/internal/core/build/managed/Configuration.java +++ b/core/org.eclipse.cdt.core/build/org/eclipse/cdt/internal/core/build/managed/Configuration.java @@ -147,13 +147,12 @@ public class Configuration extends BuildObject implements IConfiguration { if (parent != null) element.setAttribute(IConfiguration.PARENT, parent.getId()); - if (toolReferences != null) - for (int i = 0; i < toolReferences.size(); ++i) { - ToolReference toolRef = (ToolReference)toolReferences.get(i); - Element toolRefElement = doc.createElement(IConfiguration.TOOL_REF); - element.appendChild(toolRefElement); - toolRef.serialize(doc, toolRefElement); - } + for (int i = 0; i < getToolReferences().size(); ++i) { + ToolReference toolRef = (ToolReference)getToolReferences().get(i); + Element toolRefElement = doc.createElement(IConfiguration.TOOL_REF); + element.appendChild(toolRefElement); + toolRef.serialize(doc, toolRefElement); + } } /* (non-Javadoc) @@ -163,6 +162,16 @@ public class Configuration extends BuildObject implements IConfiguration { return (name == null && parent != null) ? parent.getName() : name; } + /* + * @return + */ + private List getToolReferences() { + if (toolReferences == null) { + toolReferences = new ArrayList(); + } + return toolReferences; + } + /* (non-Javadoc) * @see org.eclipse.cdt.core.build.managed.IConfiguration#getTools() */ @@ -181,6 +190,21 @@ public class Configuration extends BuildObject implements IConfiguration { return tools; } + /** + * @param targetElement + */ + public void reset(IConfigurationElement element) { + // I just need to reset the tool references + getToolReferences().clear(); + IConfigurationElement[] configElements = element.getChildren(); + for (int l = 0; l < configElements.length; ++l) { + IConfigurationElement configElement = configElements[l]; + if (configElement.getName().equals(IConfiguration.TOOL_REF)) { + new ToolReference(this, configElement); + } + } + } + /* (non-Javadoc) * @see org.eclipse.cdt.core.build.managed.IConfiguration#getParent() */ @@ -209,19 +233,16 @@ public class Configuration extends BuildObject implements IConfiguration { * @return */ private ToolReference getToolReference(ITool tool) { - if (toolReferences != null) - for (int i = 0; i < toolReferences.size(); ++i) { - ToolReference toolRef = (ToolReference)toolReferences.get(i); - if (toolRef.references(tool)) - return toolRef; - } + for (int i = 0; i < getToolReferences().size(); ++i) { + ToolReference toolRef = (ToolReference)getToolReferences().get(i); + if (toolRef.references(tool)) + return toolRef; + } return null; } public void addToolReference(ToolReference toolRef) { - if (toolReferences == null) - toolReferences = new ArrayList(); - toolReferences.add(toolRef); + getToolReferences().add(toolRef); } public OptionReference createOptionReference(IOption option) { @@ -293,4 +314,6 @@ public class Configuration extends BuildObject implements IConfiguration { if(!Arrays.equals(value, oldValue)) createOptionReference(option).setValue(value); } + + } diff --git a/core/org.eclipse.cdt.core/build/org/eclipse/cdt/internal/core/build/managed/ManagedBuildInfo.java b/core/org.eclipse.cdt.core/build/org/eclipse/cdt/internal/core/build/managed/ManagedBuildInfo.java index 66a70cff94a..382a65e3c62 100644 --- a/core/org.eclipse.cdt.core/build/org/eclipse/cdt/internal/core/build/managed/ManagedBuildInfo.java +++ b/core/org.eclipse.cdt.core/build/org/eclipse/cdt/internal/core/build/managed/ManagedBuildInfo.java @@ -133,6 +133,19 @@ public class ManagedBuildInfo implements IManagedBuildInfo, IScannerInfo { return config == null ? new String() : config.getName(); } + /* (non-Javadoc) + * @see org.eclipse.cdt.core.build.managed.IManagedBuildInfo#getConfigurationNames() + */ + public String[] getConfigurationNames() { + ArrayList configNames = new ArrayList(); + IConfiguration[] configs = getDefaultTarget().getConfigurations(); + for (int i = 0; i < configs.length; i++) { + IConfiguration configuration = configs[i]; + configNames.add(configuration.getName()); + } + return (String[])configNames.toArray(new String[configNames.size()]); + } + /* (non-Javadoc) * @see org.eclipse.cdt.core.build.managed.IManagedBuildInfo#getDefaultConfiguration() */ diff --git a/core/org.eclipse.cdt.core/build/org/eclipse/cdt/internal/core/build/managed/Target.java b/core/org.eclipse.cdt.core/build/org/eclipse/cdt/internal/core/build/managed/Target.java index 4c13d741c83..520242ef36a 100644 --- a/core/org.eclipse.cdt.core/build/org/eclipse/cdt/internal/core/build/managed/Target.java +++ b/core/org.eclipse.cdt.core/build/org/eclipse/cdt/internal/core/build/managed/Target.java @@ -132,9 +132,9 @@ public class Target extends BuildObject implements ITarget { IConfigurationElement[] targetElements = element.getChildren(); for (int k = 0; k < targetElements.length; ++k) { IConfigurationElement targetElement = targetElements[k]; - if (targetElement.getName().equals("tool")) { + if (targetElement.getName().equals(ITool.TOOL_ELEMENT_NAME)) { new Tool(this, targetElement); - } else if (targetElement.getName().equals("configuration")) { + } else if (targetElement.getName().equals(IConfiguration.CONFIGURATION_ELEMENT_NAME)) { new Configuration(this, targetElement); } } @@ -186,7 +186,7 @@ public class Target extends BuildObject implements ITarget { Node child = element.getFirstChild(); while (child != null) { - if (child.getNodeName().equals("configuration")) { + if (child.getNodeName().equals(IConfiguration.CONFIGURATION_ELEMENT_NAME)) { new Configuration(this, (Element)child); } child = child.getNextSibling(); diff --git a/core/org.eclipse.cdt.core/src/org/eclipse/cdt/internal/core/GeneratedMakefileBuilder.java b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/internal/core/GeneratedMakefileBuilder.java index 0f1dea7e89b..efa4accea72 100644 --- a/core/org.eclipse.cdt.core/src/org/eclipse/cdt/internal/core/GeneratedMakefileBuilder.java +++ b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/internal/core/GeneratedMakefileBuilder.java @@ -64,18 +64,21 @@ public class GeneratedMakefileBuilder extends ACBuilder { public class ResourceDeltaVisitor implements IResourceDeltaVisitor { - boolean bContinue; + private boolean buildNeeded = false; public boolean visit(IResourceDelta delta) throws CoreException { IResource resource = delta.getResource(); + // If the project has changed, then a build is needed and we can stop if (resource != null && resource.getProject() == getProject()) { - bContinue = true; + buildNeeded = true; return false; } + return true; } + public boolean shouldBuild() { - return bContinue; + return buildNeeded; } } @@ -255,10 +258,27 @@ public class GeneratedMakefileBuilder extends ACBuilder { } statusMsg = CCorePlugin.getFormattedString(INCREMENTAL, currentProject.getName()); monitor.subTask(statusMsg); - + + // Ask the makefile generator to generate any makefiles needed to build delta IManagedBuildInfo info = ManagedBuildManager.getBuildInfo(getProject()); - IPath buildDir = new Path(info.getConfigurationName()); - invokeMake(false, buildDir, info, monitor); + MakefileGenerator generator = new MakefileGenerator(currentProject, info, monitor); + try { + generator.generateMakefiles(delta); + } catch (CoreException e) { + if (e.getStatus().getCode() == GeneratedMakefileBuilder.EMPTY_PROJECT_BUILD_ERROR) { + // There is nothing to build so bail + monitor.worked(1); + return; + } else { + throw e; + } + } + + // Run the build if there is any relevant change + if (generator.shouldRunBuild()) { + IPath buildDir = new Path(info.getConfigurationName()); + invokeMake(false, buildDir, info, monitor); + } monitor.worked(1); } diff --git a/core/org.eclipse.cdt.core/src/org/eclipse/cdt/internal/core/MakefileGenerator.java b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/internal/core/MakefileGenerator.java index 7a855792bd4..74269e995d6 100644 --- a/core/org.eclipse.cdt.core/src/org/eclipse/cdt/internal/core/MakefileGenerator.java +++ b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/internal/core/MakefileGenerator.java @@ -29,6 +29,8 @@ import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IFolder; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IResource; +import org.eclipse.core.resources.IResourceDelta; +import org.eclipse.core.resources.IResourceDeltaVisitor; import org.eclipse.core.resources.IResourceProxy; import org.eclipse.core.resources.IResourceProxyVisitor; import org.eclipse.core.resources.IResourceStatus; @@ -69,11 +71,13 @@ public class MakefileGenerator { // Local variables needed by generator protected IManagedBuildInfo info; - protected List moduleList; + protected List modifiedList; protected IProgressMonitor monitor; + protected List subdirList; protected IProject project; protected List ruleList; protected IPath topBuildDir; + protected boolean shouldRunBuild; /** * This class is used to recursively walk the project and determine which @@ -107,7 +111,9 @@ public class MakefileGenerator { IResource resource = proxy.requestResource(); String ext = resource.getFileExtension(); if (info.buildsFileType(ext)) { - generator.appendModule(resource); + if (!generator.isGeneratedResource(resource)) { + generator.appendBuildSubdirectory(resource); + } } return false; } @@ -118,6 +124,77 @@ public class MakefileGenerator { } + public class ResourceDeltaVisitor implements IResourceDeltaVisitor { + private MakefileGenerator generator; + private IManagedBuildInfo info; + + /** + * + */ + public ResourceDeltaVisitor(MakefileGenerator generator, IManagedBuildInfo info) { + this.generator = generator; + this.info = info; + } + + /* (non-Javadoc) + * @see org.eclipse.core.resources.IResourceDeltaVisitor#visit(org.eclipse.core.resources.IResourceDelta) + */ + public boolean visit(IResourceDelta delta) throws CoreException { + // Should the visitor keep iterating in current directory + boolean keepLooking = false; + IResource resource = delta.getResource(); + + // What kind of resource change has occurred + if (resource.getType() == IResource.FILE) { + String ext = resource.getFileExtension(); + switch (delta.getKind()) { + case IResourceDelta.ADDED: + case IResourceDelta.REMOVED: + // Add the container of the resource and any resources that depend on it + if (info.buildsFileType(ext)) { + if (!generator.isGeneratedResource(resource)) { + // Here's the container + generator.appendModifiedSubdirectory(resource); + // and all the dependents + DependencyManager depMgr = CCorePlugin.getDefault().getCoreModel().getDependencyManager(); + List deps = depMgr.getProjectDependsForFile(resource.getLocation().toOSString()); + if (deps != null) { + ListIterator iter = deps.listIterator(); + while (iter.hasNext()) { + generator.appendModifiedSubdirectory(resource); + } + } + // A build should run + generator.shouldRunBuild(true); + } + } + break; + case IResourceDelta.CHANGED: + if (info.buildsFileType(ext)) { + switch (delta.getFlags()) { + case IResourceDelta.CONTENT: + // If the contents changed then just do a build + generator.shouldRunBuild(true); + keepLooking = true; + default: + keepLooking = true; + } + } + break; + default: + keepLooking = true; + break; + } + } else { + // If the resource is part of the generated directory structure don't recurse + if (!generator.isGeneratedResource(resource)) { + keepLooking = true; + } + } + return keepLooking; + } + } + public MakefileGenerator(IProject project, IManagedBuildInfo info, IProgressMonitor monitor) { super(); // Save the project so we can get path and member information @@ -126,9 +203,12 @@ public class MakefileGenerator { this.monitor = monitor; // Get the build info for the project this.info = info; + // By default a build never runs + shouldRunBuild = false; } - /** + /* (non-javadoc) + * * @param module * @return */ @@ -184,7 +264,7 @@ public class MakefileGenerator { return buffer; } - /** + /* (non-javadoc) * @param buffer * @param info */ @@ -202,13 +282,13 @@ public class MakefileGenerator { buffer.append("C_SRCS := " + NEWLINE); buffer.append("CC_SRCS := " + NEWLINE + NEWLINE); - // Add the libraries this project dependes on + // Add the libraries this project depends on buffer.append("LIBS := "); buffer.append(NEWLINE + NEWLINE); return buffer; } - /** + /* (non-javadoc) * @return */ protected StringBuffer addModules() { @@ -216,16 +296,21 @@ public class MakefileGenerator { // Add the comment buffer.append(CCorePlugin.getResourceString(MOD_LIST) + NEWLINE); buffer.append("MODULES := " + LINEBREAK + NEWLINE); - buffer.append("." + LINEBREAK + NEWLINE); // Get all the module names - ListIterator iter = getModuleList().listIterator(); + ListIterator iter = getSubdirList().listIterator(); while (iter.hasNext()) { IContainer container = (IContainer) iter.next(); - IPath path = container.getProjectRelativePath(); - buffer.append(path.toString() + WHITESPACE + LINEBREAK + NEWLINE); + // Check the special case where the module is the project root + if (container.getFullPath() == project.getFullPath()) { + buffer.append("." + WHITESPACE + LINEBREAK + NEWLINE); + } else { + IPath path = container.getProjectRelativePath(); + buffer.append(path.toString() + WHITESPACE + LINEBREAK + NEWLINE); + } } + // Now add the makefile instruction to include all the subdirectory makefile fragments buffer.append(NEWLINE); buffer.append(CCorePlugin.getResourceString(MOD_INCL) + NEWLINE); buffer.append("include ${patsubst %, %/module.mk, $(MODULES)}" + NEWLINE); @@ -235,7 +320,7 @@ public class MakefileGenerator { } - /** + /* (non-javadoc) * Answers a StringBuffer containing all of the sources contributed by * a container to the build. * @param module @@ -282,7 +367,7 @@ public class MakefileGenerator { return buffer; } - /** + /* (non-javadoc) * Answers a StrinBuffer containing all of the required targets to * properly build the project. */ @@ -398,26 +483,36 @@ public class MakefileGenerator { } /** + * Adds the container of the argument to the list of folders in the project that + * contribute source files to the build. The resource visitor has already established + * that the build model knows how to build the files. It has also checked that + * the resouce is not generated as part of the build. + * * @param resource */ - public void appendModule(IResource resource) { - // The build model knows how to build this file + public void appendBuildSubdirectory(IResource resource) { IContainer container = resource.getParent(); - - // But is this a generated directory ... - IPath root = new Path(info.getConfigurationName()); - IPath path = container.getProjectRelativePath(); - if (root.isPrefixOf(path)) { - return; + if (!getSubdirList().contains(container)) { + getSubdirList().add(container); } - - if (!getModuleList().contains(container)) { - getModuleList().add(container); + } + + /** + * Adds the container of the argument to a list of subdirectories that are part + * of an incremental rebuild of the project. The makefile fragments for these + * directories will be regenerated as a result of the build. + * + * @param resource + */ + public void appendModifiedSubdirectory(IResource resource) { + IContainer container = resource.getParent(); + if (!getModifiedList().contains(container)) { + getModifiedList().add(container); } } /** - * Check whether the build has been canceled. Cancellation requests + * Check whether the build has been cancelled. Cancellation requests * propagated to the caller by throwing OperationCanceledException. * * @see org.eclipse.core.runtime.OperationCanceledException#OperationCanceledException() @@ -428,17 +523,93 @@ public class MakefileGenerator { } } + /** - * @return + * Clients call this method when an incremental rebuild is required. The argument + * contains a set of resource deltas that will be used to determine which + * subdirectories need a new makefile and dependency list (if any). + * + * @param delta + * @throws CoreException */ - private List getModuleList() { - if (moduleList == null) { - moduleList = new ArrayList(); + public void generateMakefiles(IResourceDelta delta) throws CoreException { + /* + * Let's do a sanity check right now. This is an incremental build, so if the top-level directory is not there, then + * a rebuild is needed anyway. + */ + IFolder folder = project.getFolder(info.getConfigurationName()); + if (!folder.exists()) { + regenerateMakefiles(); + shouldRunBuild(true); + return; + } + + // Visit the resources in the delta and compile a list of subdirectories to regenerate + ResourceDeltaVisitor visitor = new ResourceDeltaVisitor(this, info); + delta.accept(visitor); + // There may be nothing to regenerate and no content changes that require a rebuild + if (getModifiedList().isEmpty() && !shouldRunBuild()) { + // There is nothing to build + IStatus status = new Status(IStatus.INFO, CCorePlugin.PLUGIN_ID, GeneratedMakefileBuilder.EMPTY_PROJECT_BUILD_ERROR, "", null); + throw new CoreException(status); + } + + // See if the user has cancelled the build + checkCancel(); + + // The top-level makefile needs this information + ResourceProxyVisitor resourceVisitor = new ResourceProxyVisitor(this, info); + project.accept(resourceVisitor, IResource.NONE); + if (getSubdirList().isEmpty()) { + // There is nothing to build (but we should never throw this exception) + IStatus status = new Status(IStatus.INFO, CCorePlugin.PLUGIN_ID, GeneratedMakefileBuilder.EMPTY_PROJECT_BUILD_ERROR, "", null); + throw new CoreException(status); + } + checkCancel(); + + // Regenerate any fragments that are missing for the exisiting directories NOT modified + Iterator iter = getSubdirList().listIterator(); + while (iter.hasNext()) { + IContainer subdirectory = (IContainer)iter.next(); + if (!getModifiedList().contains(subdirectory)) { + // Make sure a fragment makefile and dependency file exist + IFile makeFragment = project.getFile(subdirectory.getFullPath().addTrailingSeparator().append(MODFILE_NAME)); + IFile depFragment = project.getFile(subdirectory.getFullPath().addTrailingSeparator().append(DEPFILE_NAME)); + if (!makeFragment.exists() || !depFragment.exists()) { + // If one or both are missing, then add it to the list to be generated + getModifiedList().add(subdirectory); + } + } + } + + // Re-create the top-level makefile + topBuildDir = createDirectory(info.getConfigurationName()); + IPath makefilePath = topBuildDir.addTrailingSeparator().append(MAKEFILE_NAME); + IFile makefileHandle = createFile(makefilePath); + populateTopMakefile(makefileHandle); + checkCancel(); + + // Regenerate any fragments for modified directories + iter = getModifiedList().listIterator(); + while (iter.hasNext()) { + populateFragmentMakefile((IContainer) iter.next()); + checkCancel(); } - return moduleList; } - /** + /* (non-javadoc) + * @return + */ + private List getModifiedList() { + if (modifiedList == null) { + modifiedList = new ArrayList(); + } + return modifiedList; + } + + /* (non-javadoc) + * Answers the list of known build rules. This keeps me from generating duplicate + * rules for known file extensions. * */ private List getRuleList() { @@ -448,7 +619,18 @@ public class MakefileGenerator { return ruleList; } - /** + /* (non-javadoc) + * Answers the list of subdirectories contributing source code to the build + * @return + */ + private List getSubdirList() { + if (subdirList == null) { + subdirList = new ArrayList(); + } + return subdirList; + } + + /* (non-javadoc) * @param string * @return */ @@ -481,7 +663,7 @@ public class MakefileGenerator { return folder.getFullPath(); } - /** + /* (non-javadoc) * @param makefilePath * @param monitor * @return @@ -505,7 +687,7 @@ public class MakefileGenerator { else throw e; } - // TODO handle long running file operation + return newFile; } @@ -520,13 +702,32 @@ public class MakefileGenerator { } /** + * Answers true if the argument is found in a generated container + * @param resource + * @return + */ + public boolean isGeneratedResource(IResource resource) { + // Is this a generated directory ... + IPath path = resource.getProjectRelativePath(); + String[] configNames = info.getConfigurationNames(); + for (int i = 0; i < configNames.length; i++) { + String name = configNames[i]; + IPath root = new Path(name); + // It is if it is a root of the resource pathname + if (root.isPrefixOf(path)) return true; + } + + return false; + } + + /* (non-javadoc) * Create the entire contents of the makefile. * * @param fileHandle The file to place the contents in. * @param info * @param monitor */ - protected void populateMakefile(IFile fileHandle) { + protected void populateTopMakefile(IFile fileHandle) { StringBuffer buffer = new StringBuffer(); // Add the macro definitions @@ -541,16 +742,16 @@ public class MakefileGenerator { // Save the file try { Util.save(buffer, fileHandle); - } catch (CoreException e1) { + } catch (CoreException e) { // TODO Auto-generated catch block - e1.printStackTrace(); + e.printStackTrace(); } } - /** + /* (non-javadoc) * @param module */ - protected void populateModMakefile(IContainer module) throws CoreException { + protected void populateFragmentMakefile(IContainer module) throws CoreException { // Calcualte the new directory relative to the build output IPath moduleRelativePath = module.getProjectRelativePath(); IPath buildRoot = getTopBuildDir().removeFirstSegments(1); @@ -578,11 +779,14 @@ public class MakefileGenerator { } + /** + * @throws CoreException + */ public void regenerateMakefiles() throws CoreException { // Visit the resources in the project ResourceProxyVisitor visitor = new ResourceProxyVisitor(this, info); project.accept(visitor, IResource.NONE); - if (getModuleList().isEmpty()) { + if (getSubdirList().isEmpty()) { // There is nothing to build IStatus status = new Status(IStatus.INFO, CCorePlugin.PLUGIN_ID, GeneratedMakefileBuilder.EMPTY_PROJECT_BUILD_ERROR, "", null); throw new CoreException(status); @@ -599,15 +803,33 @@ public class MakefileGenerator { IFile makefileHandle = createFile(makefilePath); // Populate the makefile - populateMakefile(makefileHandle); + populateTopMakefile(makefileHandle); checkCancel(); // Now populate the module makefiles - ListIterator iter = getModuleList().listIterator(); + ListIterator iter = getSubdirList().listIterator(); while (iter.hasNext()) { - populateModMakefile((IContainer)iter.next()); + populateFragmentMakefile((IContainer)iter.next()); checkCancel(); } } + /** + * Answers whether a build is required after the makefiles have been + * generated. + * + * @return + */ + public boolean shouldRunBuild() { + return shouldRunBuild; + } + + /** + * Sets the build flag to the value of the argument. + * + * @param b + */ + public void shouldRunBuild(boolean b) { + shouldRunBuild = b; + } } diff --git a/core/org.eclipse.cdt.ui/ChangeLog b/core/org.eclipse.cdt.ui/ChangeLog index 175ec9c6710..3e7fa4b779e 100644 --- a/core/org.eclipse.cdt.ui/ChangeLog +++ b/core/org.eclipse.cdt.ui/ChangeLog @@ -1,3 +1,11 @@ +2003-09-10 Sean Evoy + Work completed to resolve [Bug 41412] Restore Default in Managed Build + project's settings Not Working. Added an event handler to reset the selected + configuration settings back to the defaults defined in the plugin manifest. + Work to resolve [Bug 42736] New: C/C++ Build Settings not remembering Configuration. + Used the managed build info to get the current config for the target. + * build/org/eclipse/cdt/ui/build/properties/BuildPropertyPage.java + 2003-09-08 Bogdan Gheorghe - Changed search pop up menu in CEditor and CContentOutlinePage diff --git a/core/org.eclipse.cdt.ui/build/org/eclipse/cdt/ui/build/properties/BuildPropertyPage.java b/core/org.eclipse.cdt.ui/build/org/eclipse/cdt/ui/build/properties/BuildPropertyPage.java index 99fe281ee6f..ff1472a2485 100644 --- a/core/org.eclipse.cdt.ui/build/org/eclipse/cdt/ui/build/properties/BuildPropertyPage.java +++ b/core/org.eclipse.cdt.ui/build/org/eclipse/cdt/ui/build/properties/BuildPropertyPage.java @@ -18,6 +18,7 @@ import java.util.ListIterator; import java.util.Map; import org.eclipse.cdt.core.build.managed.IConfiguration; +import org.eclipse.cdt.core.build.managed.IManagedBuildInfo; import org.eclipse.cdt.core.build.managed.IOptionCategory; import org.eclipse.cdt.core.build.managed.ITarget; import org.eclipse.cdt.core.build.managed.ManagedBuildManager; @@ -276,7 +277,7 @@ public class BuildPropertyPage extends PropertyPage implements IWorkbenchPropert */ private void displayOptionsForCategory(IOptionCategory category) { // Do nothing if the selected category is is unchanged - if (selectedCategory == category) { + if (category == selectedCategory) { return; } selectedCategory = category; @@ -451,13 +452,38 @@ public class BuildPropertyPage extends PropertyPage implements IWorkbenchPropert populateConfigurations(); } - /** + /* + * (non-javadoc) * Initialize the relative weights (widths) of the 2 sides of the sash. */ protected void initializeSashForm() { sashForm.setWeights(DEFAULT_SASH_WEIGHTS); } + /* + * (non-Javadoc) + * @see org.eclipse.jface.preference.PreferencePage#performDefaults() + */ + protected void performDefaults() { + // Empty the page list + List pages = getPagesForConfig(); + pages.clear(); + + // Get the build manager to reset build info for project + ManagedBuildManager.resetConfiguration(getProject(), getSelectedConfiguration()); + + // Recreate the settings store for the configuration + settingsStore = new BuildToolsSettingsStore(getSelectedConfiguration()); + + // Reset the category selection and run selection event handler + selectedCategory = null; + handleOptionSelection(); + } + + /* + * (non-Javadoc) + * @see org.eclipse.jface.preference.IPreferencePage#performOk() + */ public boolean performOk() { // Force each settings page to update List pages = getPagesForConfig(); @@ -485,7 +511,10 @@ public class BuildPropertyPage extends PropertyPage implements IWorkbenchPropert configSelector.setItems(getConfigurationNames()); // Make sure the active configuration is selected - configSelector.select(0); + IManagedBuildInfo info = ManagedBuildManager.getBuildInfo(getProject()); + IConfiguration defaultConfig = info.getDefaultConfiguration(selectedTarget); + int index = configSelector.indexOf(defaultConfig.getName()); + configSelector.select(index == -1 ? 0 : index); handleConfigSelection(); }