foreword
With the continuous development of the project, there are more and more dependencies in the project, and sometimes there may be hundreds of them. At this time, it is necessary to have a unified management of project dependencies. We generally have the following requirements:
- Project dependencies are managed uniformly and configured in a separate file
Module
Unified version numbers of dependencies in different- Unified version numbers of dependencies in different projects
In response to these needs, there are already some solutions:
- Optimizing Gradle Dependency Management with Loops
- Using buildSrc to manage Gradle dependencies
- Use includeBuild to uniformly configure dependency versions
The above solution supports the Module
unified version number between different projects. At the same time, if it needs to be shared between projects, it can also be made into a Gradle
plug-in and released to the remote end, which can basically meet our needs.
However Gradle7.0
, a new feature has been introduced, using a Catalog
unified dependency version, it The following features are supported:
- Visible to all
module
, unified managementmodule
of all dependencies - Support for declarative dependencies
bundles
, i.e. dependencies that are always used together can be grouped together - Supports the separation of version numbers and dependency names, and can share version numbers among multiple dependencies
- Support
libs.versions.toml
for configuring dependencies in separate files - Support for sharing dependencies between projects
useVersion Catalog
Note that Catalog
it is still an incubating feature, if you want to use it, you need settings.gradle
to add the following to it:
enableFeaturePreview('VERSION_CATALOGS')
复制代码
It can also be seen from the naming that it Version Catalog
is actually a version of the directory. We can select the dependencies we need from the directory to use. We can use the dependencies declared in the
following waysCatalog
dependencies {
implementation(libs.retrofit)
implementation(libs.groovy.core)
}
复制代码
In this case, libs
a directory retrofit
representing the dependencies available in that directory. Version Catalog
Has many advantages over declaring dependencies directly in the build script :
- 对于每个
catalog
,Gradle
都会生成类型安全的访问器,以便你在IDE
中可以自动补全.(注:目前在build.gradle
中还不能自动补全,可能是指kts
或者开发中?) - 声明在
catalog
中的依赖对所有module
可见,当修改版本号时,可以统一管理统一修改 catalog
支持声明一个依赖bundles
,即一些总是一起使用的依赖的组合catalog
支持版本号与依赖名分离,可以在多个依赖间共享版本号
声明Version Catalog
Version Catalog
可以在settings.gradle(.kts)
文件中声明。
dependencyResolutionManagement {
versionCatalogs {
libs {
alias('retrofit').to('com.squareup.retrofit2:retrofit:2.9.0')
alias('groovy-core').to('org.codehaus.groovy:groovy:3.0.5')
alias('groovy-json').to('org.codehaus.groovy:groovy-json:3.0.5')
alias('groovy-nio').to('org.codehaus.groovy:groovy-nio:3.0.5')
alias('commons-lang3').to('org.apache.commons', 'commons-lang3').version {
strictly '[3.8, 4.0['
prefer '3.9'
}
}
}
}
复制代码
别名必须由一系列以破折号(-
,推荐)、下划线 (_
) 或点 (.
) 分隔的标识符组成。
标识符本身必须由ascii
字符组成,最好是小写,最后是数字。
值得注意的是,groovy-core
会被映射成libs.groovy.core
如果你想避免映射可以使用大小写来区分,比如groovyCore
会被处理成libs.groovyCore
具有相同版本号的依赖
在上面的示例中,我们可以看到三个groovy
依赖具有相同的版本号,我们可以把它们统一起来
dependencyResolutionManagement {
versionCatalogs {
libs {
version('groovy', '3.0.5')
version('compilesdk', '30')
version('targetsdk', '30')
alias('groovy-core').to('org.codehaus.groovy', 'groovy').versionRef('groovy')
alias('groovy-json').to('org.codehaus.groovy', 'groovy-json').versionRef('groovy')
alias('groovy-nio').to('org.codehaus.groovy', 'groovy-nio').versionRef('groovy')
alias('commons-lang3').to('org.apache.commons', 'commons-lang3').version {
strictly '[3.8, 4.0['
prefer '3.9'
}
}
}
}
复制代码
除了在依赖中,我们同样可以在build.gradle
中获取版本,比如可以用来指定compileSdk
等
android {
compileSdk libs.versions.compilesdk.get().toInteger()
defaultConfig {
applicationId "com.zj.gradlecatalog"
minSdk 21
targetSdk libs.versions.targetsdk.get().toInteger()
}
}
复制代码
如上,可以使用catalog
统一compileSdk
,targetSdk
,minSdk
的版本号
依赖bundles
因为在不同的项目中经常系统地一起使用某些依赖项,所以Catalog
提供了bundle
(依赖包)的概念。依赖包基本上是几个依赖项打包的别名。
例如,你可以这样使用一个依赖包,而不是像上面那样声明 3 个单独的依赖项:
dependencies {
implementation libs.bundles.groovy
}
复制代码
groovy
依赖包声明如下:
dependencyResolutionManagement {
versionCatalogs {
libs {
version('groovy', '3.0.5')
version('checkstyle', '8.37')
alias('groovy-core').to('org.codehaus.groovy', 'groovy').versionRef('groovy')
alias('groovy-json').to('org.codehaus.groovy', 'groovy-json').versionRef('groovy')
alias('groovy-nio').to('org.codehaus.groovy', 'groovy-nio').versionRef('groovy')
alias('commons-lang3').to('org.apache.commons', 'commons-lang3').version {
strictly '[3.8, 4.0['
prefer '3.9'
}
bundle('groovy', ['groovy-core', 'groovy-json', 'groovy-nio'])
}
}
}
复制代码
如上所示:添加groovy
依赖包等同于添加依赖包下的所有依赖项
插件版本
除了Library
之外,Catalog
还支持声明插件版本。
因为library
由它们的group
、artifact
和version
表示,但Gradle
插件仅由它们的id
和version
标识。
因此,插件需要单独声明:
dependencyResolutionManagement {
versionCatalogs {
libs {
alias('jmh').toPluginId('me.champeau.jmh').version('0.6.5')
}
}
}
复制代码
然后可以在plugins
块下面使用
plugins {
id 'java-library'
id 'checkstyle'
// 使用声明的插件
alias(libs.plugins.jmh)
}
复制代码
在单独文件中配置Catalog
除了在settings.gradle
中声明Catalog
外,也可以通过一个单独的文件来配置Catalog
如果在根构建的gradle
目录中找到了libs.versions.toml
文件,则将使用该文件的内容自动声明一个Catalog
TOML
文件主要由4个部分组成:
[versions]
部分用于声明可以被依赖项引用的版本[libraries]
部分用于声明Library
的别名[bundles]
部分用于声明依赖包[plugins]
部分用于声明插件
如下所示:
[versions]
groovy = "3.0.5"
checkstyle = "8.37"
compilesdk = "30"
targetsdk = "30"
[libraries]
retrofit = "com.squareup.retrofit2:retrofit:2.9.0"
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]
jmh = { id = "me.champeau.jmh", version = "0.6.5" }
复制代码
如上所示,依赖可以定义成一个字符串,也可以将module
与version
分离开来
其中versions
可以定义成一个字符串,也可以定义成一个范围,详情可参见rich-version
[versions]
my-lib = { strictly = "[1.0, 2.0[", prefer = "1.2" }
复制代码
在项目间共享Catalog
Catalog
不仅可以在项目内统一管理依赖,同样可以实现在项目间共享
例如我们需要在团队内制定一个依赖规范,不同组的不同项目需要共享这些依赖,这是个很常见的需求
通过文件共享
Catalog
支持通过从Toml
文件引入依赖,这就让我们可以通过指定文件路径来实现共享依赖
如下所示,我们在settins.gradle
中配置如下:
dependencyResolutionManagement {
versionCatalogs {
libs {
from(files("../gradle/libs.versions.toml"))
}
}
}
复制代码
此技术可用于声明来自不同文件的多个目录:
dependencyResolutionManagement {
versionCatalogs {
// 声明一个'testLibs'目录, 从'test-libs.versions.toml'文件中
testLibs {
from(files('gradle/test-libs.versions.toml'))
}
}
}
复制代码
发布插件实现共享
虽然从本地文件导入Catalog
很方便,但它并没有解决在组织或外部消费者中共享Catalog
的问题。
我们还可能通过Catalog
插件来发布目录,这样用户直接引入这个插件即可
Gradle
提供了一个Catalog
插件,它提供了声明然后发布Catalog
的能力。
1. 首先引入两个插件
plugins {
id 'version-catalog'
id 'maven-publish'
}
复制代码
然后,此插件将公开可用于声明目录的catalog
扩展
2. 定义目录
上面引入插件后,即可使用catalog
扩展定义目录
catalog {
// 定义目录
versionCatalog {
from files('../libs.versions.toml')
}
}
复制代码
然后可以通过maven-publish
插件来发布目录
3. 发布目录
publishing {
publications {
maven(MavenPublication) {
groupId = 'com.zj.catalog'
artifactId = 'catalog'
version = '1.0.0'
from components.versionCatalog
}
}
}
复制代码
我们定义好groupId
,artifactId
,version
,from
就可以发布了
我们这里发布到mavenLocal
,你也可以根据需要配置发布到自己的maven
以上发布的所有代码可见:Catalog发布相关代码
4. 使用目录
因为我们已经发布到了mavenLocal
,在仓库中引入mavenLocal
就可以使用插件了
# settings.gradle
dependencyResolutionManagement {
//...
repositories {
mavenLocal()
//...
}
}
enableFeaturePreview('VERSION_CATALOGS')
dependencyResolutionManagement {
versionCatalogs {
libs {
from("com.zj.catalog:catalog:1.0.0")
// 我们也可以重写覆盖catalog中的groovy版本
version("groovy", "3.0.6")
}
}
}
复制代码
如上就成功引入了插件,就可以使用catalog
中的依赖了
这样就完成了依赖的项目间共享,以上使用的所有代码可见:Catalog使用相关代码
总结
项目间共享依赖是比较常见的需求,虽然我们也可以通过自定义插件实现,但还是不够方便
Gradle
官方终于推出了Catalog
,让我们可以方便地实现依赖的共享,Catalog
主要具有以下特性:
- 对所有
module
可见,可统一管理所有module
的依赖 - Support for declarative dependencies
bundles
, i.e. dependencies that are always used together can be grouped together - Supports the separation of version numbers and dependency names, and can share version numbers among multiple dependencies
- Support
libs.versions.toml
for configuring dependencies in separate files - Support for sharing dependencies between projects
All relevant code in this article
Catalog publishes related code
Catalog uses related code