使用Git Submodule减少Gradle构建配置模板代码
前言
最近为了学习和了解KMP,先后创建了TODO-LIST和E-Wallet两个项目。在笔者每次创建新的项目之后,都要copy一个名为build-logic的文件夹到新的项目上去,虽然偶尔会根据情况进行一些修改,其实基本上是没有多大改动的,于是在想,如果通过submodule进行管理是不是会更方便些?
介绍
nowinandroid这个项目是一个非常值得去看去学习的,项目不大,阅读代码也不需要花太多时间。
在nowinandroid
项目中,对modularization和architecture有详细的介绍文档。而build-logic
目的就在于实现modularization时,提供使用和配置的方便性。我们知道,多模块项目中,每个模块都有一个gradle配置文件,而构建配置的复杂性将影响着模块的同步时间和维护成本。另外,如果我们不整合管理,模块的增加将带来持续的维护成本。而约定插件可以将这些可重用和可组合的构建配置提取成kotlin代码中管理。在对应模块配置的时候apply对应的plugin id即可。
修改
1. 删除不确定依赖关系
在nowinandroid
中,build-logic
作为一个单个项目的约定插件管理模块,其内部存在对外部其他模块的依赖。但如果想将其作为一个submodule,对外部这些不确定的依赖自然需要删除,所以在architecture提到的各层相关模块依赖关系需要从中删除,保留基本的构建配置项即可。
2. 增加构建配置项支持
在nowinandroid
中,build-logic
中已有jacoco
,app
,feature
,library
,hilt
等常用可组合构建配置插件,但是项目不同,构建配置需求也会不一样。就比如,在KMP(Android/iOS)项目中,在app
,feature
,library
上的构建配置是不一样的,并且di上koin
比hilt
有更好的可用性。所以增加构建配置项的支持,能大大增加submodule的适配可行性。
3. 加上catalog的管理并保留可覆盖和可扩展性
在可配置项中,比如hilt
,koin
,jacoco
等,需要使用到依赖库的版本等信息,所以catalog的管理是需要的。笔者在仓库中增加了默认的版本库,并提供一些常用的依赖库参考使用。而且当使用者使用自己catalog并将名字设置为libs
即可覆盖使用。
使用
Step1 使用submodule
git submodule add https://github.com/BreakZero/build-logic
Step2 配置必须catalog
- Option 1 直接使用
build-logic
目录下的default.versions.toml
在project目录下的settings.gradle.kts
中,将下面的代码copy到dependencyResolutionManagement
块中versionCatalogs { create("libs") { from(files("./build-logic/default.versions.toml")) } }
- Option 2 使用自己的catalog文件
- 在项目
gradle
目录下,创建一个名为libs.versions.toml
的文件 - 把
build-logic
目录下的default.versions.toml
内容全部copy到你的catalog下,再自行添加其他的。(catalogs
目录下有参考)
Step3 进行gradle同步操作并使用
通过ide操作同步gradle进行初始构建,在同步成功后,便可以直接使用plugin替换相关模块的gradle配置项
如:
plugins {
alias(libs.plugins.android.application) apply false
alias(libs.plugins.kotlin-android) apply false
id("easy.android.application")
id("easy.android.application.compose")
}
dependencies {
implementation(libs.core.ktx)
implementation(libs.androidx.compose.activity)
}
经过使用plugin之后,gradle配置文件内容将大大减少,基本如下内容所示,只需对dependencies
做好管理即可。
@Suppress("DSL_SCOPE_VIOLATION")
plugins {
alias(easy.plugins.android.feature.koin)
alias(easy.plugins.android.library.jacoco)
}
android {
namespace = "com.easy.wallet.home"
}
dependencies {
implementation(project(":Wallet-Android:design-system"))
implementation(project(":Wallet-Android:core"))
implementation(project(":platform:datastore"))
implementation(project(":platform:shared"))
implementation(project(":platform:model"))
implementation(libs.androidx.paging)
implementation(libs.androidx.paging.compose)
}
更多可以查看E-Wallet下的配置文件比较。
项目地址
总结
- 目前这个submodule也是通过在两个项目使用的过程中一步一步慢慢整理出来的,对于一些相对特殊的情况并不会被考虑到
- 虽然submodule确实减少了一部分工作,但是同时也丢失了一部分方便性,例如前文提到的
architecture
中各层相关模块的依赖性,因为层与层之间的依赖确定性基本不会改变,所以这块如果在kotlin代码中也会减少很多维护成本的。 - 虽如#2所说,但是在
multi-repo
项目中,这种使用方式笔者还是比较推荐的。
不过在这方面仁者见仁,智者见智吧。 Have a good day!!!