In our project, we want a different output folder for each source set of the .classpath
. To achieve this, I’m using whenMerged
, than for each SourceFolder
entry, I update its output
directory. It works great for the first gradle eclipse
command. But then, if we do a another gradle eclipse
, existing SourceFolder
are not merged properly with the ones Gradle adds. This results in duplicated entries for each source folder. Mainly, I have a src/main/java
and src/test/java
folders. What I do to update source folders output is:
eclipse.classpath.file.whenMerged { classpath ->
def sourceFolders = classpath.entries.findAll { it instanceof SourceFolder }
sourceFolders.each { sourceFolder ->
sourceFolder.output = "obj/${sourceFolder.path.tokenize('/')[1]}"
}
}
Project is attached to reproduce: bug-duplicate-eclipse-classpath.zip (1 KB)
Actual console output:
$ gradle -v
------------------------------------------------------------
Gradle 2.10
------------------------------------------------------------
Build time: 2015-12-21 21:15:04 UTC
Build number: none
Revision: 276bdcded730f53aa8c11b479986aafa58e124a6
Groovy: 2.4.4
Ant: Apache Ant(TM) version 1.9.3 compiled on December 23 2013
JVM: 1.8.0_25 (Oracle Corporation 25.25-b02)
OS: Windows 7 6.1 amd64
$ tree
.
├── build.gradle
└── src
├── main
│ └── java
└── test
└── java
5 directories, 1 file
$ gradle eclipse
Configuration on demand is an incubating feature.
:eclipseClasspath
:eclipseJdt
:eclipseProject
:eclipse
BUILD SUCCESSFUL
Total time: 2.924 secs
$ cat .classpath
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="output" path="bin"/>
<classpathentry output="obj/main" kind="src" path="src/main/java"/>
<classpathentry output="obj/test" kind="src" path="src/test/java"/>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
</classpath>
$ gradle eclipse
Configuration on demand is an incubating feature.
:eclipseClasspath
:eclipseJdt
:eclipseProject
:eclipse
BUILD SUCCESSFUL
Total time: 2.529 secs
$ cat .classpath
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="output" path="bin"/>
<classpathentry output="obj/main" kind="src" path="src/main/java"/>
<classpathentry output="obj/test" kind="src" path="src/test/java"/>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
<classpathentry output="obj/main" kind="src" path="src/main/java"/>
<classpathentry output="obj/test" kind="src" path="src/test/java"/>
</classpath>
Expected is that the second second writes 2 source folders not 4. Current workaround I have is to actually store duplicate SourceFolder
and then remove then from the classpath entries
list:
eclipse.classpath.file.whenMerged { classpath ->
List<SourceFolder> sourceFolders = classpath.entries.findAll { it instanceof SourceFolder }
Set<String> seenSourceFolderPaths = []
List<SourceFolder> duplicatedSourceFolders = []
sourceFolders.each { sourceFolder ->
if (sourceFolder.path in seenSourceFolderPaths) {
duplicatedSourceFolders << sourceFolder
return
}
seenSourceFolderPaths << sourceFolder.path
sourceFolder.output = "obj/${sourceFolder.path.tokenize('/')[1]}"
}
duplicatedSourceFolders.each { duplicatedSourceFolder ->
classpath.entries.remove(duplicatedSourceFolder)
}
}