版本目录是一个选定的依赖项列表,可以在构建脚本中引用,从而简化依赖管理。

无需使用字符串表示法直接指定依赖项,您可以从版本目录中选择它们

build.gradle.kts
dependencies {
    implementation(libs.groovy.core)
}
build.gradle
dependencies {
    implementation(libs.groovy.core)
}

在此示例中,libs 代表目录,而 groovy 是其中可用的依赖项。

其中定义 libs.groovy.core 的版本目录是 gradle 目录中的 libs.versions.toml 文件

gradle/libs.versions.toml
[libraries]
groovy-core = { group = "org.codehaus.groovy", name = "groovy", version = "3.0.5" }

版本目录提供了几个优点

  • 类型安全访问器:Gradle 为每个目录生成类型安全访问器,从而在 IDE 中启用自动完成。

  • 集中版本管理:每个目录对构建中的所有项目都可见。

  • 依赖项捆绑包:目录可以将常用依赖项分组到 捆绑包 中。

  • 版本分离:目录可以将依赖项坐标与版本信息分离,从而允许共享版本声明。

  • 冲突解决:与常规依赖项表示法一样,版本目录声明请求的 版本,但在 冲突解决 期间不强制执行它们。

虽然版本目录定义了版本,但它们不会影响依赖项解析过程。由于依赖关系图冲突或通过平台或依赖项管理 API 应用的约束,Gradle 仍然可以选择不同的版本。

在目录中声明的版本通常不会被强制执行,这意味着构建中使用的实际版本可能因依赖项解析而异。

访问目录

要访问在 gradle 目录中标准 libs.versions.toml 文件中定义的版本目录中的项目,请在构建脚本中使用 libs 对象。例如,要引用库,可以使用 libs.<别名>,对于插件,可以使用 libs.plugins.<别名>

使用版本目录声明依赖项

build.gradle.kts
dependencies {
    implementation(libs.groovy.core)
    implementation(libs.groovy.json)
    implementation(libs.groovy.nio)
}
build.gradle
dependencies {
    implementation libs.groovy.core
    implementation libs.groovy.json
    implementation libs.groovy.nio
}

与...相同

build.gradle.kts
dependencies {
    implementation("org.codehaus.groovy:groovy:3.0.5")
    implementation("org.codehaus.groovy:groovy-json:3.0.5")
    implementation("org.codehaus.groovy:groovy-nio:3.0.5")
}
build.gradle
dependencies {
    implementation 'org.codehaus.groovy:groovy:3.0.5'
    implementation 'org.codehaus.groovy:groovy-json:3.0.5'
    implementation 'org.codehaus.groovy:groovy-nio:3.0.5'
}

访问器直接映射到 TOML 文件中定义的别名和版本,从而为依赖项和插件提供类型安全访问。这使 IDE 能够提供自动完成、突出显示拼写错误并将缺失的依赖项识别为错误。

别名和类型安全访问器

版本目录中的别名由破折号 (-)、下划线 (_) 或点 (.) 分隔的标识符组成。为每个别名生成类型安全访问器,并规范化为点表示法

别名示例 生成的访问器

guava

libs.guava

groovy-core

libs.groovy.core

androidx.awesome.lib

libs.androidx.awesome.lib

创建目录

版本目录通常使用位于根构建的 gradle 子目录中的 libs.versions.toml 文件声明

gradle/libs.versions.toml
[versions]
groovy = "3.0.5"
checkstyle = "8.37"

[libraries]
groovy-core = { module = "org.codehaus.groovy:groovy", version.ref = "groovy" }
groovy-json = { module = "org.codehaus.groovy:groovy-json", version.ref = "groovy" }
groovy-nio = { module = "org.codehaus.groovy:groovy-nio", version.ref = "groovy" }
commons-lang3 = { group = "org.apache.commons", name = "commons-lang3", version = { strictly = "[3.8, 4.0[", prefer="3.9" } }

[bundles]
groovy = ["groovy-core", "groovy-json", "groovy-nio"]

[plugins]
versions = { id = "com.github.ben-manes.versions", version = "0.45.0" }

TOML 目录格式

TOML 文件有四个部分

  • [versions] – 声明版本标识符。

  • [libraries] – 将别名映射到 GAV 坐标。

  • [bundles] – 定义依赖项捆绑包。

  • [plugins] – 声明插件版本。

TOML 文件格式非常宽松,允许您将“点式”属性编写为完整对象声明的快捷方式。

版本

版本可以声明为单个字符串,在这种情况下,它们被解释为必需版本,或者声明为 富版本

[versions]
other-lib = "5.5.0" # Required version
my-lib = { strictly = "[1.0, 2.0[", prefer = "1.2" } # Rich version

版本声明的支持成员包括

每个库都映射到一个 GAV 坐标:组、工件、版本。它们可以声明为简单字符串,在这种情况下,它们被解释为坐标,或者单独的组和名称

[versions]
common = "1.4"

[libraries]
my-lib = "com.mycompany:mylib:1.4"
my-lib-no-version.module = "com.mycompany:mylib"
my-other-lib = { module = "com.mycompany:other", version = "1.4" }
my-other-lib2 = { group = "com.mycompany", name = "alternate", version = "1.4" }
mylib-full-format = { group = "com.mycompany", name = "alternate", version = { require = "1.4" } }

[plugins]
short-notation = "some.plugin.id:1.4"
long-notation = { id = "some.plugin.id", version = "1.4" }
reference-notation = { id = "some.plugin.id", version.ref = "common" }

您还可以使用 strictlyprefer 定义严格或首选版本

[libraries]
commons-lang3 = { group = "org.apache.commons", name = "commons-lang3", version = { strictly = "[3.8, 4.0[", prefer = "3.9" } }

如果您想引用在 [versions] 部分中声明的版本,请使用 version.ref 属性

[versions]
some = "1.4"

[libraries]
my-lib = { group = "com.mycompany", name="mylib", version.ref="some" }

捆绑包

捆绑包将多个库别名分组,因此可以在构建脚本中一起引用它们。

[versions]
groovy = "3.0.9"

[libraries]
groovy-core = { group = "org.codehaus.groovy", name = "groovy", version.ref = "groovy" }
groovy-json = { group = "org.codehaus.groovy", name = "groovy-json", version.ref = "groovy" }
groovy-nio = { group = "org.codehaus.groovy", name = "groovy-nio", version.ref = "groovy" }

[bundles]
groovy = ["groovy-core", "groovy-json", "groovy-nio"]

这对于拉取具有单个别名的多个相关依赖项非常有用

build.gradle.kts
dependencies {
    implementation(libs.bundles.groovy)
}
build.gradle
dependencies {
    implementation libs.bundles.groovy
}

插件

本节通过将插件 ID 映射到版本号来定义插件及其版本。与库一样,您可以使用“版本”部分中的别名定义插件版本,也可以直接指定版本。

[plugins]
versions = { id = "com.github.ben-manes.versions", version = "0.45.0" }

可以使用 plugins {} 代码块在构建的任何项目中访问它。要从目录中引用插件,请使用 alias() 函数

build.gradle.kts
plugins {
    `java-library`
    checkstyle
    alias(libs.plugins.versions)
}
build.gradle
plugins {
    id 'java-library'
    id 'checkstyle'
    // Use the plugin `versions` as declared in the `libs` version catalog
    alias(libs.plugins.versions)
}
您不能在设置文件或设置插件中使用在版本目录中声明的插件。

避免子组访问器

为避免生成子组访问器,请使用 camelCase 表示法

别名 访问器

groovyCore

libs.groovyCore

groovyJson-core

libs.groovyJson.core

保留关键字

某些关键字(如 extensionsclassconvention)是保留的,不能用作别名。此外,bundlesversionsplugins 不能是依赖项别名中的第一个子组。

例如,别名 versions-dependency 无效,但 versionsDependencydependency-versions 有效。

发布目录

在大多数情况下,gradle/libs.versions.toml 将被检入存储库并可供使用。

但是,这并不总是解决在组织内或为外部使用者共享目录的问题。共享目录的另一种选择是编写设置插件,将其发布到 Gradle 插件门户或内部存储库,并让使用者在其设置文件中应用该插件。

或者,Gradle 提供了版本目录插件,该插件能够声明和发布目录。

为此,您需要应用 version-catalog 插件

build.gradle.kts
plugins {
    `version-catalog`
    `maven-publish`
}
build.gradle
plugins {
    id 'version-catalog'
    id 'maven-publish'
}

然后,此插件将公开 catalog 扩展,您可以使用该扩展来声明目录

build.gradle.kts
catalog {
    // declare the aliases, bundles and versions in this block
    versionCatalog {
        library("my-lib", "com.mycompany:mylib:1.2")
    }
}
build.gradle
catalog {
    // declare the aliases, bundles and versions in this block
    versionCatalog {
        library('my-lib', 'com.mycompany:mylib:1.2')
    }
}

必须以编程方式创建插件,有关详细信息,请参阅编程目录

然后,可以通过应用 maven-publishivy-publish 插件并配置发布以使用 versionCatalog 组件来发布此类目录

build.gradle.kts
publishing {
    publications {
        create<MavenPublication>("maven") {
            from(components["versionCatalog"])
        }
    }
}
build.gradle
publishing {
    publications {
        maven(MavenPublication) {
            from components.versionCatalog
        }
    }
}

发布此类项目时,将自动生成(并上传)libs.versions.toml 文件,然后可以从其他 Gradle 构建中 使用

导入已发布的目录

版本目录插件 生成的目录可以通过 Settings API 导入

settings.gradle.kts
dependencyResolutionManagement {
    versionCatalogs {
        create("libs") {
            from("com.mycompany:catalog:1.0")
        }
    }
}
settings.gradle
dependencyResolutionManagement {
    versionCatalogs {
        libs {
            from("com.mycompany:catalog:1.0")
        }
    }
}

从文件导入目录

Gradle 会自动导入 gradle 目录中名为 libs.versions.toml 的目录。

版本目录构建器 API 允许从外部文件导入目录,从而可以在构建的不同部分(例如,与 buildSrc 共享主构建的目录)中重复使用。

例如,您可以按如下所示在 buildSrc/settings.gradle(.kts) 文件中包含目录

settings.gradle.kts
dependencyResolutionManagement {
    versionCatalogs {
        create("libs") {
            from(files("../gradle/libs.versions.toml"))
        }
    }
}
settings.gradle
dependencyResolutionManagement {
    versionCatalogs {
        libs {
            from(files("../gradle/libs.versions.toml"))
        }
    }
}

VersionCatalogBuilder.from(Object dependencyNotation) 方法仅接受单个文件,这意味着诸如 Project.files(java.lang.Object…​) 之类的表示法必须引用一个文件。否则,构建将失败。

请记住,如果名为 libs.versions.toml 的版本目录位于您的 gradle 文件夹中,则无需导入它。它将自动导入。

但是,如果您需要从多个文件导入版本目录,建议使用基于代码的方法,而不是依赖 TOML 文件。这种方法允许从不同文件声明多个目录

settings.gradle.kts
dependencyResolutionManagement {
    versionCatalogs {
        // declares an additional catalog, named 'testLibs', from the 'test-libs.versions.toml' file
        create("testLibs") {
            from(files("gradle/test-libs.versions.toml"))
        }
    }
}
settings.gradle
dependencyResolutionManagement {
    versionCatalogs {
        // declares an additional catalog, named 'testLibs', from the 'test-libs.versions.toml' file
        testLibs {
            from(files('gradle/test-libs.versions.toml'))
        }
    }
}

导入多个目录

您可以使用 Settings API 声明多个目录,以便更好地组织依赖项

settings.gradle.kts
dependencyResolutionManagement {
    versionCatalogs {
        create("libs") {
            from(files("gradle/libs.versions.toml"))
        }
        create("tools") {
            from(files("gradle/tools.versions.toml"))
        }
    }
}
build.gradle.kts
dependencies {
    implementation(libs.someDependency)
    implementation(tools.someTool)
}

为了最大限度地降低命名冲突的风险,每个目录都会生成一个应用于所有项目的扩展,因此建议选择一个唯一的名称。一种有效的方法是选择一个以 Libs 结尾的名称。

更改目录名称

默认情况下,libs.versions.toml 文件用作 libs 目录的输入。但是,如果已存在同名扩展,您可以重命名默认目录

settings.gradle.kts
dependencyResolutionManagement {
    defaultLibrariesExtensionName = "projectLibs"
}
settings.gradle
dependencyResolutionManagement {
    defaultLibrariesExtensionName = 'projectLibs'
}

覆盖目录版本

导入目录时,您可以覆盖版本

settings.gradle.kts
dependencyResolutionManagement {
    versionCatalogs {
        create("amendedLibs") {
            from("com.mycompany:catalog:1.0")
            // overwrite the "groovy" version declared in the imported catalog
            version("groovy", "3.0.6")
        }
    }
}
settings.gradle
dependencyResolutionManagement {
    versionCatalogs {
        amendedLibs {
            from("com.mycompany:catalog:1.0")
            // overwrite the "groovy" version declared in the imported catalog
            version("groovy", "3.0.6")
        }
    }
}

在上面的示例中,任何引用 groovy 版本的依赖项都将自动更新为使用 3.0.6

覆盖版本仅影响导入和声明依赖项时使用的内容。实际解析的依赖项版本可能会因冲突解决而异。

编程目录

版本目录可以在 settings.gradle(.kts) 文件中以编程方式声明。

settings.gradle.kts
dependencyResolutionManagement {
    versionCatalogs {
        create("libs") {
            version("groovy", "3.0.5")
            version("checkstyle", "8.37")
            library("groovy-core", "org.codehaus.groovy", "groovy").versionRef("groovy")
            library("groovy-json", "org.codehaus.groovy", "groovy-json").versionRef("groovy")
            library("groovy-nio", "org.codehaus.groovy", "groovy-nio").versionRef("groovy")
            library("commons-lang3", "org.apache.commons", "commons-lang3").version {
                strictly("[3.8, 4.0[")
                prefer("3.9")
            }
        }
    }
}
settings.gradle
dependencyResolutionManagement {
    versionCatalogs {
        libs {
            version('groovy', '3.0.5')
            version('checkstyle', '8.37')
            library('groovy-core', 'org.codehaus.groovy', 'groovy').versionRef('groovy')
            library('groovy-json', 'org.codehaus.groovy', 'groovy-json').versionRef('groovy')
            library('groovy-nio', 'org.codehaus.groovy', 'groovy-nio').versionRef('groovy')
            library('commons-lang3', 'org.apache.commons', 'commons-lang3').version {
                strictly '[3.8, 4.0['
                prefer '3.9'
            }
        }
    }
}
如果您在项目中具有默认的 libs.versions.toml,请不要将 libs 用于您的编程版本目录名称。

以编程方式创建版本目录使用 Settings API

settings.gradle.kts
dependencyResolutionManagement {
    versionCatalogs {
        create("libs") {
            version("groovy", "3.0.5")
            version("checkstyle", "8.37")
            library("groovy-core", "org.codehaus.groovy", "groovy").versionRef("groovy")
            library("groovy-json", "org.codehaus.groovy", "groovy-json").versionRef("groovy")
            library("groovy-nio", "org.codehaus.groovy", "groovy-nio").versionRef("groovy")
            library("commons-lang3", "org.apache.commons", "commons-lang3").version {
                strictly("[3.8, 4.0[")
                prefer("3.9")
            }
            bundle("groovy", listOf("groovy-core", "groovy-json", "groovy-nio"))
        }
    }
}
settings.gradle
dependencyResolutionManagement {
    versionCatalogs {
        libs {
            version('groovy', '3.0.5')
            version('checkstyle', '8.37')
            library('groovy-core', 'org.codehaus.groovy', 'groovy').versionRef('groovy')
            library('groovy-json', 'org.codehaus.groovy', 'groovy-json').versionRef('groovy')
            library('groovy-nio', 'org.codehaus.groovy', 'groovy-nio').versionRef('groovy')
            library('commons-lang3', 'org.apache.commons', 'commons-lang3').version {
                strictly '[3.8, 4.0['
                prefer '3.9'
            }
            bundle('groovy', ['groovy-core', 'groovy-json', 'groovy-nio'])
        }
    }
}