Duplicated classpath entries in gradle project

Hello there,

I discovered a weird behaviour in gradle projects regarding the classpath(OrderEntries).
The scenario is the following:

  • We have a gradle project
  • The project is already built with gradle - that means classes built by gradle exist in the build directory
  • We have configured a different module output path than the gradle directory
  • We have also built the project by using Intellij Build → Rebuild Project

If the above is true then determining the classpath with the following code leads to duplicate entries:

for(final Module m : ModuleManager.getInstance(project).getModules()){
	System.out.println("module "+m.getName());
	for(final VirtualFile vf : ModuleRootManager.getInstance(m).orderEntries().withoutSdk().withoutDepModules().getClassesRoots()){
		System.out.println(vf);
	}
}

In my example project this produces the following output:

module aTestGradleProject
file://C:/smo/projects/aTestProject/aTestGradleProject/build/classes/java/main
module aTestGradleProject.main
file://C:/smo/projects/aTestProject/aTestGradleProject/out/production/aTestGradleProject.main
file://C:/smo/projects/aTestProject/aTestGradleProject/build/classes/java/main
module aTestGradleProject.test
jar://C:/Users/smo/.gradle/caches/modules-2/files-2.1/org.junit.jupiter/junit-jupiter/5.10.0/8fea1d9c58b2156f1b998f2f18da04bc9e087f74/junit-jupiter-5.10.0.jar!/
jar://C:/Users/smo/.gradle/caches/modules-2/files-2.1/org.junit.jupiter/junit-jupiter-params/5.10.0/9041c7365495a897a64782ea5a6fdb99dab1814e/junit-jupiter-params-5.10.0.jar!/
jar://C:/Users/smo/.gradle/caches/modules-2/files-2.1/org.junit.jupiter/junit-jupiter-api/5.10.0/2fe4ba3d31d5067878e468c96aa039005a9134d3/junit-jupiter-api-5.10.0.jar!/
jar://C:/Users/smo/.gradle/caches/modules-2/files-2.1/org.apiguardian/apiguardian-api/1.1.2/a231e0d844d2721b0fa1b238006d15c6ded6842a/apiguardian-api-1.1.2.jar!/
jar://C:/Users/smo/.gradle/caches/modules-2/files-2.1/org.junit.platform/junit-platform-commons/1.10.0/d533ff2c286eaf963566f92baf5f8a06628d2609/junit-platform-commons-1.10.0.jar!/
jar://C:/Users/smo/.gradle/caches/modules-2/files-2.1/org.opentest4j/opentest4j/1.3.0/152ea56b3a72f655d4fd677fc0ef2596c3dd5e6e/opentest4j-1.3.0.jar!/
jar://C:/Users/smo/.gradle/caches/modules-2/files-2.1/org.junit.jupiter/junit-jupiter-engine/5.10.0/90587932d718fc51a48112d33045a18476c542ad/junit-jupiter-engine-5.10.0.jar!/
jar://C:/Users/smo/.gradle/caches/modules-2/files-2.1/org.junit.platform/junit-platform-engine/1.10.0/276c4edcf64fabb5a139fa7b4f99330d7a93b804/junit-platform-engine-1.10.0.jar!/

Problematic are these two entries which both contain the same classes(in my example project only a single class Main)

file://C:/smo/projects/aTestProject/aTestGradleProject/out/production/aTestGradleProject.main
file://C:/smo/projects/aTestProject/aTestGradleProject/build/classes/java/main

Is it possible to filter those duplicated entries somehow such that the classpath contains only one of those entries?

Thanks you and kind regards,
Samuel

PS I created an example project to make it easier to understand the problem - however seems like I am not allowed to upload a ZIP file. Is there any other way I can upload this file?

Hello Samuel Motal!

  • We have configured a different module output path than the gradle directory

How do you configure this module directory?

I tried to change the module output directory from build.gradle.kts.

sourceSets {
    main {
        java.destinationDirectory.set(file("out/production/${project.name}.main"))
    }
}

I tried to change the module output directory from Project Structure.

In both cases, I have only one output directory in module class path.

surly-golems
module surly-golems
file:///Users/Sergey.Vorobyov/Documents/Samples/Untitled/surly-golems/out/production/surly-golems.main
module surly-golems.main
file:///Users/Sergey.Vorobyov/Documents/Samples/Untitled/surly-golems/out/production/surly-golems.main
module surly-golems.test
jar:///Users/Sergey.Vorobyov/.gradle/caches/modules-2/files-2.1/org.junit.jupiter/junit-jupiter/5.10.0/8fea1d9c58b2156f1b998f2f18da04bc9e087f74/junit-jupiter-5.10.0.jar!/
jar:///Users/Sergey.Vorobyov/.gradle/caches/modules-2/files-2.1/org.junit.jupiter/junit-jupiter-params/5.10.0/9041c7365495a897a64782ea5a6fdb99dab1814e/junit-jupiter-params-5.10.0.jar!/
jar:///Users/Sergey.Vorobyov/.gradle/caches/modules-2/files-2.1/org.junit.jupiter/junit-jupiter-api/5.10.0/2fe4ba3d31d5067878e468c96aa039005a9134d3/junit-jupiter-api-5.10.0.jar!/
jar:///Users/Sergey.Vorobyov/.gradle/caches/modules-2/files-2.1/org.apiguardian/apiguardian-api/1.1.2/a231e0d844d2721b0fa1b238006d15c6ded6842a/apiguardian-api-1.1.2.jar!/
jar:///Users/Sergey.Vorobyov/.gradle/caches/modules-2/files-2.1/org.junit.platform/junit-platform-commons/1.10.0/d533ff2c286eaf963566f92baf5f8a06628d2609/junit-platform-commons-1.10.0.jar!/
jar:///Users/Sergey.Vorobyov/.gradle/caches/modules-2/files-2.1/org.opentest4j/opentest4j/1.3.0/152ea56b3a72f655d4fd677fc0ef2596c3dd5e6e/opentest4j-1.3.0.jar!/
jar:///Users/Sergey.Vorobyov/.gradle/caches/modules-2/files-2.1/org.junit.jupiter/junit-jupiter-engine/5.10.0/90587932d718fc51a48112d33045a18476c542ad/junit-jupiter-engine-5.10.0.jar!/
jar:///Users/Sergey.Vorobyov/.gradle/caches/modules-2/files-2.1/org.junit.platform/junit-platform-engine/1.10.0/276c4edcf64fabb5a139fa7b4f99330d7a93b804/junit-platform-engine-1.10.0.jar!/

IDE Script (Groovy)

import com.intellij.openapi.module.ModuleManager
import com.intellij.openapi.project.ProjectManager
import com.intellij.openapi.roots.ModuleRootManager

for (var project: ProjectManager.getInstance().openProjects) {
  println project.name
  for (var m : ModuleManager.getInstance(project).getModules()) {
    println "module " + m.getName()
    for (var vf : ModuleRootManager.getInstance(m).orderEntries().withoutSdk().withoutDepModules().getClassesRoots()) {
      println vf
    }
  }
}

Hello Sergey,

here is how the project is configured:

The compiler path is set in the project structure on project level:

The modules are configured to inherit the compiler path from the project:

However the main and the test project have a different module path configured:

I admit this is a little bit a weird configuration - I think however it is easy to encounter such a situation. What I did was just setup a gradle project and afterwards change the compiler output path on project level. The compiler output path on main and test I did never touch - I think it was initialized with the creation of the gradle project.

Thank you for your investigation so far. Is there any more information that would help?

Best regards,
Samuel