1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-04-29 19:45:01 +02:00

Bug 575490: "No rule" after removing last source file from root

Include the top-level subdir.mk only when one was actually generated
(i.e. when there are source files there), just like for all other
subdir.mk, otherwise a stale one from earlier when there were source
files that have since been removed may be picked up, causing "No rule to
make target" errors.

In some cases (from bug 303953), the removal would be noticed and the
stale subdir.mk be overwritten by a correct empty one, avoiding the
error, but not in the following cases:
- When CommonBuilder.performCleanning() decides that a full rebuild is
needed, regenerateMakefiles() is called instead of generateMakefiles(),
which doesn't get the delta.
- When the refresh in which Eclipse notices the removed source file
happens as part of a build (one that probably failed because the
makefiles weren't updated yet), the next build after that apparently
does not get the delta containing the removal anymore.

Change-Id: Id15b424f02dd5c513d2124620c0c8699d61874fd
Signed-off-by: Christian Walther <walther@indel.ch>
This commit is contained in:
Christian Walther 2021-08-17 17:10:38 +02:00
parent 3afae27158
commit f138ad10e8
5 changed files with 73 additions and 9 deletions

View file

@ -10,7 +10,6 @@ RM := rm -rf
-include sources.mk
-include module/subdir.mk
-include Sources/subdir.mk
-include subdir.mk
-include objects.mk
-include ../makefile.defs

View file

@ -16,7 +16,6 @@ RM := rm -rf
-include d1/d2/d3/subdir.mk
-include d1/d2/subdir.mk
-include d1/subdir.mk
-include subdir.mk
-include objects.mk
ifneq ($(MAKECMDGOALS),clean)

View file

@ -16,7 +16,6 @@ RM := rm -rf
-include d1/d2/d3/subdir.mk
-include d1/d2/subdir.mk
-include d1/subdir.mk
-include subdir.mk
-include objects.mk
ifneq ($(MAKECMDGOALS),clean)

View file

@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2011 Broadcom Corporation and others.
* Copyright (c) 2011, 2021 Broadcom Corporation and others.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
@ -13,21 +13,34 @@
*******************************************************************************/
package org.eclipse.cdt.managedbuilder.core.regressions;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;
import java.io.ByteArrayInputStream;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import org.eclipse.cdt.core.model.ICModelMarker;
import org.eclipse.cdt.core.settings.model.CSourceEntry;
import org.eclipse.cdt.core.settings.model.ICSourceEntry;
import org.eclipse.cdt.managedbuilder.core.ManagedBuildManager;
import org.eclipse.cdt.managedbuilder.testplugin.AbstractBuilderTest;
import org.eclipse.cdt.managedbuilder.testplugin.ResourceDeltaVerifier;
import org.eclipse.core.resources.IBuildConfiguration;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IMarker;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IResourceDelta;
import org.eclipse.core.resources.IncrementalProjectBuilder;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.ICoreRunnable;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.Path;
import org.junit.jupiter.api.Test;
/**
@ -84,4 +97,58 @@ public class Bug_303953Test extends AbstractBuilderTest {
verifyBuild(app, IncrementalProjectBuilder.INCREMENTAL_BUILD, verifier);
}
/**
* Tests that source files in the root of the project are not treated
* specially with respect to removing the last of them (bug 575490).
*/
@Test
public void testBuildAfterRootSourcefileDelete() throws CoreException, UnsupportedEncodingException {
setWorkspace("regressions");
final IProject app = loadProject("helloworldC");
setActiveConfigurationByName(app, "Debug");
// Change the source folder from /src to /
ManagedBuildManager.getBuildInfo(app).getDefaultConfiguration()
.setSourceEntries(new ICSourceEntry[] { new CSourceEntry(Path.ROOT, null, 0) });
// Add a new source file in the root
app.getFile("additional.c").create(new ByteArrayInputStream("int x = 42;\n".getBytes("UTF-8")), true, null);
// Build once: This will create a root subdir.mk referring to additional.c
ICoreRunnable build = new ICoreRunnable() {
@Override
public void run(IProgressMonitor monitor) throws CoreException {
getWorkspace().build(new IBuildConfiguration[] { app.getActiveBuildConfig() },
IncrementalProjectBuilder.FULL_BUILD, true, monitor);
}
};
getWorkspace().run(build, null);
IMarker[] markers = app.findMarkers(ICModelMarker.C_MODEL_PROBLEM_MARKER, true, IResource.DEPTH_INFINITE);
assertEquals(0, markers.length, "first build should succeed with no error markers");
// Remove additional.c behind Eclipse's back
app.getFile("additional.c").getLocation().toFile().delete();
// Build again: This is expected to fail because at the time the
// makefile is updated, the absence of additional.c hasn't been noticed
// yet. Only the refresh done at the end of this build will notice the
// removal.
getWorkspace().run(build, null);
markers = app.findMarkers(ICModelMarker.C_MODEL_PROBLEM_MARKER, true, IResource.DEPTH_INFINITE);
assertNotEquals(0, markers.length, "second build should produce an error marker");
// commented out because the exact wording may depend on the version of 'make' used
// assertEquals("make: *** No rule to make target '../additional.c', needed by 'additional.o'. Stop.",
// markers[0].getAttribute(IMarker.MESSAGE));
// Build again: The FULL_BUILD will ignore the delta indicating the
// removal of additional.c and therefore not regenerate the root
// subdir.mk (because now there are no source files in the root),
// leaving the stale one there that still refers to additional.c.
// This should succeed - before the fix, it would fail because the
// stale subdir.mk would still be included.
getWorkspace().run(build, null);
markers = app.findMarkers(ICModelMarker.C_MODEL_PROBLEM_MARKER, true, IResource.DEPTH_INFINITE);
assertEquals(0, markers.length, "final build should succeed with no error markers");
}
}

View file

@ -1258,15 +1258,15 @@ public class GnuMakefileGenerator implements IManagedBuilderMakefileGenerator2 {
List<String> subDirList = new ArrayList<>();
for (IContainer subDir : getSubdirList()) {
String projectRelativePath = subDir.getProjectRelativePath().toString();
if (!projectRelativePath.isEmpty())
subDirList.add(0, projectRelativePath);
subDirList.add(0, projectRelativePath);
}
Collections.sort(subDirList, Collections.reverseOrder());
for (String dir : subDirList) {
buffer.append("-include ").append(escapeWhitespaces(dir)).append(SEPARATOR).append("subdir.mk") //$NON-NLS-1$//$NON-NLS-2$
.append(NEWLINE);
buffer.append("-include "); //$NON-NLS-1$
if (!dir.isEmpty())
buffer.append(escapeWhitespaces(dir)).append(SEPARATOR);
buffer.append(MODFILE_NAME).append(NEWLINE);
}
buffer.append("-include subdir.mk").append(NEWLINE); //$NON-NLS-1$
buffer.append("-include objects.mk").append(NEWLINE).append(NEWLINE); //$NON-NLS-1$