Gradle 中是否共享子依赖项?

Are sub-dependencies shared in Gradle?

如果库 LXY 项目的依赖项,并且您的 MainModule 有:

implementation X
implementation Y

XY 共享相同的 L 吗?如果 X 需要与 Y 不同的 L 版本怎么办?

它在 Gradle 文档中有清楚的描述:TL;DR 在版本冲突的情况下,默认是 select 具有最高版本的依赖项。但请注意 version conflict resolution can be customized.

Version conflict resolution

A version conflict occurs when two components:

  • Depend on the same module, let’s say com.google.guava:guava

  • But on different versions, let’s say 20.0 and 25.1-android

    • Our project itself depends on com.google.guava:guava:20.0

    • Our project also depends on com.google.inject:guice:4.2.2 which itself depends on com.google.guava:guava:25.1-android

Resolution strategy

Given the conflict above, there exist multiple ways to handle it, either by selecting a version or failing the resolution. Different tools that handle dependency management have different ways of handling these type of conflicts.

Apache Maven uses a nearest first strategy.

Maven will take the shortest path to a dependency and use that version. In case there are multiple paths of the same length, the first one wins.

This means that in the example above, the version of guava will be 20.0 because the direct dependency is closer than the guice dependency.

The main drawback of this method is that it is ordering dependent. Keeping order in a very large graph can be a challenge. For example, what if the new version of a dependency ends up having its own dependency declarations in a different order than the previous version?

With Maven, this could have unwanted impact on resolved versions.

Apache Ivy is a very flexible dependency management tooling. It offers the possibility to customize dependency resolution, including conflict resolution.

This flexibility comes with the price of making it hard to reason about.

Gradle will consider all requested versions, wherever they appear in the dependency graph. Out of these versions, it will select the highest one.

As you have seen, Gradle supports a concept of rich version declaration, so what is the highest version depends on the way versions were declared:

  • If no ranges are involved, then the highest version that is not rejected will be selected.

    • If a version declared as strictly is lower than that version, selection will fail.
  • If ranges are involved:

    • If there is a non range version that falls within the specified ranges or is higher than their upper bound, it will be selected.

    • If there are only ranges, the highest existing version of the range with the highest upper bound will be selected.

    • If a version declared as strictly is lower than that version, selection will fail.

Note that in the case where ranges come into play, Gradle requires metadata to determine which versions do exist for the considered range. This causes an intermediate lookup for metadata, as described in How Gradle retrieves dependency metadata?.

-- https://docs.gradle.org/current/userguide/dependency_resolution.html#sec:version-conflict