Gradle 统一版本控制
说实在的,对于Gradle的版本控制来讲,这里面能讲的也许还没有上一篇多模块能讲的多。
BuildSrc
开门见山,首先我选择的版本控制方案是通过 buildSrc
来实现的。有关它的官方介绍,你可以参考Gradle的文档 《Use buildSrc to abstract imperative logic》 。
那么什么是buildSrc
呢?通俗一点并带些个人理解的来讲,buildSrc
就是 Gradle
保留给你作为抽象层用的。你可以在这里定义一些类似于全局的逻辑或者变量,来供于各个其他模块来使用。
那么怎么用呢?你只需要在项目根目录下创建一个目录 buildSrc
, 然后在这个目录下创建一个 build.gradle.kts
配置脚本,结构如下:
由于我是使用Gradle Kotlin DSL作为脚本配置文件的,所以构建脚本的扩展名是
.kts
。
root
├── buildSrc
│ ├── src/main/kotlin
│ └── build.gradle.kts
│
│
├── build.gradle.kts
├── gradle.properties
└── settings.gradle.kts
复制代码
build.gradle.kts
中的内容大致为:
plugins {
`kotlin-dsl`
}
repositories {
mavenCentral()
}
kotlin {
// kotlin 配置..
}
dependencies {
api(gradleApi())
}
复制代码
由于我打算通过 Kotlin
进行配置,如果你打算使用Java或者Groovy也是完全可以的。有关于这个 kotlin-dsl
插件,你可以参考官方文档的描述:《The Kotlin DSL Plugin》 。
那么 buildSrc
环境配置好了之后,接下来该怎么做呢?假如我们现在有一个普通的模块,他们使用了下面的依赖:
implementation("com.example:example-api:11.45.14")
implementation("com.example:example-core:11.45.14")
复制代码
然后我希望能够统一配置这个依赖的版本号,那么你可以在buildSrc
中创建一个存放常量的类,这里简单点儿,比如说就叫 D.kt
, 用来代表 Dependency
:
root
├── buildSrc
│ ├── src/main/kotlin
│ │ └── D.kt
│ │
│ └── build.gradle.kts
│
│
├── build.gradle.kts
├── gradle.properties
└── settings.gradle.kts
复制代码
文件里,你可以这么写:
object D {
const val EXAMPLE_VERSION = "11.45.14"
}
复制代码
然后,修改其他的普通模块,让他们的依赖变为:
implementation("com.example:example-api:${D.EXAMPLE_VERSION}")
implementation("com.example:example-core:${D.EXAMPLE_VERSION}")
复制代码
这就是最基础的一种统一版本控制啦~通过这种方式你也许就不需要在每一个模块下都去写一遍版本号了。也许概念上...还是比较类似于Maven的 properties
标签的吧?
不过 buildSrc
能做到的不仅仅是配置版本号,一开始说到,它可以用来抽象逻辑,因此你可以将各种各样重复的逻辑也一同抽象到这里,让你的模块配置变得简洁、干净。
邪道
讲完了比较基础的版本控制,我发现这篇文章的字数属实是有点儿少。因此我打算把我配置版本控制的方式跟大家分享一下,也就当看个乐子:
abstract class Dependency(val groupId: String, val name: String, val version: String? = null) {
val notation: String = if (version != null) "$groupId:$name:$version" else "$groupId:$name"
override fun toString(): String = "DependencyNotation(notation=$NOTATION)"
}
object D {
sealed class Example(id: String) : Dependency("com.example", "example-$id", VERSION) {
companion object {
const val VERSION = "11.45.14"
}
object Api : Example("api")
object Core : Example("core")
}
// ...其他
}
复制代码
在其他模块中:
implementation(D.Example.Api.notation)
implementation(D.Example.Core.notation)
复制代码
我通过各种嵌套的 sealed class
和 object
代替了常量版本号,直接通过调用的方式导入依赖。这种方法的好处还是有的,比如你能更有层次感的去使用依赖之类的。
但是说实在的,我并不非常推荐你使用这种方式。