5

I'm trying to compile a module whose dependency tree looks like

+--- com.squareup.burst:burst-junit4:1.0.2
|    +--- com.squareup.burst:burst:1.0.2
|    \--- junit:junit:4.11 -> 4.12
|         \--- org.hamcrest:hamcrest-core:1.3
+--- com.android.support.test.espresso:espresso-core:2.0
|    +--- com.squareup:javawriter:2.1.1
|    +--- org.hamcrest:hamcrest-integration:1.1
|    |    \--- org.hamcrest:hamcrest-core:1.1 -> 1.3
|    +--- org.hamcrest:hamcrest-library:1.1
|    |    \--- org.hamcrest:hamcrest-core:1.1 -> 1.3
|    +--- com.android.support.test.espresso:espresso-idling-resource:2.0
|    +--- com.android.support.test:testing-support-lib:0.1
|    |    \--- junit:junit-dep:4.10
|    |         \--- org.hamcrest:hamcrest-core:1.1 -> 1.3
|    +--- com.google.code.findbugs:jsr305:2.0.1
|    +--- javax.annotation:javax.annotation-api:1.2
|    \--- org.hamcrest:hamcrest-core:1.1 -> 1.3
...

As you can see there's a hamcrest-core version conflict, but gradle appears to recognize the conflict and apply its default "latest version" strategy, which is exactly what I want.

However, when trying to run assembleDebugTest (either manually or through Android Studio) I get

com.android.dex.DexException: Multiple dex files define Lorg/hamcrest/MatcherAssert;

Some answers to similar questions suggest excludeing the unwanted jars, but I've encountered a bunch of similar conflicts, and it's getting a bit out of hand.

Why isn't gradle's default conflict strategy removing the older jar automatically? Does the android gradle plugin suppress that functionality?

Daniel Lubarov
  • 7,796
  • 1
  • 37
  • 56
  • http://stackoverflow.com/questions/20989317/multiple-dex-files-define-landroid-support-v4-accessibilityservice-accessibility – Robert Rowntree Jan 21 '15 at 01:45
  • I did see that, and I understand the quick fix. My questions is why gradle's default resolution strategy isn't being used to remove one of the jars automatically, as I would expect from reading [this doc](http://www.gradle.org/docs/current/dsl/org.gradle.api.artifacts.ResolutionStrategy.html). – Daniel Lubarov Jan 21 '15 at 01:58
  • could try a build with -verbose ... find where configurations.resolutionStrategy{} is invoked.... if NOT invoked then provide ur own implementation of it. – Robert Rowntree Jan 21 '15 at 16:04
  • I tried providing a custom `resolutionStrategy`, and the versions in `gradle dependencies` showed that my strategy was being used. The build log from `gradle --debug assembleDebugTest` or `gradle --debug dependencies` didn't contain `resolutionStrategy` though; is it supposed to be logged? – Daniel Lubarov Jan 21 '15 at 18:48
  • was a wild guess?? sorry. AFAIK, you can throw a log statement from "resolutionStrategy" by extending the DSL logger and looking for curTask="resolutionStrategy" ... http://www.gradle.org/docs/current/userguide/logging.html otherwise i have no idea – Robert Rowntree Jan 21 '15 at 19:12

1 Answers1

8

After some more digging, it seems the issue is that my dependency tree contained hamcrest-core 1.3 and hamcrest-integration 1.1, and MatcherAssert was moved from hamcrest-integration to hamcrest-core between those versions.

So gradle was performing conflict resolution as documented; there was just a conflict between distinct modules which I didn't expect.

Forcing 1.3 for all three hamcrest modules took care of the problem.

Daniel Lubarov
  • 7,796
  • 1
  • 37
  • 56