Gradle 提供了工具来浏览依赖项图并减轻依赖项混乱。用户可以呈现完整的依赖项图,以及识别依赖项的选择原因和来源。依赖项可以通过构建脚本声明的依赖项或传递依赖项来生成。您可以使用以下方式可视化依赖项

  • 内置 Gradle CLI dependencies 任务

  • 内置 Gradle CLI dependencyInsight 任务

  • 构建扫描

列出项目依赖项

Gradle 提供了内置的 dependencies 任务,用于从命令行呈现依赖项树。默认情况下,依赖项树会呈现配置中所有单个项目的依赖项。依赖项树指示每个依赖项所选的版本。它还显示有关依赖项冲突解决的信息。

dependencies 任务对于与传递依赖项相关的问题特别有用。您的构建文件列出了直接依赖项,但 dependencies 任务可以帮助您了解在构建期间解析了哪些传递依赖项。

可以在buildscript classpath配置中声明的依赖项图使用任务buildEnvironment呈现。

输出注释

dependencies 任务使用以下注释标记依赖项树

  • (*):指示传递依赖项子树的重复出现。Gradle 仅在每个项目中展开传递依赖项子树一次;重复出现仅显示子树的根,后跟此注释。

  • (c):此元素是 依赖项约束,而不是依赖项。在树中的其他位置查找匹配的依赖项。

  • (n):无法解析的依赖项或依赖项配置,请参见 无法解析

指定依赖项配置

要重点关注一个依赖项配置的信息,请提供可选参数 --configuration。就像 项目和任务名称 一样,Gradle 接受缩写名称来选择依赖项配置。例如,如果模式与单个依赖项配置匹配,则可以指定 tRC 而不是 testRuntimeClasspath。以下两个示例都显示了 Java 项目的 testRuntimeClasspath 依赖项配置中的依赖项

> gradle -q dependencies --configuration testRuntimeClasspath
> gradle -q dependencies --configuration tRC

要查看项目中所有可用配置的列表(包括任何插件添加的配置),可以运行 resolvableConfigurations 报告。

有关更多信息,请参阅该插件的文档(例如,Java 插件在此处记录 here)。

示例

考虑一个使用 JGit 库 为发布过程执行源代码管理 (SCM) 操作的项目。您可以借助 自定义依赖项配置 为外部工具声明依赖项。这避免了污染其他上下文,例如生产源代码的编译类路径。

以下示例声明了一个名为“scm”的自定义依赖项配置,其中包含 JGit 依赖项

build.gradle.kts
repositories {
    mavenCentral()
}

configurations {
    create("scm")
}

dependencies {
    "scm"("org.eclipse.jgit:org.eclipse.jgit:4.9.2.201712150930-r")
}
build.gradle
repositories {
    mavenCentral()
}

configurations {
    scm
}

dependencies {
    scm 'org.eclipse.jgit:org.eclipse.jgit:4.9.2.201712150930-r'
}

使用以下命令查看 scm 依赖项配置的依赖项树

> gradle -q dependencies --configuration scm

------------------------------------------------------------
Root project 'dependencies-report'
------------------------------------------------------------

scm
\--- org.eclipse.jgit:org.eclipse.jgit:4.9.2.201712150930-r
     +--- com.jcraft:jsch:0.1.54
     +--- com.googlecode.javaewah:JavaEWAH:1.1.6
     +--- org.apache.httpcomponents:httpclient:4.3.6
     |    +--- org.apache.httpcomponents:httpcore:4.3.3
     |    +--- commons-logging:commons-logging:1.1.3
     |    \--- commons-codec:commons-codec:1.6
     \--- org.slf4j:slf4j-api:1.7.2

A web-based, searchable dependency report is available by adding the --scan option.

识别所选依赖项版本

一个项目可能会直接或间接请求同一依赖项的两个不同版本。Gradle 应用 版本冲突解决 以确保依赖项图中仅存在一个版本的依赖项。以下示例引入了与 commons-codec:commons-codec 的冲突,该冲突同时作为直接依赖项和 JGit 的传递依赖项添加

build.gradle.kts
repositories {
    mavenCentral()
}

configurations {
    create("scm")
}

dependencies {
    "scm"("org.eclipse.jgit:org.eclipse.jgit:4.9.2.201712150930-r")
    "scm"("commons-codec:commons-codec:1.7")
}
build.gradle
repositories {
    mavenCentral()
}

configurations {
    scm
}

dependencies {
    scm 'org.eclipse.jgit:org.eclipse.jgit:4.9.2.201712150930-r'
    scm 'commons-codec:commons-codec:1.7'
}

构建扫描 中的依赖项树显示有关冲突的信息。单击依赖项并选择“所需”选项卡以查看依赖项的选择原因和来源。

dependency management dependency insight report build scan

依赖项见解

Gradle 提供内置的 dependencyInsight 任务,用于从命令行呈现依赖项洞察报告。依赖项洞察提供有关单个 配置 中单个依赖项的信息。给定一个依赖项,您可以识别选择原因和来源。

dependencyInsight 接受以下参数

--dependency <dependency>(必需)

要调查的依赖项。您可以提供完整的 group:name,或其一部分。如果有多个依赖项匹配,Gradle 会生成涵盖所有匹配依赖项的报告。

--configuration <name>(必需)

解析给定依赖项的依赖项配置。对于使用 Java 插件 的项目,此参数是可选的,因为该插件提供了 compileClasspath 的默认值。

--single-path(可选)

仅呈现到依赖项的单一路径。

以下代码段演示了如何在“scm”配置中为名为“commons-codec”的依赖项的所有路径运行依赖项洞察报告

> gradle -q dependencyInsight --dependency commons-codec --configuration scm
commons-codec:commons-codec:1.7
  Variant default:
    | Attribute Name    | Provided | Requested |
    |-------------------|----------|-----------|
    | org.gradle.status | release  |           |
   Selection reasons:
      - By conflict resolution: between versions 1.7 and 1.6

commons-codec:commons-codec:1.7
\--- scm

commons-codec:commons-codec:1.6 -> 1.7
\--- org.apache.httpcomponents:httpclient:4.3.6
     \--- org.eclipse.jgit:org.eclipse.jgit:4.9.2.201712150930-r
          \--- scm

A web-based, searchable dependency report is available by adding the --scan option.

有关配置的更多信息,请参阅 依赖项配置文档

选择原因

依赖项洞察报告的“选择原因”部分列出了选择依赖项的原因。请查看下表以了解所用不同术语的含义

表 1. 术语
原因 含义

(不存在)

除了直接或传递引用之外,没有其他原因。

已请求:<text>

依赖项出现在图表中,并且包含 because 文本

已请求:与版本 <versions> 不匹配

依赖项出现时带有 动态版本,其中不包括列出的版本。后面可能会跟一个 because 文本。

已请求:拒绝版本 <versions>

依赖项出现时带有 丰富版本,其中包含一个或多个 reject。后面可能会跟一个 because 文本。

通过冲突解决:在版本 <version> 之间

依赖项出现多次,版本请求不同。这导致 冲突解决,以选择最合适的版本。

通过约束

一个 依赖项约束 参与了版本选择。后面可能会跟一个 because 文本。

通过祖先

有一个 丰富版本,其中带有 strictly,它强制执行此依赖项的版本。

按规则选择

一个 依赖项解析规则 否决了默认选择流程。可能后面会跟一个 because 文本。

拒绝:按规则拒绝 <版本>,原因是 <文本>

一个 ComponentSelection.reject 拒绝了给定版本 的依赖项。

拒绝:版本 <版本>:<属性信息>

依赖项具有动态版本,某些版本与 请求的属性 不匹配。

强制

构建通过强制平台或解析策略强制执行依赖项的版本。

如果存在多个选择原因,洞察报告会列出所有原因。

故障排除

版本冲突

如果所选版本与你的预期不符,Gradle 提供了一系列工具来帮助你 控制传递依赖项

变体选择错误

有时选择错误发生在 变体选择级别。请参阅 专门的部分 来了解这些错误以及如何解决它们。

不安全的配置解析错误

解析配置可能会对 Gradle 的项目模型产生副作用。因此,Gradle 必须管理对每个项目的配置的访问。配置可能以多种方式不安全地解析。例如

  • 一个项目中的任务直接在任务的操作中解析另一个项目中的配置。

  • 一个任务将另一个项目中的配置指定为输入文件集合。

  • 一个项目的构建脚本在评估期间解析另一个项目中的配置。

  • 项目配置在设置文件中解析。

Gradle 会针对每次不安全的访问产生弃用警告。不安全的访问会导致不确定的错误。你应该 修复构建中的不安全访问警告

在大多数情况下,您可以通过创建对其他项目的跨项目依赖关系来解决不安全的访问。有关详细信息,请参阅在项目之间共享输出的文档。

如果您发现无法使用这些技术解决的用例,请通过提交GitHub 问题告知我们。