Skip to main content
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDoug Schaefer2003-09-30 02:14:44 +0000
committerDoug Schaefer2003-09-30 02:14:44 +0000
commit9fa37457aedc2c850545a313a52db269bac0777e (patch)
tree36c267d3c5afbe8577f943713159a938bdc80c90
parent7fab73d44fbd7ca8bc880c74e371bd25547636c7 (diff)
downloadorg.eclipse.cdt-9fa37457aedc2c850545a313a52db269bac0777e.tar.gz
org.eclipse.cdt-9fa37457aedc2c850545a313a52db269bac0777e.tar.xz
org.eclipse.cdt-9fa37457aedc2c850545a313a52db269bac0777e.zip
Patch for Sean Evoy:
I have documented the patch in the change log; the only bonus is that it fixes 43214 for free. The managed builder should now respond correctly to deletions of any types of file in the project (or referenced projects). This includes makefiles, intermediate files, and the build target. It should also properly handle changes in the project settings in any referenced project. Referenced projects should now get their project views refreshed as a result of any changes.
-rw-r--r--build/org.eclipse.cdt.managedbuilder.core/ChangeLog36
-rw-r--r--build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/core/GeneratedMakefileBuilder.java96
-rw-r--r--build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/core/MakefileGenerator.java99
3 files changed, 120 insertions, 111 deletions
diff --git a/build/org.eclipse.cdt.managedbuilder.core/ChangeLog b/build/org.eclipse.cdt.managedbuilder.core/ChangeLog
index 8b80491cb2b..7085a3aadc4 100644
--- a/build/org.eclipse.cdt.managedbuilder.core/ChangeLog
+++ b/build/org.eclipse.cdt.managedbuilder.core/ChangeLog
@@ -1,4 +1,40 @@
2003-09-26 Sean Evoy
+ A partial implementation for bug 41826. This patch contains the logic to properly
+ respond in the face of the following project changes:
+
+ 1. A generated project element, such as the build target or an intermediate file,
+ is deleted in the build project, or any projects it references.
+ 2. The build settings change in the build project or any projects it
+ references.
+
+ In order to actually do this correctly, I had to stop being so precious during the
+ build. The makefile generator was was calculating the "build needed" state as it
+ walked the change delta. However, the Eclipse core has already determined that I
+ need to do a build. Further, as I discovered earlier, it doesn't always pass what
+ has changed in referenced projects as part of the delta. Essentially, that means I
+ will never be able to fully calculate the change set in the makefile generator's
+ delta visitor, and to even approximate a decent set of cases, the logic would quickly
+ bog down in complexity.
+
+ The solution is to trust Eclipse and alway invoke make when my incremental builder
+ is called. At worst, if there is no significant change, make will execute and
+ report nothing to be done.
+
+ The modified makefile builder no longer asks the makefile generator if it should
+ build. It also no longer cares if the change set is empty (make will report that).
+ Since it responds to changes in referenced project's build information, it also
+ scrubs all relevant projects after building. Since a build might involve building
+ referenced project elements, those projects get their project views refreshed after
+ build. The build markers for referenced projects are removed prior to build.
+ * src/org/eclipse/cdt/managedbuilder/internal/core/GeneratedMakefileBuilder.java
+
+ The makefile generator has been simplified. The resource delta visitor logic no
+ longer trie to decide if a build should occur. The method to ask has been removed.
+ The class no longer throws an exception if the change set is empty. I am also a bit
+ more careful to call make with the right targets if a referenced project is built.
+ * src/org/eclipse/cdt/managedbuilder/internal/core/MakefileGenerator.java
+
+2003-09-26 Sean Evoy
I added a fix to the builder and makefile generator to properly handle the following case.
Project A depends on Project B. Something changes in project B and the user requests
that A be built. Inthis case, the incremental builder is invoked, but it is passed a
diff --git a/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/core/GeneratedMakefileBuilder.java b/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/core/GeneratedMakefileBuilder.java
index 3b45d2b72f2..5b8ed071467 100644
--- a/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/core/GeneratedMakefileBuilder.java
+++ b/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/core/GeneratedMakefileBuilder.java
@@ -58,9 +58,6 @@ public class GeneratedMakefileBuilder extends ACBuilder {
private static final String REFRESH = MESSAGE + ".updating"; //$NON-NLS-1$
private static final String MARKERS = MESSAGE + ".creating.markers"; //$NON-NLS-1$
- // Status codes
- public static final int EMPTY_PROJECT_BUILD_ERROR = 1;
-
// Local variables
protected List resourcesToBuild;
protected List ruleList;
@@ -89,7 +86,6 @@ public class GeneratedMakefileBuilder extends ACBuilder {
*
*/
public GeneratedMakefileBuilder() {
-
}
/* (non-Javadoc)
@@ -100,7 +96,8 @@ public class GeneratedMakefileBuilder extends ACBuilder {
if (statusMsg != null) {
monitor.subTask(statusMsg);
}
-
+
+ // Get the build information
IManagedBuildInfo info = ManagedBuildManager.getBuildInfo(getProject());
if (kind == IncrementalProjectBuilder.FULL_BUILD || info.isDirty()) {
@@ -123,10 +120,18 @@ public class GeneratedMakefileBuilder extends ACBuilder {
}
}
}
+
+ // Scrub the build info of all the projects participating in the build
info.setDirty(false);
+ IProject[] deps = getProject().getReferencedProjects();
+ for (int i = 0; i < deps.length; i++) {
+ IProject project = deps[i];
+ IManagedBuildInfo depInfo = ManagedBuildManager.getBuildInfo(project);
+ depInfo.setDirty(false);
+ }
// Ask build mechanism to compute deltas for project dependencies next time
- return getProject().getReferencedProjects();
+ return deps;
}
/**
@@ -150,15 +155,8 @@ public class GeneratedMakefileBuilder extends ACBuilder {
monitor = new NullProgressMonitor();
}
- // We also need one of these ...
- IProject currentProject = getProject();
- if (currentProject == null) {
- // Flag some sort of error and bail
- return;
- }
-
// Regenerate the makefiles for any managed projects this project depends on
- IProject[] deps = currentProject.getReferencedProjects();
+ IProject[] deps = getProject().getReferencedProjects();
for (int i = 0; i < deps.length; i++) {
IProject depProject = deps[i];
if (ManagedBuildManager.manages(depProject)) {
@@ -167,32 +165,23 @@ public class GeneratedMakefileBuilder extends ACBuilder {
try {
generator.regenerateMakefiles();
} catch (CoreException e) {
- // This may be an empty project exception
- if (e.getStatus().getCode() == GeneratedMakefileBuilder.EMPTY_PROJECT_BUILD_ERROR) {
- // Just keep looking for other projects
- continue;
- } else {
- // Throw the exception back to the builder
- throw e;
- }
+ // Throw the exception back to the builder
+ throw e;
}
}
}
// Need to report status to the user
- String statusMsg = ManagedBuilderCorePlugin.getFormattedString(REBUILD, currentProject.getName());
+ String statusMsg = ManagedBuilderCorePlugin.getFormattedString(REBUILD, getProject().getName());
monitor.subTask(statusMsg);
// Regenerate the makefiles for this project
- MakefileGenerator generator = new MakefileGenerator(currentProject, info, monitor);
+ MakefileGenerator generator = new MakefileGenerator(getProject(), info, monitor);
try {
generator.regenerateMakefiles();
} catch (CoreException e) {
- // See if this is an empty project
- if (e.getStatus().getCode() == GeneratedMakefileBuilder.EMPTY_PROJECT_BUILD_ERROR) {
- monitor.worked(1);
- return;
- }
+ // Throw the exception back to the builder
+ throw e;
}
IPath topBuildDir = generator.getTopBuildDir();
@@ -254,35 +243,43 @@ public class GeneratedMakefileBuilder extends ACBuilder {
*/
protected void incrementalBuild(IResourceDelta delta, IManagedBuildInfo info, IProgressMonitor monitor) throws CoreException {
// Rebuild the resource tree in the delta
- IProject currentProject = getProject();
String statusMsg = null;
// Need to report status to the user
if (monitor == null) {
monitor = new NullProgressMonitor();
}
- statusMsg = ManagedBuilderCorePlugin.getFormattedString(INCREMENTAL, currentProject.getName());
+ statusMsg = ManagedBuilderCorePlugin.getFormattedString(INCREMENTAL, getProject().getName());
monitor.subTask(statusMsg);
+ // Regenerate the makefiles for any managed projects this project depends on
+ IProject[] deps = getProject().getReferencedProjects();
+ for (int i = 0; i < deps.length; i++) {
+ IProject depProject = deps[i];
+ if (ManagedBuildManager.manages(depProject)) {
+ IManagedBuildInfo depInfo = ManagedBuildManager.getBuildInfo(depProject);
+ MakefileGenerator generator = new MakefileGenerator(depProject, depInfo, monitor);
+ try {
+ generator.regenerateMakefiles();
+ } catch (CoreException e) {
+ // Throw the exception back to the builder
+ throw e;
+ }
+ }
+ }
+
// Ask the makefile generator to generate any makefiles needed to build delta
- MakefileGenerator generator = new MakefileGenerator(currentProject, info, monitor);
+ MakefileGenerator generator = new MakefileGenerator(getProject(), 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;
- }
+ // Throw the exception back to the builder
+ 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);
- }
+ // Run the build
+ IPath buildDir = new Path(info.getConfigurationName());
+ invokeMake(false, buildDir, info, monitor);
monitor.worked(1);
}
@@ -310,6 +307,11 @@ public class GeneratedMakefileBuilder extends ACBuilder {
// Remove all markers for this project
removeAllMarkers(currentProject);
+ IProject[] deps = currentProject.getReferencedProjects();
+ for (int i = 0; i < deps.length; i++) {
+ IProject project = deps[i];
+ removeAllMarkers(project);
+ }
IPath workingDirectory = getWorkingDirectory().append(buildDir);
@@ -361,12 +363,16 @@ public class GeneratedMakefileBuilder extends ACBuilder {
errMsg = launcher.getErrorMessage();
}
- // Force a resync of the project without allowing the user to cancel.
+ // Force a resync of the projects without allowing the user to cancel.
// This is probably unkind, but short of this there is no way to insure
// the UI is up-to-date with the build results
monitor.subTask(ManagedBuilderCorePlugin.getResourceString(REFRESH));
try {
currentProject.refreshLocal(IResource.DEPTH_INFINITE, null);
+ for (int j = 0; j < deps.length; ++j) {
+ IProject project = deps[j];
+ project.refreshLocal(IResource.DEPTH_INFINITE, null);
+ }
} catch (CoreException e) {
monitor.subTask(ManagedBuilderCorePlugin.getResourceString(REFRESH_ERROR));
}
diff --git a/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/core/MakefileGenerator.java b/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/core/MakefileGenerator.java
index 19db6c8247b..14659171fab 100644
--- a/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/core/MakefileGenerator.java
+++ b/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/core/MakefileGenerator.java
@@ -44,10 +44,8 @@ import org.eclipse.core.resources.IWorkspaceRoot;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
-import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.OperationCanceledException;
import org.eclipse.core.runtime.Path;
-import org.eclipse.core.runtime.Status;
public class MakefileGenerator {
// String constants for messages
@@ -83,7 +81,6 @@ public class MakefileGenerator {
protected IProject project;
protected List ruleList;
protected IPath topBuildDir;
- protected boolean shouldRunBuild;
private String target;
@@ -184,21 +181,12 @@ public class MakefileGenerator {
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;
- }
+ keepLooking = true;
}
break;
default:
@@ -208,9 +196,7 @@ public class MakefileGenerator {
} if (resource.getType() == IResource.PROJECT) {
// If there is a zero-length delta, something the project depends on has changed so just call make
IResourceDelta[] children = delta.getAffectedChildren();
- if (children != null && children.length == 0) {
- generator.shouldRunBuild(true);
- } else {
+ if (children != null && children.length > 0) {
keepLooking = true;
}
} else {
@@ -237,8 +223,6 @@ public class MakefileGenerator {
this.monitor = monitor;
// Get the build info for the project
this.info = info;
- // By default a build never runs
- shouldRunBuild = false;
// Get the name of the build target
target = info.getBuildArtifactName();
// Get its extension
@@ -386,8 +370,9 @@ public class MakefileGenerator {
/* (non-javadoc)
* Answers a <code>StringBuffer</code> containing all of the sources contributed by
* a container to the build.
+ *
* @param module
- * @return
+ * @return StringBuffer
*/
protected StringBuffer addSources(IContainer module) throws CoreException {
// Calculate the new directory relative to the build output
@@ -450,6 +435,8 @@ public class MakefileGenerator {
/* (non-javadoc)
* Answers a <code>StrinBuffer</code> containing all of the required targets to
* properly build the project.
+ *
+ * @return StringBuffer
*/
protected StringBuffer addTargets(boolean rebuild) {
StringBuffer buffer = new StringBuffer();
@@ -492,6 +479,7 @@ public class MakefileGenerator {
for (int i = 0; i < deps.length; i++) {
IProject dep = deps[i];
String buildDir = dep.getLocation().toString();
+ String depTargets = targets;
if (ManagedBuildManager.manages(dep)) {
// Add the current configuration to the makefile path
IManagedBuildInfo depInfo = ManagedBuildManager.getBuildInfo(dep);
@@ -501,9 +489,12 @@ public class MakefileGenerator {
String depTarget = depInfo.getBuildArtifactName();
String depExt = (new Path(depTarget)).getFileExtension();
String depPrefix = depInfo.getOutputPrefix(depExt);
+ if (depInfo.isDirty()) {
+ depTargets = "clean all";
+ }
managedProjectOutputs.add(buildDir + SEPARATOR + depPrefix + depTarget);
}
- buffer.append(TAB + "cd" + WHITESPACE + buildDir + SEMI_COLON + WHITESPACE + "$(MAKE) " + targets + NEWLINE);
+ buffer.append(TAB + "cd" + WHITESPACE + buildDir + SEMI_COLON + WHITESPACE + "$(MAKE) " + depTargets + NEWLINE);
}
}
buffer.append(NEWLINE);
@@ -514,7 +505,6 @@ public class MakefileGenerator {
* targ_<prefix><target>.<extension>: $(OBJS) [<dep_proj_1_output> ... <dep_proj_n_output>]
* $(BUILD_TOOL) $(FLAGS) $(OUTPUT_FLAG) $@ $(OBJS) $(USER_OBJS) $(LIB_DEPS)
*/
- //
buffer.append(outputPrefix + target + COLON + WHITESPACE + "$(OBJS)");
Iterator iter = managedProjectOutputs.listIterator();
while (iter.hasNext()) {
@@ -535,6 +525,12 @@ public class MakefileGenerator {
return buffer;
}
+ /* (non-javadoc)
+ *
+ * @param relativePath
+ * @param buffer
+ * @param resource
+ */
protected void addRule(String relativePath, StringBuffer buffer, IResource resource) {
String rule = null;
String cmd = null;
@@ -633,25 +629,20 @@ public class MakefileGenerator {
*/
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.
+ * Let's do a sanity check right now.
+ *
+ * 1. This is an incremental build, so if the top-level directory is not
+ * there, then a rebuild is needed.
*/
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, ManagedBuilderCorePlugin.getUniqueIdentifier(), GeneratedMakefileBuilder.EMPTY_PROJECT_BUILD_ERROR, "", null);
- throw new CoreException(status);
- }
// See if the user has cancelled the build
checkCancel();
@@ -659,11 +650,6 @@ public class MakefileGenerator {
// 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, ManagedBuilderCorePlugin.getUniqueIdentifier(), GeneratedMakefileBuilder.EMPTY_PROJECT_BUILD_ERROR, "", null);
- throw new CoreException(status);
- }
checkCancel();
// Regenerate any fragments that are missing for the exisiting directories NOT modified
@@ -697,7 +683,8 @@ public class MakefileGenerator {
}
/* (non-javadoc)
- * @return
+ *
+ * @return List
*/
private List getModifiedList() {
if (modifiedList == null) {
@@ -710,6 +697,7 @@ public class MakefileGenerator {
* Answers the list of known build rules. This keeps me from generating duplicate
* rules for known file extensions.
*
+ * @return List
*/
private List getRuleList() {
if (ruleList == null) {
@@ -720,7 +708,8 @@ public class MakefileGenerator {
/* (non-javadoc)
* Answers the list of subdirectories contributing source code to the build
- * @return
+ *
+ * @return List
*/
private List getSubdirList() {
if (subdirList == null) {
@@ -731,7 +720,7 @@ public class MakefileGenerator {
/* (non-javadoc)
* @param string
- * @return
+ * @return IPath
*/
private IPath createDirectory(String dirName) throws CoreException {
// Create or get the handle for the build directory
@@ -765,7 +754,7 @@ public class MakefileGenerator {
/* (non-javadoc)
* @param makefilePath
* @param monitor
- * @return
+ * @return IFile
*/
private IFile createFile(IPath makefilePath) throws CoreException {
// Create or get the handle for the makefile
@@ -794,7 +783,7 @@ public class MakefileGenerator {
* Answers the <code>IPath</code> of the top directory generated for the build
* output, or <code>null</code> if none has been generated.
*
- * @return
+ * @return IPath
*/
public IPath getTopBuildDir() {
return topBuildDir;
@@ -803,7 +792,7 @@ public class MakefileGenerator {
/**
* Answers <code>true</code> if the argument is found in a generated container
* @param resource
- * @return
+ * @return boolean
*/
public boolean isGeneratedResource(IResource resource) {
// Is this a generated directory ...
@@ -824,6 +813,7 @@ public class MakefileGenerator {
*
* @param fileHandle The file to place the contents in.
* @param rebuild FLag signalling that the user is doing a full rebuild
+ * @throws CoreException
*/
protected void populateTopMakefile(IFile fileHandle, boolean rebuild) throws CoreException {
StringBuffer buffer = new StringBuffer();
@@ -843,6 +833,7 @@ public class MakefileGenerator {
/* (non-javadoc)
* @param module
+ * @throws CoreException
*/
protected void populateFragmentMakefile(IContainer module) throws CoreException {
// Calcualte the new directory relative to the build output
@@ -879,11 +870,6 @@ public class MakefileGenerator {
// Visit the resources in the project
ResourceProxyVisitor visitor = new ResourceProxyVisitor(this, info);
project.accept(visitor, IResource.NONE);
- if (getSubdirList().isEmpty()) {
- // There is nothing to build
- IStatus status = new Status(IStatus.INFO, ManagedBuilderCorePlugin.getUniqueIdentifier(), GeneratedMakefileBuilder.EMPTY_PROJECT_BUILD_ERROR, "", null);
- throw new CoreException(status);
- }
// See if the user has cancelled the build
checkCancel();
@@ -906,23 +892,4 @@ public class MakefileGenerator {
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;
- }
-
}

Back to the top