版本目录是精选的依赖项列表,可在构建脚本中引用,从而简化依赖管理。
除了直接使用字符串符号指定依赖项外,您还可以从版本目录中选择它们
dependencies {
implementation(libs.groovy.core)
}
dependencies {
implementation(libs.groovy.core)
}
在此示例中,libs
表示目录,而 groovy
是目录中可用的依赖项。
其中定义 libs.groovy.core
的版本目录是 gradle
目录中的 libs.versions.toml
文件
[libraries]
groovy-core = { group = "org.codehaus.groovy", name = "groovy", version = "3.0.5" }
版本目录提供了一些优点
版本目录定义了版本,但它们不影响依赖解析过程。由于依赖图冲突或通过平台或依赖管理 API 应用的约束,Gradle 仍然可能选择不同的版本。
目录中声明的版本通常不强制执行,这意味着构建中使用的实际版本可能会因依赖解析而有所不同。 |
访问目录
要访问位于 gradle
目录中标准 libs.versions.toml
文件中定义的版本目录中的项,您可以在构建脚本中使用 libs
对象。例如,要引用库,可以使用 libs.<alias>
;要引用插件,可以使用 libs.plugins.<alias>
。
使用版本目录声明依赖项
dependencies {
implementation(libs.groovy.core)
implementation(libs.groovy.json)
implementation(libs.groovy.nio)
}
dependencies {
implementation libs.groovy.core
implementation libs.groovy.json
implementation libs.groovy.nio
}
与之相同的是
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")
}
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 能够提供自动完成、突出显示拼写错误并将缺失的依赖项标识为错误。
别名和类型安全的访问器
版本目录中的别名由破折号 (-
)、下划线 (_
) 或点 (.
) 分隔的标识符组成。为每个别名生成类型安全的访问器,规范化为点符号
示例别名 | 生成的访问器 |
---|---|
|
|
|
|
|
|
创建目录
版本目录通常使用位于根构建的 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 目录格式
The TOML 文件有四个部分
-
[versions]
– 声明版本标识符。 -
[libraries]
– 将别名映射到 GAV 坐标。 -
[bundles]
– 定义依赖项 Bundle。 -
[plugins]
– 声明插件版本。
TOML 文件格式非常宽松,允许您将“点式”属性写为完整对象声明的快捷方式。
版本
版本可以声明为单个字符串(在这种情况下,它们被解释为 所需 版本)或 富版本 (rich version)
[versions]
other-lib = "5.5.0" # Required version
my-lib = { strictly = "[1.0, 2.0[", prefer = "1.2" } # Rich version
版本声明支持的成员有
库
每个库都映射到一个 GAV 坐标:group、artifact、version。它们可以声明为一个简单的字符串,在这种情况下它们被解释为坐标,或者分开声明 group 和 name
[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" }
您还可以使用 strictly
或 prefer
定义严格或首选版本
[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" }
Bundle
Bundle 将多个库别名分组,以便它们可以在构建脚本中一起引用。
[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"]
这对于使用单个别名引入多个相关依赖项非常有用
dependencies {
implementation(libs.bundles.groovy)
}
dependencies {
implementation libs.bundles.groovy
}
插件
本节通过将插件 ID 映射到版本号来定义插件及其版本。就像库一样,您可以使用 [versions]
部分中的别名或直接指定版本来定义插件版本。
[plugins]
versions = { id = "com.github.ben-manes.versions", version = "0.45.0" }
可以使用 plugins {}
块在构建的任何项目中访问它。要引用目录中的插件,请使用 alias()
函数
plugins {
`java-library`
checkstyle
alias(libs.plugins.versions)
}
plugins {
id 'java-library'
id 'checkstyle'
// Use the plugin `versions` as declared in the `libs` version catalog
alias(libs.plugins.versions)
}
您不能在设置文件或设置插件中使用版本目录中声明的插件。 |
避免使用子组访问器
为避免生成子组访问器,请使用 camelCase (驼峰命名法)
别名 | 访问器 |
---|---|
|
|
|
|
保留关键字
某些关键字,例如 extensions
、class
和 convention
,是保留的,不能用作别名。此外,bundles
、versions
和 plugins
不能作为依赖别名中的第一个子组。
例如,别名 versions-dependency
无效,但 versionsDependency
或 dependency-versions
有效。
发布目录
在大多数情况下,gradle/libs.versions.toml
将被提交到仓库并可供使用。
然而,这并不能总是解决在组织内部或面向外部消费者共享目录的问题。共享目录的另一种选择是编写一个 settings 插件,将其发布到 Gradle 插件门户或内部仓库,并让消费者在其 settings 文件中应用该插件。
另一种方式是,Gradle 提供了一个 版本目录 插件,它具有声明和发布目录的能力。
为此,您需要应用 version-catalog
插件
plugins {
`version-catalog`
`maven-publish`
}
plugins {
id 'version-catalog'
id 'maven-publish'
}
然后,此插件将暴露 catalog 扩展,您可以使用它来声明目录
catalog {
// declare the aliases, bundles and versions in this block
versionCatalog {
library("my-lib", "com.mycompany:mylib:1.2")
}
}
catalog {
// declare the aliases, bundles and versions in this block
versionCatalog {
library('my-lib', 'com.mycompany:mylib:1.2')
}
}
插件必须以编程方式创建,详情请参阅 编程方式创建目录。
然后可以通过应用 maven-publish
或 ivy-publish
插件并将发布配置为使用 versionCatalog
组件来发布此类目录
publishing {
publications {
create<MavenPublication>("maven") {
from(components["versionCatalog"])
}
}
}
publishing {
publications {
maven(MavenPublication) {
from components.versionCatalog
}
}
}
发布此类项目时,会自动生成(并上传)一个 libs.versions.toml
文件,然后可以被其他 Gradle 构建消费。
导入已发布的目录
由 版本目录插件 生成的目录可以通过 Settings API 导入
dependencyResolutionManagement {
versionCatalogs {
create("libs") {
from("com.mycompany:catalog:1.0")
}
}
}
dependencyResolutionManagement {
versionCatalogs {
libs {
from("com.mycompany:catalog:1.0")
}
}
}
从文件导入目录
Gradle 会自动导入 gradle 目录中名为 libs.versions.toml 的目录。 |
The 版本目录构建器 API 允许从外部文件导入目录,从而实现在构建的不同部分之间重用,例如与 buildSrc
共享主构建的目录。
例如,您可以将目录包含在 buildSrc/settings.gradle(.kts)
文件中,如下所示
dependencyResolutionManagement {
versionCatalogs {
create("libs") {
from(files("../gradle/libs.versions.toml"))
}
}
}
dependencyResolutionManagement {
versionCatalogs {
libs {
from(files("../gradle/libs.versions.toml"))
}
}
}
The VersionCatalogBuilder.from(Object dependencyNotation) 方法只接受单个文件,这意味着像 Project.files(java.lang.Object…) 这样的符号必须引用一个文件。否则,构建将失败。
请记住,如果名为 libs.versions.toml 的版本目录位于您的 gradle 文件夹中,则无需导入它。它将自动导入。 |
但是,如果您需要从多个文件导入版本目录,建议使用基于代码的方法,而不是依赖 TOML 文件。这种方法允许从不同文件声明多个目录
dependencyResolutionManagement {
versionCatalogs {
// declares an additional catalog, named 'testLibs', from the 'test-libs.versions.toml' file
create("testLibs") {
from(files("gradle/test-libs.versions.toml"))
}
}
}
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 声明多个目录,以便更好地组织依赖项
dependencyResolutionManagement {
versionCatalogs {
create("libs") {
from(files("gradle/libs.versions.toml"))
}
create("tools") {
from(files("gradle/tools.versions.toml"))
}
}
}
dependencies {
implementation(libs.someDependency)
implementation(tools.someTool)
}
为了最大程度地减少命名冲突的风险,每个目录都会生成一个应用于所有项目的扩展,因此建议选择一个唯一的名称。一个有效的方法是选择一个以 |
更改目录名称
默认情况下,libs.versions.toml
文件用作 libs
目录的输入。但是,如果已存在同名扩展,您可以重命名默认目录
dependencyResolutionManagement {
defaultLibrariesExtensionName = "projectLibs"
}
dependencyResolutionManagement {
defaultLibrariesExtensionName = 'projectLibs'
}
覆盖目录版本
导入目录时可以覆盖版本
dependencyResolutionManagement {
versionCatalogs {
create("amendedLibs") {
from("com.mycompany:catalog:1.0")
// overwrite the "groovy" version declared in the imported catalog
version("groovy", "3.0.6")
}
}
}
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)
文件中以编程方式声明。
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")
}
}
}
}
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
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"))
}
}
}
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'])
}
}
}
在 buildSrc
中使用目录
版本目录提供了一种集中管理项目依赖项的方式。然而,buildSrc
不会自动继承主项目的版本目录,因此需要额外的配置。
要使用版本目录,您需要在 buildSrc/settings.gradle(.kts)
中显式导入它
// Add the version catalog to buildSrc using dependencyResolutionManagement
dependencyResolutionManagement {
versionCatalogs {
create("libs") {
from(files("../gradle/libs.versions.toml"))
}
}
}
// Add the version catalog to buildSrc using dependencyResolutionManagement
dependencyResolutionManagement {
versionCatalogs {
create("libs") {
from(files("../gradle/libs.versions.toml"))
}
}
}
版本目录导入后,可以使用一些技巧引用依赖项
plugins {
`kotlin-dsl`
alias(libs.plugins.versions) // Access version catalog in builSrc build file for plugin
}
repositories {
gradlePluginPortal()
}
dependencies {
// Access version catalog in buildSrc build file for dependencies
implementation(plugin(libs.plugins.jacocolog)) // Plugin dependency
implementation(libs.groovy.core) // Regular library from version catalog
implementation("org.apache.commons:commons-lang3:3.9") // Direct dependency
}
// Helper function that transforms a Gradle Plugin alias from a
// Version Catalog into a valid dependency notation for buildSrc
fun DependencyHandlerScope.plugin(plugin: Provider<PluginDependency>) =
plugin.map { "${it.pluginId}:${it.pluginId}.gradle.plugin:${it.version}" }
plugins {
id 'groovy-gradle-plugin'
alias(libs.plugins.versions) // Access version catalog in buildSrc for plugin
}
repositories {
gradlePluginPortal()
}
def catalogs = project.extensions.getByType(VersionCatalogsExtension)
def libs = catalogs.named("libs")
dependencies {
// Access version catalog in buildSrc for dependencies
implementation plugin(libs.findPlugin("jacocolog").get()) // Plugin dependency
implementation libs.findLibrary("groovy-core").get() // Regular library from version catalog
implementation "org.apache.commons:commons-lang3:3.9" // Direct dependency
}
// Helper function that transforms a Gradle Plugin alias from a
// Version Catalog into a valid dependency notation for buildSrc
def plugin(Provider<PluginDependency> plugin) {
return plugin.map { it.pluginId + ":" + it.pluginId + ".gradle.plugin:" + it.version }
}
在 buildSrc
内部的预编译脚本插件中,可以使用 extensions.getByType(VersionCatalogsExtension)
访问版本目录,如本约定插件的依赖项块所示
plugins {
id("java-library")
//alias(libs.plugins.jacocolog) // Unfortunately it is not possible the version catalog in buildSrc code for plugins
// Remember that unlike regular Gradle projects, convention plugins in buildSrc do not automatically resolve
// external plugins. We must declare them as dependencies in buildSrc/build.gradle.kts.
id("org.barfuin.gradle.jacocolog") // Apply the plugin manually as a workaround with the external plugin
// version from the version catalog specified in implementation dependency
// artifact in build file
}
repositories {
mavenCentral()
}
// Access the version catalog
val libs = extensions.getByType(VersionCatalogsExtension::class.java).named("libs")
//val libs = the<VersionCatalogsExtension>().named("libs")
dependencies {
// Access version catalog in buildSrc code for dependencies
implementation(libs.findLibrary("guava").get()) // Regular library from version catalog
testImplementation(platform("org.junit:junit-bom:5.9.1")) // Platform dependency
testImplementation("org.junit.jupiter:junit-jupiter") // Direct dependency
}
tasks.test {
useJUnitPlatform()
}
plugins {
id 'java-library'
// alias(libs.plugins.jacocolog) - Unfortunately, it is not possible to use the version catalog for plugins in buildSrc
// Unlike regular Gradle projects, convention plugins in buildSrc do not automatically resolve
// external plugins. We must declare them as dependencies in buildSrc/build.gradle.
id 'org.barfuin.gradle.jacocolog' // Apply the plugin manually as a workaround
// The external plugin version comes from the implementation dependency
// artifact in the build file
}
repositories {
mavenCentral()
}
// Access the version catalog
def libs = project.extensions.getByType(VersionCatalogsExtension).named("libs")
dependencies {
// Access version catalog in buildSrc for dependencies
implementation libs.findLibrary("guava").get() // Regular library from version catalog
testImplementation platform("org.junit:junit-bom:5.9.1") // Platform dependency
testImplementation "org.junit.jupiter:junit-jupiter" // Direct dependency
}
tasks.withType(Test).configureEach {
useJUnitPlatform()
}
但是,预编译脚本插件中的 plugins 块无法访问版本目录。