Gradle 提供了导航依赖关系图和缓解依赖地狱的工具。用户可以呈现完整的依赖关系图,并确定依赖关系的选择原因和来源。依赖关系可以通过构建脚本声明的依赖关系或传递依赖关系产生。您可以使用以下方式可视化依赖关系:

  • 内置 Gradle CLIdependencies任务

  • 内置 Gradle CLIdependencyInsight任务

  • 构建扫描

列出项目依赖项

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

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

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

输出注释

dependencies任务使用以下注释标记依赖关系树:

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

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

  • (n):无法解析的依赖项或依赖项配置。

指定依赖配置

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

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

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

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

例子

考虑一个使用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'
}

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

依赖管理依赖洞察报告构建扫描

依赖性洞察

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. 术语
原因 意义

(缺席的)

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

请求:<文本>

依赖关系出现在图中,并且包含内容带有because文本

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

依赖项以动态版本显示,但不包括列出的版本。后面可能会附有一段because文字。

被请求:拒绝版本 <versions>

该依赖项以包含一个或多个reject.后面可能会附有一段because文字。

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

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

通过约束

依赖约束参与了版本选择。后面可能会附有一段because文字。

由祖先

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

按规则选择

依赖性解析规则推翻了默认选择过程。后面可能会附有一段because文字。

拒绝:按规则 <version> 因为 <text>

AComponentSelection.reject 拒绝了给定版本的依赖项。

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

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

被迫

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

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

故障排除

版本冲突

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

变体选择错误

有时,选择错误会发生在变体选择级别。请查看专用部分以了解这些错误以及如何解决它们。

不安全配置解析错误

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

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

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

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

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

Gradle 会为每次不安全访问生成弃用警告。不安全的访问可能会导致不确定的错误。您应该修复构建中的不安全访问警告。

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

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