在查看依赖项声明本身之前,需要定义依赖项配置的概念。

什么是依赖配置

为 Gradle 项目声明的每个依赖项都适用于特定范围。例如,一些依赖项应该用于编译源代码,而其他依赖项只需要在运行时可用。 Gradle 在Configuration的帮助下表示依赖项的范围。每个配置都可以通过唯一的名称来标识。

许多 Gradle 插件都会向您的项目添加预定义的配置。例如,Java 插件添加配置来表示源代码编译、执行测试等所需的各种类路径。有关示例,请参阅Java 插件章节。

依赖管理配置
图 1. 配置将声明的依赖项用于特定目的

有关使用配置来导航、检查和后处理分配的依赖项的元数据和工件的更多示例,请查看解析结果 API

配置继承和组合

一个配置可以扩展其他配置以形成继承层次结构。子配置继承为其任何超级配置声明的整套依赖项。

配置继承被 Gradle 核心插件(例如Java 插件)大量使用。例如,testImplementation配置扩展implementation配置。配置层次结构有一个实际目的:编译测试需要在编写测试类所需的依赖项之上添加被测源代码的依赖项。使用 JUnit 编写和执行测试代码的 Java 项目如果在生产源代码中导入其类,也需要 Guava。

依赖管理配置继承
图 2. Java 插件提供的配置继承

在底层,配置testImplementation通过implementation调用方法Configuration.extendsFrom(org.gradle.api.artifacts.Configuration[])形成继承层次结构。配置可以扩展任何其他配置,无论其在构建脚本或插件中的定义如何。

假设您想编写一套冒烟测试。每个冒烟测试都会进行 HTTP 调用来验证 Web 服务端点。该项目已经使用 JUnit 作为底层测试框架。您可以定义一个名为的新配置smokeTest,该配置从testImplementation配置扩展以重用现有的测试框架依赖项。

build.gradle.kts
val smokeTest by configurations.creating {
    extendsFrom(configurations.testImplementation.get())
}

dependencies {
    testImplementation("junit:junit:4.13")
    smokeTest("org.apache.httpcomponents:httpclient:4.5.5")
}
build.gradle
configurations {
    smokeTest.extendsFrom testImplementation
}

dependencies {
    testImplementation 'junit:junit:4.13'
    smokeTest 'org.apache.httpcomponents:httpclient:4.5.5'
}

可解析和消耗性配置

配置是 Gradle 中依赖解析的基本部分。在依赖性解析的上下文中,区分消费者生产者很有用。沿着这些思路,配置至少有 3 个不同的角色:

  1. 声明依赖关系

  2. 作为消费者,解决一组对文件的依赖关系

  3. 作为生产者,公开工件及其依赖项以供其他项目使用(此类消耗性配置通常代表生产者向其消费者提供的变体)

例如,要表达一个应用程序app 依赖于library lib至少需要一项配置:

build.gradle.kts
// declare a "configuration" named "someConfiguration"
val someConfiguration by configurations.creating

dependencies {
    // add a project dependency to the "someConfiguration" configuration
    someConfiguration(project(":lib"))
}
build.gradle
configurations {
    // declare a "configuration" named "someConfiguration"
    someConfiguration
}
dependencies {
    // add a project dependency to the "someConfiguration" configuration
    someConfiguration project(":lib")
}

配置可以通过扩展来继承其他配置的依赖关系。现在,请注意,上面的代码没有告诉我们有关此配置的预期使用者的任何信息。特别是,它没有告诉我们如何使用该配置。假设这lib是一个 Java 库:它可能会公开不同的内容,例如 API、实现或测试装置。可能有必要app根据我们正在执行的任务(根据 的 API 进行编译lib、执行应用程序、编译测试等)来更改解决依赖关系的方式。为了解决这个问题,您经常会找到配套配置,它们旨在明确声明用法:

build.gradle.kts
configurations {
    // declare a configuration that is going to resolve the compile classpath of the application
    compileClasspath {
        extendsFrom(someConfiguration)
    }

    // declare a configuration that is going to resolve the runtime classpath of the application
    runtimeClasspath {
        extendsFrom(someConfiguration)
    }
}
build.gradle
configurations {
    // declare a configuration that is going to resolve the compile classpath of the application
    compileClasspath.extendsFrom(someConfiguration)

    // declare a configuration that is going to resolve the runtime classpath of the application
    runtimeClasspath.extendsFrom(someConfiguration)
}

此时,我们有 3 种不同的配置,具有不同的角色:

  • someConfiguration声明我的应用程序的依赖项。它只是依赖项的集合。

  • compileClasspath和是要解析的runtimeClasspath配置:解析后它们应分别包含应用程序的编译类路径和运行时类路径。

canBeResolved这种区别由类型中的标志来表示Configuration可以解析的配置是我们可以计算依赖图的配置,因为它包含解析发生的所有必要信息。也就是说,我们将计算依赖图,解析图中的组件,并最终获得工件。已canBeResolved设置为 的配置false并不意味着将被解析。这样的配置只是为了声明依赖关系。原因是根据使用情况(编译类路径、运行时类路径),它可以解析为不同的图。尝试解析已canBeResolved设置为 的配置是错误的false。在某种程度上,这类似于不应该被实例化的抽象类( = false ) 和扩展抽象类 ( = true ) 的具体类。可解析配置将扩展至少一种不可解析配置(并且可以扩展多个)。canBeResolvedcanBeResolved

另一方面,在库项目端(生产者,我们也使用配置来表示可以使用的内容。例如,库可能会公开 API 或运行时,我们会将工件附加到其中之一、另一个或两者。通常,要针对 进行编译lib,我们需要 的 API lib,但不需要其运行时依赖项。因此该lib项目将公开一个apiElements配置,该配置针对寻找其 API 的消费者。这样的配置是可消耗的,但并不意味着要解决。这是通过a 的canBeConsumedConfiguration标志来表达的:

build.gradle.kts
configurations {
    // A configuration meant for consumers that need the API of this component
    create("exposedApi") {
        // This configuration is an "outgoing" configuration, it's not meant to be resolved
        isCanBeResolved = false
        // As an outgoing configuration, explain that consumers may want to consume it
        assert(isCanBeConsumed)
    }
    // A configuration meant for consumers that need the implementation of this component
    create("exposedRuntime") {
        isCanBeResolved = false
        assert(isCanBeConsumed)
    }
}
build.gradle
configurations {
    // A configuration meant for consumers that need the API of this component
    exposedApi {
        // This configuration is an "outgoing" configuration, it's not meant to be resolved
        canBeResolved = false
        // As an outgoing configuration, explain that consumers may want to consume it
        assert canBeConsumed
    }
    // A configuration meant for consumers that need the implementation of this component
    exposedRuntime {
        canBeResolved = false
        assert canBeConsumed
    }
}

canBeResolved简而言之,配置的角色由和canBeConsumed标志组合确定:

表 1. 配置角色

配置角色

可以解决

可以食用

依赖范围

错误的

错误的

解决特定用途

真的

错误的

暴露给消费者

错误的

真的

旧版,请勿使用

真的

真的

为了向后兼容,两个标志都有一个默认值true,但作为插件作者,您应该始终确定这些标志的正确值,否则您可能会意外地引入解析错误。

为依赖项选择正确的配置

选择声明依赖项的配置非常重要。然而,没有固定的规则依赖项必须进入哪个配置。它主要取决于配置的组织方式,这通常是所应用插件的属性。

例如,在java插件中,创建的配置被记录下来,并且应该作为根据其在代码中的角色确定在何处声明依赖项的基础。

作为建议,插件应清楚地记录其配置链接在一起的方式,并应尽可能努力隔离其角色

已弃用的配置

配置旨在用于单个角色:声明依赖项、执行解析或定义可使用的变体。过go,某些配置没有定义它们的用途。当以非预期方式使用配置时,会发出弃用警告。要修复弃用问题,您需要停止使用已弃用角色中的配置。所需的确切更改取决于配置的使用方式以及是否存在应使用的替代配置。

定义自定义配置

您可以自己定义配置,即所谓的自定义配置。自定义配置对于分离专用目的所需的依赖关系范围非常有用。

假设您想要声明对Jasper Ant 任务的依赖关系,以便预编译 JSP 文件,这些文件不应出现在编译源代码的类路径中。通过引入自定义配置并在任务中使用它来实现该目标相当简单。

build.gradle.kts
val jasper by configurations.creating

repositories {
    mavenCentral()
}

dependencies {
    jasper("org.apache.tomcat.embed:tomcat-embed-jasper:9.0.2")
}

tasks.register("preCompileJsps") {
    val jasperClasspath = jasper.asPath
    val projectLayout = layout
    doLast {
        ant.withGroovyBuilder {
            "taskdef"("classname" to "org.apache.jasper.JspC",
                      "name" to "jasper",
                      "classpath" to jasperClasspath)
            "jasper"("validateXml" to false,
                     "uriroot" to projectLayout.projectDirectory.file("src/main/webapp").asFile,
                     "outputDir" to projectLayout.buildDirectory.file("compiled-jsps").get().asFile)
        }
    }
}
build.gradle
configurations {
    jasper
}

repositories {
    mavenCentral()
}

dependencies {
    jasper 'org.apache.tomcat.embed:tomcat-embed-jasper:9.0.2'
}

tasks.register('preCompileJsps') {
    def jasperClasspath = configurations.jasper.asPath
    def projectLayout = layout
    doLast {
        ant.taskdef(classname: 'org.apache.jasper.JspC',
                    name: 'jasper',
                    classpath: jasperClasspath)
        ant.jasper(validateXml: false,
                   uriroot: projectLayout.projectDirectory.file('src/main/webapp').asFile,
                   outputDir: projectLayout.buildDirectory.file("compiled-jsps").get().asFile)
    }
}

您可以使用对象管理项目配置configurations。配置有一个名称并且可以相互扩展。要了解有关此 API 的更多信息,请查看ConfigurationContainer

不同类型的依赖关系

模块依赖

模块依赖是最常见的依赖。它们引用存储库中的模块。

build.gradle.kts
dependencies {
    runtimeOnly(group = "org.springframework", name = "spring-core", version = "2.5")
    runtimeOnly("org.springframework:spring-aop:2.5")
    runtimeOnly("org.hibernate:hibernate:3.0.5") {
        isTransitive = true
    }
    runtimeOnly(group = "org.hibernate", name = "hibernate", version = "3.0.5") {
        isTransitive = true
    }
}
build.gradle
dependencies {
    runtimeOnly group: 'org.springframework', name: 'spring-core', version: '2.5'
    runtimeOnly 'org.springframework:spring-core:2.5',
            'org.springframework:spring-aop:2.5'
    runtimeOnly(
        [group: 'org.springframework', name: 'spring-core', version: '2.5'],
        [group: 'org.springframework', name: 'spring-aop', version: '2.5']
    )
    runtimeOnly('org.hibernate:hibernate:3.0.5') {
        transitive = true
    }
    runtimeOnly group: 'org.hibernate', name: 'hibernate', version: '3.0.5', transitive: true
    runtimeOnly(group: 'org.hibernate', name: 'hibernate', version: '3.0.5') {
        transitive = true
    }
}

有关更多示例和完整参考,请参阅API 文档中的DependencyHandler类。

Gradle 为模块依赖项提供了不同的表示法。有字符串符号和地图符号。模块依赖项有一个允许进一步配置的 API。查看ExternalModuleDependency以了解有关 API 的所有信息。该API提供属性和配置方法。通过字符串表示法,您可以定义属性的子集。使用地图符号,您可以定义所有属性。要使用映射或字符串表示法访问完整的 API,您可以将单个依赖项与闭包一起分配给配置。

如果您声明模块依赖项,Gradle 会在存储库中查找模块元数据文件(.module.pom或)。ivy.xml如果这样的模块元数据文件存在,则对其进行解析并下载该模块的工件(例如hibernate-3.0.5.jar)及其依赖项(例如)。cglib如果不存在这样的模块元数据文件,从 Gradle 6.0 开始,您需要配置元数据源定义以查找hibernate-3.0.5.jar直接调用的工件文件。

在 Maven 中,一个模块只能有一个工件。

在 Gradle 和 Ivy 中,一个模块可以有多个工件。每个工件可以有一组不同的依赖关系。

文件依赖关系

项目有时不依赖二进制存储库产品(例如 JFrog Artifactory 或 Sonatype Nexus)来托管和解决外部依赖项。通常的做法是将这些依赖项托管在共享驱动器上,或者将它们与项目源代码一起签入版本控制。这些依赖项被称为文件依赖项,原因是它们代表一个没有附加任何元数据(如有关传递依赖项、来源或其作者的信息)的文件。

依赖管理文件依赖
图 3. 解决本地文件系统和共享驱动器的文件依赖性

以下示例解析目录antlibs和中的文件依赖性tools

build.gradle.kts
configurations {
    create("antContrib")
    create("externalLibs")
    create("deploymentTools")
}

dependencies {
    "antContrib"(files("ant/antcontrib.jar"))
    "externalLibs"(files("libs/commons-lang.jar", "libs/log4j.jar"))
    "deploymentTools"(fileTree("tools") { include("*.exe") })
}
build.gradle
configurations {
    antContrib
    externalLibs
    deploymentTools
}

dependencies {
    antContrib files('ant/antcontrib.jar')
    externalLibs files('libs/commons-lang.jar', 'libs/log4j.jar')
    deploymentTools(fileTree('tools') { include '*.exe' })
}

正如您在代码示例中看到的,每个依赖项都必须定义其在文件系统中的确切位置。创建文件引用最重要的方法是 Project.files(java.lang.Object…​)ProjectLayout.files(java.lang.Object…​)Project.fileTree(java.lang.Object) 或者,您可以还以平面目录存储库的形式定义一个或多个文件依赖项的源目录。

a 中的文件顺序FileTree并不稳定,即使在一台计算机上也是如此。这意味着使用此类构造播种的依赖项配置可能会产生具有不同顺序的解析结果,可能会影响使用结果作为输入的任务的可缓存性。files建议尽可能使用更简单的方法。

文件依赖项允许您直接将一组文件添加到配置中,而无需先将它们添加到存储库中。如果您不能或不想将某些文件放入存储库中,这会很有用。或者,如果您根本不想使用任何存储库来存储依赖项。

要添加一些文件作为配置的依赖项,您只需将文件集合作为依赖项传递即可:

build.gradle.kts
dependencies {
    runtimeOnly(files("libs/a.jar", "libs/b.jar"))
    runtimeOnly(fileTree("libs") { include("*.jar") })
}
build.gradle
dependencies {
    runtimeOnly files('libs/a.jar', 'libs/b.jar')
    runtimeOnly fileTree('libs') { include '*.jar' }
}

文件依赖项不包含在项目的已发布依赖项描述符中。但是,文件依赖项包含在同一构建内的传递项目依赖项中。这意味着它们不能在当前构建之外使用,但可以在同一构建内使用。

您可以声明哪些任务为文件依赖项生成文件。例如,当文件由构建生成时,您可以执行此操作。

build.gradle.kts
dependencies {
    implementation(files(layout.buildDirectory.dir("classes")) {
        builtBy("compile")
    })
}

tasks.register("compile") {
    doLast {
        println("compiling classes")
    }
}

tasks.register("list") {
    val compileClasspath: FileCollection = configurations["compileClasspath"]
    dependsOn(compileClasspath)
    doLast {
        println("classpath = ${compileClasspath.map { file: File -> file.name }}")
    }
}
build.gradle
dependencies {
    implementation files(layout.buildDirectory.dir('classes')) {
        builtBy 'compile'
    }
}

tasks.register('compile') {
    doLast {
        println 'compiling classes'
    }
}

tasks.register('list') {
    FileCollection compileClasspath = configurations.compileClasspath
    dependsOn compileClasspath
    doLast {
        println "classpath = ${compileClasspath.collect { File file -> file.name }}"
    }
}
$ gradle -q list
compiling classes
classpath = [classes]

文件依赖项的版本控制

建议明确表达文件依赖关系的意图和具体版本。 Gradle 的版本冲突解决不考虑文件依赖关系。因此,为文件名分配一个版本以指示其附带的不同更改集非常重要。例如,commons-beanutils-1.3.jar让您可以通过发行说明跟踪库的更改。

因此,项目的依赖关系更容易维护和组织。通过分配的版本更容易发现潜在的 API 不兼容性。

项目依赖

软件项目通常将软件组件分解为模块,以提高可维护性并防止强耦合。模块可以定义彼此之间的依赖关系,以便在同一项目中重用代码。

依赖管理项目依赖
图 4. 项目之间的依赖关系

Gradle 可以对模块之间的依赖关系进行建模。这些依赖项称为项目依赖项,因为每个模块都由一个 Gradle 项目表示。

build.gradle.kts
dependencies {
    implementation(project(":shared"))
}
build.gradle
dependencies {
    implementation project(':shared')
}

在运行时,构建会自动确保项目依赖项以正确的顺序构建并添加到类路径中进行编译。创作多项目构建一章更详细地讨论了如何设置和配置多项目构建。

以下示例声明了项目对utilsapi项目的依赖关系web-service。方法Project.project(java.lang.String)通过路径创建对特定子项目的引用。

web-service/build.gradle.kts
dependencies {
    implementation(project(":utils"))
    implementation(project(":api"))
}
web-service/build.gradle
dependencies {
    implementation project(':utils')
    implementation project(':api')
}

类型安全的项目依赖项

类型安全的项目访问器是一项必须显式启用的孵化功能。实施可能随时改变。

要添加对类型安全项目访问器的支持,请将其添加到您的settings.gradle(.kts)文件中:

enableFeaturePreview("TYPESAFE_PROJECT_ACCESSORS")

该表示法的一个问题project(":some:path")是您必须记住您想要依赖的每个项目的路径。另外,更改项目路径需要您更改所有使用项目依赖项的地方,但很容易错过一个或多个出现的地方(因为您必须依赖于搜索和替换)。

从 Gradle 7 开始,Gradle 为项目依赖项提供了一个实验性的类型安全 API。与上面相同的示例现在可以重写为:

web-service/build.gradle.kts
dependencies {
    implementation(projects.utils)
    implementation(projects.api)
}
web-service/build.gradle
dependencies {
    implementation projects.utils
    implementation projects.api
}

类型安全 API 的优点是提供 IDE 完成功能,因此您无需弄清楚项目的实际名称。

如果您添加或删除使用 Kotlin DSL 的项目,并且忘记更新依赖项,构建脚本编译将会失败。

项目访问器是从项目路径映射的。例如,如果项目路径为,:commons:utils:some:lib则项目访问器将为projects.commons.utils.some.lib(这是 的简写符号projects.getCommons().getUtils().getSome().getLib())。

some-lib带有 kebab case ( ) 或 Snake case ( )的项目名称some_lib将在访问器中转换为驼峰式大小写:projects.someLib

模块依赖项的本地分支

如果模块本身是使用 Gradle 构建的,则模块依赖项可以替换为对该模块源的本地分支的依赖项。这可以通过利用复合构建来完成。例如,这允许您通过使用和构建本地修补版本而不是发布的二进制版本来修复应用程序中使用的库中的问题。有关复合构建的部分描述了其详细信息。

Gradle 发行版特定的依赖项

Gradle API 依赖

您可以使用DependencyHandler.gradleApi()方法声明对当前版本 Gradle 的 API 的依赖关系。当您开发自定义 Gradle 任务或插件时,这非常有用。

build.gradle.kts
dependencies {
    implementation(gradleApi())
}
build.gradle
dependencies {
    implementation gradleApi()
}

Gradle TestKit 依赖项

您可以使用 DependencyHandler.gradleTestKit ()方法声明对当前版本 Gradle 的 TestKit API 的依赖项。这对于编写和执行 Gradle 插件和构建脚本的功能测试非常有用。

build.gradle.kts
dependencies {
    testImplementation(gradleTestKit())
}
build.gradle
dependencies {
    testImplementation gradleTestKit()
}

TestKit章节通过示例解释了TestKit的使用。

本地 Groovy 依赖

您可以使用DependencyHandler.localGroovy()方法声明对随 Gradle 分发的 Groovy 的依赖项。当您在 Groovy 中开发自定义 Gradle 任务或插件时,这非常有用。

build.gradle.kts
dependencies {
    implementation(localGroovy())
}
build.gradle
dependencies {
    implementation localGroovy()
}

记录依赖关系

当您声明依赖项或依赖项约束时,您可以提供声明的自定义原因。这使得构建脚本中的依赖项声明和依赖项洞察报告更易于解释。

build.gradle.kts
plugins {
    `java-library`
}

repositories {
    mavenCentral()
}

dependencies {
    implementation("org.ow2.asm:asm:7.1") {
        because("we require a JDK 9 compatible bytecode generator")
    }
}
build.gradle
plugins {
    id 'java-library'
}

repositories {
    mavenCentral()
}

dependencies {
    implementation('org.ow2.asm:asm:7.1') {
        because 'we require a JDK 9 compatible bytecode generator'
    }
}

示例:使用具有自定义原因的依赖性洞察报告

输出gradle -q dependencyInsight --dependency asm
> gradle -q dependencyInsight --dependency asm
org.ow2.asm:asm:7.1
  Variant compile:
    | Attribute Name                 | Provided | Requested    |
    |--------------------------------|----------|--------------|
    | org.gradle.status              | release  |              |
    | org.gradle.category            | library  | library      |
    | org.gradle.libraryelements     | jar      | classes      |
    | org.gradle.usage               | java-api | java-api     |
    | org.gradle.dependency.bundling |          | external     |
    | org.gradle.jvm.environment     |          | standard-jvm |
    | org.gradle.jvm.version         |          | 11           |
   Selection reasons:
      - Was requested: we require a JDK 9 compatible bytecode generator

org.ow2.asm:asm:7.1
\--- compileClasspath

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

解决模块依赖项中的特定工件

每当 Gradle 尝试解析 Maven 或 Ivy 存储库中的模块时,它都会查找元数据文件和默认工件文件(JAR)。如果无法解析这些工件文件,则构建将失败。在某些情况下,您可能需要调整 Gradle 解析依赖项的工件的方式。

  • 该依赖项仅提供不带任何元数据(例如 ZIP 文件)的非标准工件。

  • 模块元数据声明多个工件,例如作为 Ivy 依赖描述符的一部分。

  • 您只想下载特定的工件,而无需在元数据中声明任何传递依赖项。

Gradle 是一种多语言构建工具,不仅限于解析 Java 库。假设您想要使用 JavaScript 作为客户端技术来构建 Web 应用程序。大多数项目将外部 JavaScript 库签入版本控制。外部 JavaScript 库与可重用 Java 库没有什么不同,那么为什么不从存储库下载它呢?

Google Hosted Libraries是流行的开源 JavaScript 库的分发平台。借助仅工件符号,您可以下载 JavaScript 库文件,例如 JQuery。该@字符将依赖项的坐标与工件的文件扩展名分开。

build.gradle.kts
repositories {
    ivy {
        url = uri("https://ajax.googleapis.com/ajax/libs")
        patternLayout {
            artifact("[organization]/[revision]/[module].[ext]")
        }
        metadataSources {
            artifact()
        }
    }
}

configurations {
    create("js")
}

dependencies {
    "js"("jquery:jquery:3.2.1@js")
}
build.gradle
repositories {
    ivy {
        url 'https://ajax.googleapis.com/ajax/libs'
        patternLayout {
            artifact '[organization]/[revision]/[module].[ext]'
        }
        metadataSources {
            artifact()
        }
    }
}

configurations {
    js
}

dependencies {
    js 'jquery:jquery:3.2.1@js'
}

某些模块提供同一工件的不同“风格”,或者它们发布属于特定模块版本但具有不同用途的多个工件。 Java 库通常会发布包含已编译类文件的工件,另一个库仅包含源代码,第三个库包含 Javadoc。

在 JavaScript 中,库可能以未压缩或缩小的工件形式存在。在 Gradle 中,特定的工件标识符称为classifier,该术语通常用于 Maven 和 Ivy 依赖项管理。

假设我们想要下载 JQuery 库的缩小版而不是未压缩的文件。您可以提供分类器min作为依赖项声明的一部分。

build.gradle.kts
repositories {
    ivy {
        url = uri("https://ajax.googleapis.com/ajax/libs")
        patternLayout {
            artifact("[organization]/[revision]/[module](.[classifier]).[ext]")
        }
        metadataSources {
            artifact()
        }
    }
}

configurations {
    create("js")
}

dependencies {
    "js"("jquery:jquery:3.2.1:min@js")
}
build.gradle
repositories {
    ivy {
        url 'https://ajax.googleapis.com/ajax/libs'
        patternLayout {
            artifact '[organization]/[revision]/[module](.[classifier]).[ext]'
        }
        metadataSources {
            artifact()
        }
    }
}

configurations {
    js
}

dependencies {
    js 'jquery:jquery:3.2.1:min@js'
}

支持的元数据格式

外部模块依赖项需要模块元数据(因此,通常,Gradle 可以找出模块的传递依赖项)。为此,Gradle 支持不同的元数据格式。

Gradle 模块元数据文件

Gradle 模块元数据经过专门设计,支持 Gradle 依赖管理模型的所有功能,因此是首选格式。您可以在此处找到其规格

POM文件

Gradle 原生支持Maven POM 文件。值得注意的是,默认情况下 Gradle 将首先查找 POM 文件,但如果该文件包含特殊标记,Gradle 将改用Gradle 模块元数据

常春藤档案

同样,Gradle 支持Apache Ivy 元数据文件。同样,Gradle 将首先查找一个ivy.xml文件,但如果该文件包含特殊标记,Gradle 将使用Gradle 模块元数据