隨著項目的不斷發展,項目中的依賴也越來越多,有時可能會有幾百個,這個時候對項目依賴做一個統一的管理很有必要,我們一般會有以下需求:
1、項目依賴統一管理,在單獨文件中配置。
2、不同Module中的依賴版本號統一。
3、不同項目中的依賴版本號統一。
針對這些需求,目前其實已經有了一些方案:
使用循環優化Gradle依賴管理
https://juejin.cn/post/6947675376835362846#heading-2
使用buildSrc管理Gradle依賴
https://juejin.cn/post/6844903615346245646
使用includeBuild統一配置依賴版本
https://juejin.cn/post/6844904169833234439
上面的方案支持在不同Module間統一版本號,同時如果需要在項目間共享,也可以做成Gradle插件發布到遠端,已經基本可以滿足我們的需求。
不過Gradle7.0推出了一個新的特性,使用Catalog統一依賴版本,它支持以下特性:
1、對所有module可見,可統一管理所有module的依賴。
2、支持聲明依賴bundles,即總是一起使用的依賴可以組合在一起。
3、支持版本號與依賴名分離,可以在多個依賴間共享版本號。
4、支持在單獨的libs.versions.toml文件中配置依賴。
5、支持在項目間共享依賴。
注意,Catalog仍然是一個孵化中的特性,如需使用,需要在settings.gradle中添加以下內容:
enableFeaturePreview('VERSION_CATALOGS')
從命名上也可以看出,Version Catalog其實就是一個版本的目錄,我們可以從目錄中選出我們需要的依賴使用。
我們可以通過如下方式使用Catalog中聲明的依賴。
dependencies?{
????implementation(libs.retrofit)
????implementation(libs.groovy.core)
}
在這種情況下,libs是一個目錄,retrofit表示該目錄中可用的依賴項。與直接在構建腳本中聲明依賴項相比,Version Catalog具有許多優點:
1、對于每個catalog,Gradle都會生成類型安全的訪問器,以便你在IDE中可以自動補全。(注:目前在build.gradle中還不能自動補全,可能是指kts或者開發中?)
2、聲明在catalog中的依賴對所有module可見,當修改版本號時,可以統一管理統一修改。
3、catalog支持聲明一個依賴bundles,即一些總是一起使用的依賴的組合。
4、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"
minSdk21
????????targetSdk?libs.versions.targetsdk.get().toInteger()
????}
}
如上,可以使用catalog統一compileSdk,targetSdk,minSdk的版本號。
因為在不同的項目中經常系統地一起使用某些依賴項,所以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)
}
除了在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。
https://docs.gradle.org/current/userguide/rich_versions.html#rich-version-constraints
[versions]
my-lib?=?{?strictly?="[1.0,?2.0[",?prefer?="1.2"}
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發布相關代碼。
https://github.com/shenzhen2017/GradleCatalog
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使用相關代碼。
https://github.com/shenzhen2017/GradleCatalog/tree/feature/useCatalog
項目間共享依賴是比較常見的需求,雖然我們也可以通過自定義插件實現,但還是不夠方便
Gradle官方終于推出了Catalog,讓我們可以方便地實現依賴的共享,Catalog主要具有以下特性:
1、對所有module可見,可統一管理所有module的依賴。
2、支持聲明依賴bundles,即總是一起使用的依賴可以組合在一起。
3、支持版本號與依賴名分離,可以在多個依賴間共享版本號。
4、支持在單獨的libs.versions.toml文件中配置依賴。
5、支持在項目間共享依賴。