How can I force Gradle to set the same version for two dependencies?

117,661

Solution 1

One of your dependencies is forcing the guava version to update. Use gradle dependencies to locate which library is evicting your version.

The problem you have is that if you force it to use 14.0.1 another library may not work properly. Can you not just use the 17.0 version as your dependency?

Rather than maintain individual version numbers in the build.gradle I use a dependencies.gradle file which will have a mapping of version numbers and pull that into the build.gradle. That way I only need to maintain the single guava version. So your example will be:

dependencies.gradle

ext {
    ver = [
        guava: '14.0.1'
    ]
}

and then in the build.gradle file you can have:

apply from: "dependencies.gradle"

dependencies {
    compile group: 'com.google.guava', module: 'guava', version: ver.guava
    compile group: 'com.google.guava', module: 'guava-gwt', version: ver.guava
}

then when I want to move to 17.0 I only need to change the dependencies.gradle.

I am also a definite fan of setting transitive dependencies to false with

configurations.compile { transitive = false }

this way you do not have some dependencies evicted at compile time, although you may have a problem at run time if the evicting library is not fully backward compatible. Lets face it if you are writing the code you should know what libraries you use and you should be explicit about your dependencies. It protects you from one of your dependencies upgrading and messing you up.

Solution 2

Add this section to dependencies.gradle file

configurations.all {
        resolutionStrategy { 
            force 'com.google.guava:guava:14.0.1'
            force 'com.google.guava:guava-gwt:14.0.1'
        }
    }

Solution 3

configurations.all {
  resolutionStrategy.eachDependency { details ->
    if (details.requested.group == 'com.google.guava') {
      details.useVersion "14.0.1"
    }
  }
}

dependencies {
  compile 'com.google.guava:guava'
  compile 'com.google.guava:guava-gwt'
}

Solution 4

I had a similar situation where one of the dependencies used spring-web 4.2.4 which was broken. You have to force specific library version you want. As mentioned in another comment, it might cause compatibility issues but sometimes is necessary.

Least intrusive way of forcing a library version I found was instead of using

compile "org.springframework:spring-web:4.2.3.RELEASE"

specifying dependency configuration as forced:

compile("org.springframework:spring-web:4.2.3.RELEASE"){
    force = true
}

I used it when I needed to downgrade Spring version temporarily (until next release).

Solution 5

Another option is to use dependency constraint: https://docs.gradle.org/current/userguide/dependency_constraints.html

dependencies {
    implementation 'org.apache.httpcomponents:httpclient'
    constraints {
        implementation('org.apache.httpcomponents:httpclient:4.5.3') {
            because 'previous versions have a bug impacting this application'
        }
        implementation('commons-codec:commons-codec:1.11') {
            because 'version 1.9 pulled from httpclient has bugs affecting this application'
        }
    }
}
Share:
117,661
confile
Author by

confile

Java, GWT, JavaScript, Grails, Groovy, Swift, Objective-C, iOS

Updated on February 18, 2022

Comments

  • confile
    confile about 2 years

    I use the following two dependencies:

    compile 'com.google.guava:guava:14.0.1'
    compile 'com.google.guava:guava-gwt:14.0.1'
    

    Both must be the same version to work correctly. Since my other dependencies use a higher version, Gradle uses different versions for each dependency.

    I found this by running gradle dependencies:

    compile - Compile classpath for source set 'main'.
     +--- com.google.guava:guava:14.0.1 -> 17.0
     +--- com.google.guava:guava-gwt:14.0.1
     |    +--- com.google.code.findbugs:jsr305:1.3.9
     |    \--- com.google.guava:guava:14.0.1 -> 17.0 
    

    How can I force Gradle to set the same version for these two dependencies?

  • IgorGanapolsky
    IgorGanapolsky almost 8 years
    Where to put this within the gradle file? At the bottom of the block?
  • IgorGanapolsky
    IgorGanapolsky almost 8 years
    I still get errors like: Execution failed for task ':transformClassesWithJarMergingForDebug'. > com.android.build.api.transform.TransformException: java.util.zip.ZipException: duplicate entry: com/google/android/gms/gcm/GoogleCloudMessaging$1.class
  • cmcginty
    cmcginty over 6 years
    @IgorGanapolsky The location does not matter typically, but I would put it near the top.
  • reith
    reith almost 6 years
    For some reason force method didn't prevent other versions of library being added to jar file but with your method I'll get multiple exact version of same library in jar file. One step closer. Thanks!
  • Joaquin Iurchuk
    Joaquin Iurchuk over 5 years
    this goes in dependencies.gradle file
  • Mr X
    Mr X over 5 years
    DependencyResolveDetails not found in androidsudio 3.3.0
  • cmcginty
    cmcginty almost 5 years
    @Aravinth I think you can also use extended syntax to change the extension type. Look at the declaring dependencies docs in Gradle
  • Aravinth
    Aravinth almost 5 years
    @cmcginty What do you mean by 'extension type'?
  • dtc
    dtc about 4 years
    what's the difference between this and using constraints+"strictly"?
  • Vyacheslav Shvets
    Vyacheslav Shvets over 3 years
    @MrX I've removed unnecessary DependencyResolveDetails mention from the code. Please try again
  • diesersamat
    diesersamat over 2 years
    force = true is deprecated now