diff --git a/build/org.eclipse.cdt.managedbuilder.core.tests/resources/test30Projects/CDTFortranTest2/Benchmarks/makefile b/build/org.eclipse.cdt.managedbuilder.core.tests/resources/test30Projects/CDTFortranTest2/Benchmarks/makefile index 254e4f9e3d1..92830e5c239 100644 --- a/build/org.eclipse.cdt.managedbuilder.core.tests/resources/test30Projects/CDTFortranTest2/Benchmarks/makefile +++ b/build/org.eclipse.cdt.managedbuilder.core.tests/resources/test30Projects/CDTFortranTest2/Benchmarks/makefile @@ -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 diff --git a/build/org.eclipse.cdt.managedbuilder.core.tests/resources/test40Projects/test_40/Benchmarks/Test 4.0 ConfigName.Dbg/makefile b/build/org.eclipse.cdt.managedbuilder.core.tests/resources/test40Projects/test_40/Benchmarks/Test 4.0 ConfigName.Dbg/makefile index a63e18c0cf1..40639006c5a 100644 --- a/build/org.eclipse.cdt.managedbuilder.core.tests/resources/test40Projects/test_40/Benchmarks/Test 4.0 ConfigName.Dbg/makefile +++ b/build/org.eclipse.cdt.managedbuilder.core.tests/resources/test40Projects/test_40/Benchmarks/Test 4.0 ConfigName.Dbg/makefile @@ -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) diff --git a/build/org.eclipse.cdt.managedbuilder.core.tests/resources/test40Projects/test_40/Benchmarks/dbg 2/makefile b/build/org.eclipse.cdt.managedbuilder.core.tests/resources/test40Projects/test_40/Benchmarks/dbg 2/makefile index f4acfa97436..8f2c8eb4acb 100644 --- a/build/org.eclipse.cdt.managedbuilder.core.tests/resources/test40Projects/test_40/Benchmarks/dbg 2/makefile +++ b/build/org.eclipse.cdt.managedbuilder.core.tests/resources/test40Projects/test_40/Benchmarks/dbg 2/makefile @@ -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) diff --git a/build/org.eclipse.cdt.managedbuilder.core.tests/tests/org/eclipse/cdt/managedbuilder/core/regressions/Bug_303953Test.java b/build/org.eclipse.cdt.managedbuilder.core.tests/tests/org/eclipse/cdt/managedbuilder/core/regressions/Bug_303953Test.java index 3d705a4d106..1211288aac8 100644 --- a/build/org.eclipse.cdt.managedbuilder.core.tests/tests/org/eclipse/cdt/managedbuilder/core/regressions/Bug_303953Test.java +++ b/build/org.eclipse.cdt.managedbuilder.core.tests/tests/org/eclipse/cdt/managedbuilder/core/regressions/Bug_303953Test.java @@ -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"); + } + } diff --git a/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/makegen/gnu2/GnuMakefileGenerator.java b/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/makegen/gnu2/GnuMakefileGenerator.java index e1fecedcc38..78cb573d28c 100644 --- a/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/makegen/gnu2/GnuMakefileGenerator.java +++ b/build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/makegen/gnu2/GnuMakefileGenerator.java @@ -1258,15 +1258,15 @@ public class GnuMakefileGenerator implements IManagedBuilderMakefileGenerator2 { List 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$