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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/25792398/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-11-02 08:42:22  来源:igfitidea点击:

Gradle Transitive dependency exclusion is not working as expected. (How do I get rid of com.google.guava:guava-jdk5:13.0 ?)

javagoogle-app-enginemapreducegradleguava

提问by unify

here is a snippet of my build.gradle:

这是我的 build.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'
compile 'com.google.appengine.tools:appengine-gcs-client:0.4.1'
compile 'com.google.appengine.tools:appengine-mapreduce:0.8'

which imports multiple version of guava as you can see with dependencyInsight:

它导入了多个版本的番石榴,您可以使用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)

I have tried removing the dependency to : by doing:

我尝试通过执行以下操作来删除对 : 的依赖:

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

but the dependencyInsight remains the same. I also tried

但dependencyInsight 保持不变。我也试过

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

but again dependency insight remains the same. How do I get rid of com.google.guava:guava-jdk5:13.0 ?

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

Details: I've tried gradle 1.2 and 2.1 on a windows 8.1 box

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

The reason for me to try this is to get rid of this exception:

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

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

采纳答案by unify

It turns out that guava-jdk5 is still being maintained.

原来guava-jdk5还在维护中。

So I changed this:

所以我改变了这个:

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

for this:

为了这:

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

And that fixed my issues, I can now use classes from the 'com.google.common' package in Google App Engine project with all the described dependencies

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

回答by thoutbeckers

It seems a dependency will not be excluded if there is another dependency somewhere that points to that same dependency without any of the excludes.

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

You can exclude a dependency through configurationhowever:

但是,您可以通过以下方式排除依赖项configuration

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

回答by entpnerd

Building on @thoutbeckers answer due to a special case, where I didn't think that his answer applied, but it actually did. Hopefully, this answer can help others who shared my special case problem. Originally I thought that the bad transitive dependency was only referenced by one dependency in the build.gradlefile but it was actually referenced by two dependencies. This was because both dependencies where the the bad transitive dependency was referenced from had a parent/child relationship, but I only noticed the relationship with the child dependency, and not the parent dependency.

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

Consider the following dependency tree (produced by the command gradle <my-project-name>:dependencies):

考虑以下依赖树(由命令生成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

From the dependency tree, it looks like the other.org:bad.transitive:dependency:0.9.1is only referenced by one dependency in your build file, not two. However, suppose your Gradle file looks like this:

从依赖关系树来看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'
}

For a Gradle file like the one above, the error will persist even though the transitive dependency you wanted to exclude occurs only in the child dependency, not the parent dependency. However, because both the parent and child projects are referenced by the build.gradlefile, the bad transitive dependency must be excluded from both dependencies, as @thoutbeckers stated above.

对于像上面这样的 Gradle 文件,即使您想要排除的传递依赖只出现在子依赖中,而不是父依赖中,错误也会持续存在。但是,由于build.gradle文件引用了父项目和子项目,因此必须从两个依赖项中排除错误的传递依赖项,如上面@thoutbeckers 所述。

Note that if you don't want to add the exclusion at the configuration level (as @thoutbeckers showed in their answer), you can always just exclude the transitive dependency from both dependencies where it is referenced, explicitly.

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

回答by Rusi Popov

I met several causes of this strange behavior of gradle dependencies:

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

  • it turned out that Gradle 4.10.x caches some interim results in its daemon, so just running the command might not be up to date. Thus, disable the Gradle daemon.
  • there are other tools and IDEs (Eclipse,etc.) that can run the Gradle daemon for their own integration and project build. Thus, check for other daemon processes and kill them
  • there seems to be some additional caching even with disabled daemon, therefore run gradle clean dependenciesinstead
  • consider setting environment variable GRADLE_OPTS=-Dorg.gradle.daemon=false -Dorg.gradle.caching=falseto avoid the caching or provide these options in the command line
  • the dependenciesreport itself is deceptive as it may not show (neither indicate) the next occurrences of the same the unwanted dependency, reached through other paths. Then excluding the transitive the unwanted dependency from the first path does not workand still shows it on that path, no matter that it came through another (invisible) path.
  • 事实证明,Gradle 4.10.x 在其守护进程中缓存了一些临时结果,因此仅运行该命令可能不是最新的。因此,禁用 Gradle 守护进程。
  • 还有其他工具和 IDE(Eclipse 等)可以运行 Gradle 守护程序以进行自己的集成和项目构建。因此,检查其他守护进程并杀死它们
  • 即使禁用了守护进程,似乎还有一些额外的缓存,因此gradle clean dependencies改为运行
  • 考虑设置环境变量GRADLE_OPTS=-Dorg.gradle.daemon=false -Dorg.gradle.caching=false以避免缓存或在命令行中提供这些选项
  • dependencies报告本身是具有欺骗性的,因为它可能不会显示(也不会指示)通过其他路径到达的相同不需要的依赖项的下一次出现。然后从第一条路径排除不需要的传递性依赖项不起作用,并且仍然在该路径上显示它,无论它来自另一个(不可见的)路径。

Identify all pathsthe the unwanted dependency is reached through and exclude it from all of them.

确定不需要的依赖项通过的所有路径,并将其从所有路径中排除。

Comment out the first path / dependency run gradle clean dependenciesto find the next path the dependency is reached through. Repeat until all such paths found. Then uncomment and exclude the unwanted dependency from all paths identified.

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