eclipse / buildship

The Eclipse Plug-ins for Gradle project.
530 stars 169 forks source link

Duplicate results in the classpath when using spring aot plugin #1236

Open CsCherrYY opened 1 year ago

CsCherrYY commented 1 year ago

Steps to Reproduce

  1. git clone https://github.com/scratches/gradle-aot
  2. run ./gradlew clean build in the project root folder
  3. Open the project in VS Code or eclipse
  4. Run the test case ConfigTest, you can see the errors.

Expected Behavior

The test should succeed.

Current Behavior

The test fails due to the duplicate results in the classpath. image

Context

It looks like the issue exists in the interaction between spring aot plugin and buildship/Gradle eclipse plugin. The aot plugin will add each source set's output to the runtime classpath. See : https://github.com/spring-projects/spring-boot/blob/5d49889bfde45ec0cf1d73b96ae61096add9dae7/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/main/java/org/springframework/boot/gradle/plugin/SpringBootAotPlugin.java#L78 and https://github.com/spring-projects/spring-boot/blob/5d49889bfde45ec0cf1d73b96ae61096add9dae7/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/main/java/org/springframework/boot/gradle/plugin/SpringBootAotPlugin.java#L92

dsyer commented 1 year ago

Looks like this might be related: https://github.com/gradle/gradle/issues/23032 (according to comments in https://github.com/redhat-developer/vscode-java/issues/2344). Might even be fixed upstream already, but still broken for me in "pre-release" version of vscode extensions (redhat.java v1.18.2023041704)?

CsCherrYY commented 1 year ago

@dsyer I guess you should use Gradle 8.1 first (the version is mentioned in the PR's milestone) and configure like the following snippet:

eclipse {
  classpath {
    baseSourceOutputDir = file('build')
  }
}

Unfortunately, it doesn't help. The generated files are under build folder but the classpath entries are still duplicated.

snjeza commented 1 year ago

@CsCherrYY @dsyer You can try the following patch:

diff --git a/build.gradle b/build.gradle
index 5dd773c..c1053ce 100644
--- a/build.gradle
+++ b/build.gradle
@@ -3,6 +3,7 @@ plugins {
   id 'org.springframework.boot' version '3.0.5'
   id 'io.spring.dependency-management' version '1.1.0'
   id 'org.graalvm.buildtools.native' version '0.9.20'
+  id 'eclipse'
 }

 group = 'com.example'
@@ -20,4 +21,19 @@ dependencies {

 tasks.named('test') {
   useJUnitPlatform()
-}
\ No newline at end of file
+}
+
+eclipse {
+  classpath {
+    defaultOutputDir = file('build-default')
+    file {
+        whenMerged {
+            cp -> cp.getEntries().forEach{
+                cpEntry -> if(cpEntry.path=='src/main/resources') {
+                    cpEntry.output = 'build/resources/main'
+                }
+            }
+        }
+    }
+  }
+}
dsyer commented 1 year ago

Why does Buildship want to use bin/main as a default build location? I imagine there is a reason for it, and this patch changes the build location, and therefore probably breaks something else?

snjeza commented 1 year ago

@dsyer you may want to take a look at https://github.com/eclipse/buildship/issues/1131#issuecomment-1014559863

dsyer commented 1 year ago

From that it seems like changing the default is a bad idea - gradle clean would break the IDE? Also the patch is ugly, and I wouldn't want everyone who uses Spring AOT to have to use it. So I'm not sure what to do next.

donat commented 1 year ago

This is the same problem that was described in #1238. In this case, the org.graalvm.buildtools.native contributes the classes directory to the Eclipse classpath. Currently we can only work around the problem (see the previous comment). The correct solution requires a deeper change on how the Gradle classpath is mapped into Eclipse.

xerx593 commented 1 year ago

Besides the "strange url" (classpath*:*), I could not reproduce! Nor via:

Vs Code: v1.78.0

>.\gradlew.bat --version

------------------------------------------------------------
Gradle 8.1.1
------------------------------------------------------------

Build time:   2023-04-21 12:31:26 UTC
Revision:     1cf537a851c635c364a4214885f8b9798051175b

Kotlin:       1.8.10
Groovy:       3.0.15
Ant:          Apache Ant(TM) version 1.10.11 compiled on July 10 2021
JVM:          17.0.7 (Oracle Corporation 17.0.7+8-LTS-224)
OS:           Windows 10 10.0 amd64

>.\gradlew.bat clean build     
...
BUILD SUCCESSFUL in 18s
15 actionable tasks: 15 executed

Is this OS-specific? Or rather (recently/unlcky timing) fixed by https://github.com/gradle/gradle/issues/23032 -> https://github.com/redhat-developer/vscode-java/issues/634 -> https://github.com/eclipse/eclipse.jdt.ls/pull/1108 ?

dsyer commented 1 year ago

It's not OS-specific. Did you run the tests in the IDE? I just checked in Codespaces and it's still broken with 1.78.1 and the latest Java extensions v0.25.1 (although I'm not sure if that includes the fixes you mentioned).

xerx593 commented 1 year ago

Did you run the tests in the IDE?

Confirmative, @dsyer.

I am on "release channel" (yesterday was a (code) update between the tests, but tests passed before&after..) Furthermore: I cannot see the symptom: file.txt is unique (in bin and build folders)

image

dsyer commented 1 year ago

I have all the same versions of extensions and it is still broken for me: test fails and

$ find . -name file.txt
./bin/main/file.txt
./src/main/resources/file.txt
./build/resources/main/file.txt

I also tried with pre-release versions.

xerx593 commented 1 year ago

ok, now confirm: found the 2nd file(.txt) :see_no_evil:

but still: test passes! :flushed:

let's try in a "uniform" devcontainer!? (OS!?/side effects"!??) :thinking:

dsyer commented 1 year ago

Please send a PR for your suggested change at https://github.com/scratches/gradle-aot and/or open an issue there.

xerx593 commented 1 year ago

I can reproduce on a (linux) dev container, but still not on (minimal, win) profile

changing (source code) to classpath:/*.txt (behaves uniformly on platforms, but)

oleosterhagen commented 2 months ago

The Spring Boot Gradle plugin introduces additional source sets (aot / aotTest) and corresponding configurations (aotCompileClasspath, aotRuntimeClasspath, ...).

As long as the build (./gradlew build) has not been invoked these sources are not created and no duplicate entries (e.g. file.txt) are added to the classpath. After executing the build (and executing Refresh Gradle Project) these classpath entries are created and lead to the unwanted duplicates.

When the functionality from the Spring AOT plugin is not needed during development in Eclipse you can remove the source sets and configurations in build.gradle:

eclipse {
  classpath {
    plusConfigurations -= [
      configurations.aotCompileClasspath,
      configurations.aotRuntimeClasspath,
      configurations.aotTestCompileClasspath,
      configurations.aotTestRuntimeClasspath
    ]

    sourceSets -= [ sourceSets.aot, sourceSets.aotTest ]
  }
}

Now, after invoking Refresh Gradle Project the ConfigTest should complete successfully.

The behavior of the Spring AOT plugin is not OS dependent. I can also reproduce this issue on Windows.