
本文原作者:程序員江同學,原文發布於:程序員江同學
隨着項目的不斷發展,項目中的依賴也越來越多,有時可能會有幾百個,這個時候對項目依賴做一個統一的管理很有必要,我們一般會有以下需求:不同 Module 中的依賴版本號統一
不同項目中的依賴版本號統一
使用循環優化 Gradle 依賴管理
使用 buildSrc 管理 Gradle 依賴
使用 includeBuild 統一配置依賴版本
上面的方案支持在不同 Module 間統一版本號,同時如果需要在項目間共享,也可以做成 Gradle 插件發布到遠端,已經基本可以滿足我們的需求。
不過 Gradle 7.0 推出了一個新的特性,使用 Catalog 統一依賴版本,它支持以下特性:對所有 module 可見,可統一管理所有 module 的依賴
支持聲明依賴 bundles,即總是一起使用的依賴可以組合在一起
支持版本號與依賴名分離,可以在多個依賴間共享版本號
支持在單獨的 libs.versions.toml 文件中配置依賴
支持在項目間共享依賴
注意,Catalog 仍然是一個孵化中的特性,如需使用,需要在 settings.gradle 中添加以下內容:enableFeaturePreview('VERSION_CATALOGS')從命名上也可以看出,Version Catalog 其實就是一個版本的目錄,我們可以從目錄中選出我們需要的依賴使用。我們可以通過如下方式使用 Catalog 中聲明的依賴:dependencies { implementation(libs.retrofit) implementation(libs.groovy.core)}在這種情況下,libs 是一個目錄,retrofit 表示該目錄中可用的依賴項。與直接在構建腳本中聲明依賴項相比,Version Catalog 具有許多優點:
對於每個 catalog,Gradle 都會生成類型安全的訪問器,以便您在 IDE 中可以自動補全。(注: 目前在 build.gradle 中還不能自動補全,可能是指 kts 或者開發中?)
聲明在 catalog 中的依賴對所有 module 可見,當修改版本號時,可以統一管理統一修改
catalog 支持聲明一個依賴 bundles,即一些總是一起使用的依賴的組合
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 的版本號。因為在不同的項目中經常系統地一起使用某些依賴項,所以 Catalog 提供了 bundle (依賴包) 的概念。依賴包基本上是幾個依賴項打包的別名。例如,您可以這樣使用一個依賴包,而不是像上面那樣聲明 3 個單獨的依賴項:dependencies { implementation libs.bundles.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 { id 'java-library' id 'checkstyle' // 使用聲明的插件 alias(libs.plugins.jmh)}除了在 settings.gradle 中聲明 Catalog 外,也可以通過一個單獨的文件來配置 Catalog。
如果在根構建的 gradle 目錄中找到了 libs.versions.toml 文件,則將使用該文件的內容自動聲明一個 Catalog。
[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 支持通過從 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 的能力。首先引入兩個插件
plugins { id 'version-catalog' id 'maven-publish'}然後,此插件將公開可用於聲明目錄的 catalog 擴展。定義目錄
上面引入插件後,即可使用 catalog 擴展定義目錄。
catalog { // 定義目錄 versionCatalog { from files('../libs.versions.toml') }}然後可以通過 maven-publish 插件來發布目錄。
publishing { publications { maven(MavenPublication) { groupId = 'com.zj.catalog' artifactId = 'catalog' version = '1.0.0' from components.versionCatalog } }}我們定義好 groupId,artifactId,version,from 就可以發布了。
我們這裡發布到 mavenLocal,您也可以根據需要配置發布到自己的 maven
以上發布的所有代碼可見:Catalog 發布相關代碼
使用目錄
因為我們已經發布到了 mavenLocal,在倉庫中引入 mavenLocal 就可以使用插件了。
# settings.gradledependencyResolutionManagement { //... 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 的依賴支持聲明依賴 bundles,即總是一起使用的依賴可以組合在一起
支持版本號與依賴名分離,可以在多個依賴間共享版本號
支持在單獨的 libs.versions.toml 文件中配置依賴
支持在項目間共享依賴
"開發者說·DTalk" 面向
中國開發者們徵集 Google 移動應用 (apps & games)相關的產品/技術內容。歡迎大家前來分享您對移動應用的行業洞察或見解、移動開發過程中的心得或新發現、以及應用出海的實戰經驗總結和相關產品的使用反饋等。我們由衷地希望可以給這些出眾的中國開發者們提供更好展現自己、充分發揮自己特長的平台。我們將通過大家的技術內容着重選出優秀案例進行谷歌開發技術專家 (GDE)的推薦。
點擊屏末|閱讀原文|即刻報名參與"開發者說·DTalk"
