当前位置:   article > 正文

Gradle 7.0 依赖统一管理的全新方式,了解一下

dependencyresolutionmanagement

前言

随着项目的不断发展,项目中的依赖也越来越多,有时可能会有几百个,这个时候对项目依赖做一个统一的管理很有必要,我们一般会有以下需求:

  1. 项目依赖统一管理,在单独文件中配置

  2. 不同Module中的依赖版本号统一

  3. 不同项目中的依赖版本号统一

针对这些需求,目前其实已经有了一些方案:

  1. 使用循环优化Gradle依赖管理[1]

  2. 使用buildSrc管理Gradle依赖[2]

  3. 使用includeBuild统一配置依赖版本[3]

上面的方案支持在不同Module间统一版本号,同时如果需要在项目间共享,也可以做成Gradle插件发布到远端,已经基本可以满足我们的需求
不过Gradle7.0推出了一个新的特性,使用Catalog统一依赖版本,它支持以下特性:

  1. 对所有module可见,可统一管理所有module的依赖

  2. 支持声明依赖bundles,即总是一起使用的依赖可以组合在一起

  3. 支持版本号与依赖名分离,可以在多个依赖间共享版本号

  4. 支持在单独的libs.versions.toml文件中配置依赖

  5. 支持在项目间共享依赖

使用Version Catalog

注意,Catalog仍然是一个孵化中的特性,如需使用,需要在settings.gradle中添加以下内容:

enableFeaturePreview('VERSION_CATALOGS')

从命名上也可以看出,Version Catalog其实就是一个版本的目录,我们可以从目录中选出我们需要的依赖使用

我们可以通过如下方式使用Catalog中声明的依赖

  1. dependencies {
  2.     implementation(libs.retrofit)
  3.     implementation(libs.groovy.core)
  4. }

在这种情况下,libs是一个目录,retrofit表示该目录中可用的依赖项。与直接在构建脚本中声明依赖项相比,Version Catalog具有许多优点:

  • 对于每个catalog,Gradle都会生成类型安全的访问器,以便你在IDE中可以自动补全.(注:目前在build.gradle中还不能自动补全,可能是指kts或者开发中?)

  • 声明在catalog中的依赖对所有module可见,当修改版本号时,可以统一管理统一修改

  • catalog支持声明一个依赖bundles,即一些总是一起使用的依赖的组合

  • catalog支持版本号与依赖名分离,可以在多个依赖间共享版本号

声明Version Catalog

Version Catalog可以在settings.gradle(.kts)文件中声明。

  1. dependencyResolutionManagement {
  2.     versionCatalogs {
  3.         libs {
  4.             alias('retrofit').to('com.squareup.retrofit2:retrofit:2.9.0')
  5.             alias('groovy-core').to('org.codehaus.groovy:groovy:3.0.5')
  6.             alias('groovy-json').to('org.codehaus.groovy:groovy-json:3.0.5')
  7.             alias('groovy-nio').to('org.codehaus.groovy:groovy-nio:3.0.5')
  8.             alias('commons-lang3').to('org.apache.commons''commons-lang3').version {
  9.                 strictly '[3.8, 4.0['
  10.                 prefer '3.9'
  11.             }
  12.         }
  13.     }
  14. }

别名必须由一系列以破折号(-,推荐)、下划线 (_) 或点 (.) 分隔的标识符组成。

标识符本身必须由ascii字符组成,最好是小写,最后是数字。

值得注意的是,groovy-core会被映射成libs.groovy.core
如果你想避免映射可以使用大小写来区分,比如groovyCore会被处理成libs.groovyCore

具有相同版本号的依赖

在上面的示例中,我们可以看到三个groovy依赖具有相同的版本号,我们可以把它们统一起来

  1. dependencyResolutionManagement {
  2.     versionCatalogs {
  3.         libs {
  4.             version('groovy''3.0.5')
  5.             version('compilesdk''30')
  6.             version('targetsdk''30')
  7.             alias('groovy-core').to('org.codehaus.groovy''groovy').versionRef('groovy')
  8.             alias('groovy-json').to('org.codehaus.groovy''groovy-json').versionRef('groovy')
  9.             alias('groovy-nio').to('org.codehaus.groovy''groovy-nio').versionRef('groovy')
  10.             alias('commons-lang3').to('org.apache.commons''commons-lang3').version {
  11.                 strictly '[3.8, 4.0['
  12.                 prefer '3.9'
  13.             }
  14.         }
  15.     }
  16. }

除了在依赖中,我们同样可以在build.gradle中获取版本,比如可以用来指定compileSdk

  1. android {
  2.     compileSdk libs.versions.compilesdk.get().toInteger()
  3.     defaultConfig {
  4.         applicationId "com.zj.gradlecatalog"
  5.         minSdk 21
  6.         targetSdk libs.versions.targetsdk.get().toInteger()
  7.     }
  8. }

如上,可以使用catalog统一compileSdk,targetSdk,minSdk的版本号

依赖bundles

因为在不同的项目中经常系统地一起使用某些依赖项,所以Catalog提供了bundle(依赖包)的概念。依赖包基本上是几个依赖项打包的别名。

例如,你可以这样使用一个依赖包,而不是像上面那样声明 3 个单独的依赖项:

  1. dependencies {
  2.     implementation libs.bundles.groovy
  3. }

groovy依赖包声明如下:

  1. dependencyResolutionManagement {
  2.     versionCatalogs {
  3.         libs {
  4.             version('groovy''3.0.5')
  5.             version('checkstyle''8.37')
  6.             alias('groovy-core').to('org.codehaus.groovy''groovy').versionRef('groovy')
  7.             alias('groovy-json').to('org.codehaus.groovy''groovy-json').versionRef('groovy')
  8.             alias('groovy-nio').to('org.codehaus.groovy''groovy-nio').versionRef('groovy')
  9.             alias('commons-lang3').to('org.apache.commons''commons-lang3').version {
  10.                 strictly '[3.8, 4.0['
  11.                 prefer '3.9'
  12.             }
  13.             bundle('groovy', ['groovy-core''groovy-json''groovy-nio'])
  14.         }
  15.     }
  16. }

如上所示:添加groovy依赖包等同于添加依赖包下的所有依赖项

插件版本

除了Library之外,Catalog还支持声明插件版本。
因为library由它们的groupartifactversion表示,但Gradle插件仅由它们的idversion标识。
因此,插件需要单独声明:

  1. dependencyResolutionManagement {
  2.     versionCatalogs {
  3.         libs {
  4.             alias('jmh').toPluginId('me.champeau.jmh').version('0.6.5')
  5.         }
  6.     }
  7. }

然后可以在plugins块下面使用

  1. plugins {
  2.     id 'java-library'
  3.     id 'checkstyle'
  4.     // 使用声明的插件
  5.     alias(libs.plugins.jmh)
  6. }

在单独文件中配置Catalog

除了在settings.gradle中声明Catalog外,也可以通过一个单独的文件来配置Catalog
如果在根构建的gradle目录中找到了libs.versions.toml文件,则将使用该文件的内容自动声明一个Catalog

TOML文件主要由4个部分组成:

  • [versions] 部分用于声明可以被依赖项引用的版本

  • [libraries] 部分用于声明Library的别名

  • [bundles] 部分用于声明依赖包

  • [plugins] 部分用于声明插件

如下所示:

  1. [versions]
  2. groovy = "3.0.5"
  3. checkstyle = "8.37"
  4. compilesdk = "30"
  5. targetsdk = "30"
  6. [libraries]
  7. retrofit = "com.squareup.retrofit2:retrofit:2.9.0"
  8. groovy-core = { module = "org.codehaus.groovy:groovy", version.ref = "groovy" }
  9. groovy-json = { module = "org.codehaus.groovy:groovy-json", version.ref = "groovy" }
  10. groovy-nio = { module = "org.codehaus.groovy:groovy-nio", version.ref = "groovy" }
  11. commons-lang3 = { group = "org.apache.commons", name = "commons-lang3", version = { strictly = "[3.8, 4.0[", prefer="3.9" } }
  12. [bundles]
  13. groovy = ["groovy-core""groovy-json""groovy-nio"]
  14. [plugins]
  15. jmh = { id = "me.champeau.jmh", version = "0.6.5" }

如上所示,依赖可以定义成一个字符串,也可以将moduleversion分离开来。

其中versions可以定义成一个字符串,也可以定义成一个范围,详情可参见rich-version[4]

  1. [versions]
  2. my-lib = { strictly = "[1.0, 2.0[", prefer = "1.2" }

在项目间共享Catalog

Catalog不仅可以在项目内统一管理依赖,同样可以实现在项目间共享
例如我们需要在团队内制定一个依赖规范,不同组的不同项目需要共享这些依赖,这是个很常见的需求

通过文件共享

Catalog支持通过从Toml文件引入依赖,这就让我们可以通过指定文件路径来实现共享依赖。

如下所示,我们在settins.gradle中配置如下:

  1. dependencyResolutionManagement {
  2.     versionCatalogs {
  3.         libs {
  4.             from(files("../gradle/libs.versions.toml"))
  5.         }
  6.     }
  7. }

此技术可用于声明来自不同文件的多个目录:

  1. dependencyResolutionManagement {
  2.     versionCatalogs {
  3.         // 声明一个'testLibs'目录, 从'test-libs.versions.toml'文件中
  4.         testLibs {
  5.             from(files('gradle/test-libs.versions.toml'))
  6.         }
  7.     }
  8. }

发布插件实现共享

虽然从本地文件导入Catalog很方便,但它并没有解决在组织或外部消费者中共享Catalog的问题。

我们还可能通过Catalog插件来发布目录,这样用户直接引入这个插件即可

Gradle提供了一个Catalog插件,它提供了声明然后发布Catalog的能力。

1. 首先引入两个插件
  1. plugins {
  2.     id 'version-catalog'
  3.     id 'maven-publish'
  4. }

然后,此插件将公开可用于声明目录的catalog扩展

2. 定义目录

上面引入插件后,即可使用catalog扩展定义目录

  1. catalog {
  2.     // 定义目录
  3.     versionCatalog {
  4.         from files('../libs.versions.toml')
  5.     }
  6. }

然后可以通过maven-publish插件来发布目录

3. 发布目录
  1. publishing {
  2.     publications {
  3.         maven(MavenPublication) {
  4.             groupId = 'com.zj.catalog'
  5.             artifactId = 'catalog'
  6.             version = '1.0.0'
  7.             from components.versionCatalog
  8.         }
  9.     }
  10. }

我们定义好groupId,artifactId,version,from就可以发布了
我们这里发布到mavenLocal,你也可以根据需要配置发布到自己的maven
以上发布的所有代码可见:Catalog发布相关代码[5]

4. 使用目录

因为我们已经发布到了mavenLocal,在仓库中引入mavenLocal就可以使用插件了

  1. # settings.gradle
  2. dependencyResolutionManagement {
  3.     //...
  4.     repositories {
  5.         mavenLocal()
  6.         //...
  7.     }
  8. }
  9. enableFeaturePreview('VERSION_CATALOGS')
  10. dependencyResolutionManagement {
  11.     versionCatalogs {
  12.         libs {
  13.             from("com.zj.catalog:catalog:1.0.0")
  14.             // 我们也可以重写覆盖catalog中的groovy版本
  15.             version("groovy""3.0.6")
  16.         }
  17.     }
  18. }

如上就成功引入了插件,就可以使用catalog中的依赖了

这样就完成了依赖的项目间共享,以上使用的所有代码可见:Catalog使用相关代码[6]

总结

项目间共享依赖是比较常见的需求,虽然我们也可以通过自定义插件实现,但还是不够方便

Gradle官方终于推出了Catalog,让我们可以方便地实现依赖的共享,Catalog主要具有以下特性:

  1. 对所有module可见,可统一管理所有module的依赖

  2. 支持声明依赖bundles,即总是一起使用的依赖可以组合在一起

  3. 支持版本号与依赖名分离,可以在多个依赖间共享版本号

  4. 支持在单独的libs.versions.toml文件中配置依赖

  5. 支持在项目间共享依赖

本文所有相关代码

Catalog发布相关代码[7]
Catalog使用相关代码[8]

参考资料

Sharing dependency versions between projects[9]

参考资料

[1]

https://juejin.cn/post/6947675376835362846#heading-2

[2]

https://juejin.cn/post/6844903615346245646

[3]

https://juejin.cn/post/6844904169833234439

[4]

https://docs.gradle.org/current/userguide/rich_versions.html#rich-version-constraints

[5]

https://github.com/shenzhen2017/GradleCatalog

[6]

https://github.com/shenzhen2017/GradleCatalog/tree/feature/useCatalog

[7]

https://github.com/shenzhen2017/GradleCatalog

[8]

https://github.com/shenzhen2017/GradleCatalog/tree/feature/useCatalog

[9]

https://docs.gradle.org/current/userguide/platforms.html

转自:掘金  RicardoMJiang

https://juejin.cn/post/6997396071055900680

PS:如果觉得我的分享不错,欢迎大家随手点赞、转发、在看。

PS:欢迎在留言区留下你的观点,一起讨论提高。如果今天的文章让你有新的启发,欢迎转发分享给更多人。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/繁依Fanyi0/article/detail/907356
推荐阅读
相关标签
  

闽ICP备14008679号