Gradle 传递依赖排除未按预期工作。 (我如何摆脱 com.google.guava:guava-jdk5:13.0 ?)

Posted

技术标签:

【中文标题】Gradle 传递依赖排除未按预期工作。 (我如何摆脱 com.google.guava:guava-jdk5:13.0 ?)【英文标题】:Gradle Transitive dependency exclusion is not working as expected. (How do I get rid of com.google.guava:guava-jdk5:13.0 ?) 【发布时间】:2014-11-05 16:40:38 【问题描述】:

这是我的 build.gradle 的 sn-p:

compile 'com.google.api-client:google-api-client:1.19.0'
compile 'com.google.apis:google-api-services-oauth2:v2-rev77-1.19.0'
compile 'com.google.apis:google-api-services-plus:v1-rev155-1.19.0'
compile 'com.google.appengine.tools:appengine-gcs-client:0.4.1'
compile 'com.google.appengine.tools:appengine-mapreduce:0.8'

它可以导入多个版本的番石榴,正如您在dependencyInsight中看到的那样:

com.google.guava:guava:15.0 (conflict resolution)

com.google.guava:guava:14.0.1 -> 15.0
+--- com.googlecode.objectify:objectify:4.1.3
|    \--- default
\--- net.eusashead.spring:spring-cache-gae:1.0.0.RELEASE
     \--- default

com.google.guava:guava:[15.0,15.99] -> 15.0
+--- com.google.appengine.tools:appengine-gcs-client:0.4.1
|    +--- default
|    +--- com.google.appengine.tools:appengine-mapreduce:0.8
|    |    \--- default
|    \--- com.google.appengine.tools:appengine-pipeline:0.2.10
|         \--- com.google.appengine.tools:appengine-mapreduce:0.8 (*)
+--- com.google.appengine.tools:appengine-mapreduce:0.8 (*)
\--- com.google.appengine.tools:appengine-pipeline:0.2.10 (*)

com.google.guava:guava-jdk5:13.0
\--- com.google.api-client:google-api-client:1.19.0
     +--- default
     +--- com.google.apis:google-api-services-oauth2:v2-rev77-1.19.0
     |    \--- default
     +--- com.google.apis:google-api-services-plus:v1-rev155-1.19.0
     |    \--- default
     +--- com.google.appengine.tools:appengine-gcs-client:0.4.1
     |    +--- default
     |    +--- com.google.appengine.tools:appengine-mapreduce:0.8
     |    |    \--- default
     |    \--- com.google.appengine.tools:appengine-pipeline:0.2.10
     |         \--- com.google.appengine.tools:appengine-mapreduce:0.8 (*)
     +--- com.google.api-client:google-api-client-appengine:1.17.0-rc
     |    \--- com.google.appengine.tools:appengine-gcs-client:0.4.1 (*)
     +--- com.google.apis:google-api-services-storage:v1-rev1-1.18.0-rc
     |    \--- com.google.appengine.tools:appengine-gcs-client:0.4.1 (*)
     +--- com.google.apis:google-api-services-bigquery:v2-rev154-1.19.0
     |    \--- com.google.appengine.tools:appengine-mapreduce:0.8 (*)
     \--- com.google.api-client:google-api-client-servlet:1.17.0-rc
          \--- com.google.api-client:google-api-client-appengine:1.17.0-rc (*)

(*) - dependencies omitted (listed previously)

我已尝试通过以下方式删除对 : 的依赖:

compile ('com.google.api-client:google-api-client:1.19.0')
        exclude group: 'com.google.guava', module: 'guava-jdk5'
    
compile ('com.google.api-client:google-api-client:1.19.0')
        exclude group: 'com.google.guava', 
    

但dependencyInsight 保持不变。 我也试过了

compile ('com.google.guava:guava:15.0')force = true

但是依赖洞察力仍然保持不变。 如何摆脱 com.google.guava:guava-jdk5:13.0 ?

详情: 我在 Windows 8.1 机器上尝试过 gradle 1.2 和 2.1

我尝试这个的原因是为了摆脱这个异常:

java.lang.NoSuchMethodError: com.google.common.base.Stopwatch.createStarted()Lcom/google/common/base/Stopwatch;

【问题讨论】:

如果您在命令行上清理和构建(即不涉及 IDE),是否会出现此库? 我正在通过命令行运行它。该错误仅在运行时发生 【参考方案1】:

如果某处有另一个依赖项指向相同的依赖项而没有任何排除项,则似乎不会排除依赖项。

您可以通过configuration 排除依赖项:

configurations 
  all*.exclude group: 'com.google.guava', module:'guava-jdk5'

【讨论】:

这对我有用。谢谢!但就个人而言,我不喜欢 gradle 处理依赖项的方式。 Maven 更加清晰和简单。【参考方案2】:

基于@thoutbeckers 的回答,由于一个特殊情况,我认为他的回答并不适用,但它确实适用。希望这个答案可以帮助其他分享我的特殊情况问题的人。最初我认为错误的传递依赖项仅被build.gradle 文件中的一个依赖项引用,但实际上它被两个依赖项引用。这是因为引用错误传递依赖的两个依赖都具有父/子关系,但我只注意到与子依赖的关系,而不是父依赖。

考虑以下依赖树(由命令gradle <my-project-name>:dependencies 生成):

compileClasspath - Compile classpath for source set 'main'.
+--- my.org:com.my.pkg.parent:6.+ -> 6.0.4
|    +--- # misc. dependencies
|    +--- my.org:com.my.pkg.child:6.0.4
|    |    +--- # misc. dependencies
|    |    +--- other.org:bad.transitive.dependency:0.9.1 FAILED
|    |    +--- # misc. dependencies
|    |--- # misc. dependencies
+--- # misc. dependencies

从依赖关系树看来,other.org:bad.transitive:dependency:0.9.1 似乎只被构建文件中的一个依赖项引用,而不是两个。但是,假设您的 Gradle 文件如下所示:

// ... misc. ...
dependencies 
    // ... misc. dependencies ...
    compile 'my.org:com.my.pkg.parent:6.+'
    // ... misc. dependencies ...
    compile ('my.org:com.my.pkg.child:6.0.4') 
        exclude group: 'other.org', module: 'bad.transitive.dependency'

对于像上面这样的 Gradle 文件,即使您要排除的传递依赖项仅发生在子依赖项中,而不是父依赖项中,错误也会持续存在。但是,因为父项目和子项目都被 build.gradle 文件引用,所以必须从这两个依赖项中排除错误的传递依赖项,正如上面的 @thoutbeckers 所述。

请注意,如果您不想在配置级别添加排除项(正如@thoutbeckers 在他们的回答中显示的那样),您始终可以明确地从引用它的两个依赖项中排除传递依赖项。

【讨论】:

【参考方案3】:

原来 guava-jdk5 还在维护中。

所以我改变了这个:

compile ('com.google.guava:guava:15.0')force = true

为此:

compile('com.google.guava:guava-jdk5:17.0')  force = true 

这解决了我的问题,我现在可以使用 Google App Engine 项目中“com.google.common”包中的类以及所有描述的依赖项

【讨论】:

不,在我看来,JDK5 变体没有得到维护。 Guava 最高为 18.0,但 jdk5 变体没有 18。见 search.maven.org/…【参考方案4】:

我遇到了gradle dependencies这种奇怪行为的几个原因:

事实证明,Gradle 4.10.x 在其守护进程中缓存了一些临时结果,因此仅运行命令可能不是最新的。因此,请禁用 Gradle 守护程序。 还有其他工具和 IDE(Eclipse 等)可以运行 Gradle 守护程序以进行自己的集成和项目构建。因此,检查其他守护进程并杀死它们 似乎有一些额外的缓存,即使禁用了守护程序,因此请运行 gradle clean dependencies 考虑设置环境变量GRADLE_OPTS=-Dorg.gradle.daemon=false -Dorg.gradle.caching=false 以避免缓存或在命令行中提供这些选项 dependencies 报告本身具有欺骗性,因为它可能不会显示(也未指明)通过其他路径到达的相同不需要的依赖项的下一次出现。然后从第一条路径中排除传递的不需要的依赖项不起作用并且仍然在该路径上显示它,无论它来自另一个(不可见)路径。

识别所有路径通过并从所有路径中排除不需要的依赖项。

注释掉第一个路径/依赖运行gradle clean dependencies 以找到到达依赖的下一个路径。重复直到找到所有此类路径。然后取消注释并从所有标识的路径中排除不需要的依赖项。

【讨论】:

【参考方案5】:

似乎 Gradle 的工作方式是每个依赖项都会带来其所有传递依赖项。如果您将其中一些从一个依赖项中排除,它们可能是由其他依赖项带来的。

如果你有

compile 'com.google.api-client:google-api-client:1.19.0'
compile 'com.google.apis:google-api-services-oauth2:v2-rev77-1.19.0'
compile 'com.google.apis:google-api-services-plus:v1-rev155-1.19.0'

为了从构建过程中排除com.google.guava:guava-jdk5,您必须从它们中排除它:

compile ('com.google.api-client:google-api-client:1.19.0') 
    exclude group: 'com.google.guava', module: 'guava-jdk5'

compile ('com.google.apis:google-api-services-oauth2:v2-rev77-1.19.0') 
    exclude group: 'com.google.guava', module: 'guava-jdk5'

compile ('com.google.apis:google-api-services-plus:v1-rev155-1.19.0') 
    exclude group: 'com.google.guava', module: 'guava-jdk5'

dependencyInsight 可以帮助找出在哪里放置exclude。它显示了在其传递依赖项中具有特定依赖项的依赖项列表(不幸的是,它没有显示其中哪些已经在配置中排除了它)


更简单的方法是从整个配置(或从所有配置)中排除依赖:

configurations.all 
    exclude group: 'com.google.guava', module: 'guava-jdk5'

参考:https://docs.gradle.org/current/userguide/resolution_rules.html#excluding_a_dependency_from_a_configuration_completely

【讨论】:

以上是关于Gradle 传递依赖排除未按预期工作。 (我如何摆脱 com.google.guava:guava-jdk5:13.0 ?)的主要内容,如果未能解决你的问题,请参考以下文章

Gradle - 排除嵌套的传递依赖

XSLT - 使用隧道传递变量未按预期工作

Android Gradle 插件Gradle 依赖管理 ⑦ ( dependencies 传递依赖设置 | transitive 关闭依赖传递配置 | exclude 排除子依赖配置 )

Wordpress 下一篇文章链接,未按预期工作

Gradle 排除依赖非常混乱

Gradle-5.3:依赖-管理依赖的版本(传递(transitive)排除(exclude)强制(force)动态版本(+))