`gradle eclipse` generates duplicate classpathentry in Eclipse's `.classpath` with gradle >= 2.6

The eclipse target generates duplicate <classpathentry/> entries in .classpath when run with gradle 2.6 or higher. See for example the xpp3 classpathentry in the following:

<classpath>
    <classpathentry kind="output" path="bin"/>
    <classpathentry kind="src" path="src/main/java"/>
    <classpathentry kind="src" path="src/main/resources"/>
    <classpathentry kind="src" path="src/test/java"/>
    <classpathentry kind="src" path="src/test/resources"/>
    <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
    <classpathentry sourcepath="/home/flo/.m2/repository/xpp3/xpp3/1.1.4c/xpp3-1.1.4c-sources.jar" kind="lib" path="/home/flo/.m2/repository/xpp3/xpp3/1.1.4c/xpp3-1.1.4c.jar">
        <attributes>
            <attribute name="javadoc_location" value="jar:file:/home/flo/.m2/repository/xpp3/xpp3/1.1.4c/xpp3-1.1.4c-javadoc.jar!/"/>
        </attributes>
    </classpathentry>
...
    <classpathentry kind="lib" path="/home/flo/.m2/repository/xpp3/xpp3/1.1.4c/xpp3-1.1.4c.jar"/>
...
</classpath>

(full file here)

This results in eclipse reporting “Build path contains duplicate entry … for project …”.

Happens with gradle 2.6 and 2.7. Does not happen with gradle 2.4. Not sure if this qualifies as regression (e.g. GRADLE-1953). The project in question is https://github.com/igniterealtime/Smack

The issue still exists in Gradle 2.8 btw.

And it’s still here in 2.11rc1. :frowning:

Gradle 2.11 still produces duplicate .classpath entries.

Looking at the git log REL_2.4..REL_2.6 for the supposed relevant path subprojects/ide/src/main the commit series consisting of

  • c3bb8f01c5bed7d653685ff517303cc8b8d3e9d4
  • 3d8ec0df6364c2033a57efaf48abcca3578518d5
  • a490fe506efa1aaf3bbeef9e73767e970fcb75e0
  • 109bb0bc54def466a45ce413609c6215cbcb64b8
  • 9b3b88f02392135f6828929bc30c51529fb9ae7c
  • 612e8dae4864a9ad98e69ce98eb0e5a7746a6403
    could be the cause.

Thanks for the bug report. I took a look at this and I was able to reproduce the problem and I can see the duplicate in smack-tcp/.classpath.

This might be a bug in version handling since when I change the xpp3 library dependency to 'xpp3:xpp3:1.1.3.3' in smack-core/build.gradle, no duplicate gets produced in the .classpath files.

What catched my eye was the letter in the version of xpp3 dependency 'xpp3:xpp3:1.1.4c'.
I assume that the xpp3 dependency is the only duplicate and it could be related to a bug in version handling in Gradle.

I created a failing unit test https://gist.github.com/lhotari/735a4ff4988d6820eac9#file-eclipseclasspathintegrationtest-groovy-L1061-L1101 . The test passes with version ‘1.1.3.3’ .

The problem seems to occur with the dependency testCompile project(':smack-core').sourceSets.test.runtimeClasspath. Perhaps you could find a way to workaround the problem until this bug is fixed.

I have created the issue https://issues.gradle.org/browse/GRADLE-3396 to track this bug.

The problem goes away when the dependencies are configured in a proper way.

Currently there are dependencies like this:
testCompile project(':smack-core').sourceSets.test.runtimeClasspath

The correct way to express the dependency is:
testCompile project(path: ":smack-core", configuration: "testRuntime")

Thanks so much for your help. Really appreciated.

While this fixes the issue, it causes gradle check to fail with

:smack-experimental:compileTestJava
/home/flo/data/code/smack/smack-experimental/src/test/java/org/jivesoftware/smackx/carbons/CarbonTest.java:21: error: package org.jivesoftware.smack.test.util does not exist
import static org.jivesoftware.smack.test.util.CharsequenceEquals.equalsCharSequence;
                                              ^
/home/flo/data/code/smack/smack-experimental/src/test/java/org/jivesoftware/smackx/carbons/CarbonTest.java:21: error: static import only from classes and interfaces
import static org.jivesoftware.smack.test.util.CharsequenceEquals.equalsCharSequence;
^
2 errors
:smack-experimental:compileTestJava FAILED

So the code from smack-core/src/test/java is not available to smack-experimental test runtime. I believe that is why I added the dependency this way in the first place.

How can I fix this too?

I think i’ve fixed it by adding the "archives’ configuration, which includes the test jar.

dependencies {
	compile project(':smack-core')
	testCompile project(path: ":smack-core", configuration: "testRuntime")
	testCompile project(path: ":smack-core", configuration: "archives")
}

Thanks to https://softnoise.wordpress.com/2014/09/07/gradle-sub-project-test-dependencies-in-multi-project-builds/ for the hint.

Looks good to me. Kudos to @hauner for the helpful article.