如何强制Gradle为两个依赖项设置相同的版本?

113

我使用以下两个依赖项:

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

为了正常工作,两者必须是相同的版本。由于我的其他依赖项使用更高版本,Gradle会为每个依赖项使用不同的版本。

我通过运行 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 

我怎样可以强制Gradle为这两个依赖项设置相同的版本号?

11个回答

157
将以下内容添加到您的dependencies块之上。
Groovy/Gradle:
configurations.all {
  resolutionStrategy { 
    force 'com.google.guava:guava:14.0.1'
    force 'com.google.guava:guava-gwt:14.0.1'
  }
}

Kotlin脚本:

configurations.all {
  resolutionStrategy {
    force("com.google.guava:guava:14.0.1")
    force("com.google.guava:guava-gwt:14.0.1")
  }
}

33
将这个放在Gradle文件的哪里?在块的底部吗? - IgorGanapolsky
1
我仍然会遇到错误,例如:`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`
- IgorGanapolsky
1
@IgorGanapolsky 通常位置不重要,但我会把它放在靠近顶部的地方。 - cmcginty
3
这需要放在dependencies.gradle文件中。 - Joaquin Iurchuk
3
这和使用约束条件+"strictly"有什么区别? - dtc
显示剩余2条评论

83
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'
}

1
由于某些原因,强制方法无法防止其他版本的库被添加到JAR文件中,但是使用您的方法,我将在JAR文件中获得多个相同库的确切版本。离成功更近了一步。谢谢! - reith
1
Android Studio 3.3.0中找不到DependencyResolveDetails。 - Mr X
@MrX 我已经从代码中删除了不必要的DependencyResolveDetails提及。请再试一次。 - Vyacheslav Shvets
谢谢,当你在组中有多个构件时,这是完美的解决方案! - Max

43

我有过类似的情况,其中一个依赖项使用了已经损坏的spring-web 4.2.4。您必须强制使用您想要的特定库版本。如另一条评论所述,这可能会导致兼容性问题,但有时是必要的。

我发现最不具侵入性的强制库版本的方式是,而不是使用

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

强制指定依赖配置:

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

当我需要临时降级Spring版本(直到下一个版本发布),我使用了它。


6
force = true 现在已经被弃用。 - diesersamat
4
确实,force = true已经被弃用了。现在你应该使用strictlyimplementation("org.springframework:spring-web") { version { strictly "4.2.3.RELEASE" } } - Luke Needham

20

您的某个依赖项强制更新了guava版本。使用gradle dependencies来定位是哪个库在驱逐您的版本。

您面临的问题是,如果您强制使用14.0.1版本,可能会导致其他库无法正常工作。您不能只使用17.0版本作为依赖吗?

我使用一个dependencies.gradle文件来维护build.gradle中的单个guava版本号,该文件将具有版本号映射并将其拉入build.gradle中。这样,我只需要维护单个guava版本即可。所以您的示例将是:

dependencies.gradle

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

然后在 build.gradle 文件中可以有:

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
}

那么当我想要升级到17.0时,我只需要更改dependencies.gradle文件。

我也绝对支持将传递依赖项设置为false。

configurations.compile { transitive = false }

通过这种方式,您在编译时不会有一些依赖项被驱逐,尽管如果被驱逐的库不完全向后兼容,您在运行时可能会遇到问题。让我们面对现实,如果您正在编写代码,您应该知道您使用的库,并且您应该明确您的依赖关系。这可以保护您免受其中一个依赖项升级并导致错误的影响。


11

这是为 Kotlin DSL(build.gradle.kts)与 Gradle 7.1 测试用的:

dependencies {
    implementation("org.jsoup", "jsoup") {
        version {
            strictly("1.14.3")
        }
    }
}

另一种方法:
dependencies {
    implementation("org.jsoup:jsoup") {
        version {
            strictly("1.14.+") // You can also use dynamic versions
        }
    }
}

另一种方式,正如其他答案所建议的:
configurations.all {
    resolutionStrategy {
        force("org.jsoup:jsoup:1.14.3")
        force("com.google.guava:guava-gwt:14.0.1")
    }
}

9
另一种选择是使用依赖约束: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'
        }
    }
}

有没有办法在循环中实现这个?例如,我需要约束io.netty组中的大约8个包,并且不想为每个包复制和粘贴一个约束条件,但我看不到通配符支持。 - drobert

5

2

或者您可以在Gradle插件的spring-dependency-management中使用dependencySets(或mavenBom,当BOM POM可用时)。请注意,此插件也会自动应用于spring-boot Gradle插件。有关更多详细信息,请参见此处

plugins {
  id 'io.spring.dependency-management' version '1.0.1.RELEASE'
}

dependencyManagement {
  dependencies {
    dependencySet(group: 'com.google.guava', version: '14.0.1') {
      entry 'guava'
      entry 'guava-gwt'
    }
  }
}

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

1
如果只使用新版本的依赖关系就可以,解决问题的最简单方法是更新您的依赖关系:
compile 'com.google.guava:guava:17.0'
compile 'com.google.guava:guava-gwt:17.0'

这将确保它们都使用17.0版本。这比试图强制两者使用旧版本要简单,而且作为额外的奖励,您会获得一个新版本,其中(可能)包含错误修复和新功能。
公平地说,@Klunk在他的答案中提到了这一点,他问道:“你不能只使用17.0版本作为你的依赖吗?”但这只是顺带提及,很容易被忽视,所以我认为把它发布为一个单独的答案是有意义的。

1

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接