I'm trying to find a way to share a dependency's version across multiple Version Catalog toml files.
For example, say I have the following two Version Catalog toml files:
libs.versions.toml
[versions]
dagger = "2.42"
[libraries]
dagger-android = { module = "com.google.dagger:dagger-android", version.ref = "dagger" }
buildLibs.versions.toml
[versions]
dagger = "2.42"
[libraries]
hiltAndroidGradlePlugin = { module = "com.google.dagger:hilt-android-gradle-plugin", version.ref = "dagger" }
I use the same dagger version across both Version Catalogs, and when I need to bump the dagger version I have to remember to update all toml files.
My workaround is to share the version using the Version Catalog builder API by doing:
In my settings.gradle
ext.sharedVersions = [ dagger : "2.42"]
dependencyResolutionManagement {
versionCatalogs {
libs {
version('dagger', sharedVersions.dagger)
library('dagger-android', 'com.google.dagger', 'dagger-android').versionRef('dagger')
}
buildLibs {
version('dagger', sharedVersions.dagger)
library('hiltAndroidGradlePlugin', 'com.google.dagger', 'hilt-android-gradle-plugin').versionRef('dagger')
}
}
}
which works, but takes away from my dependencies being centralized as some are declared in toml files, while other are declared in settings.gradle.
As of now, the Version Catalog Builder API is the recommended solution.
https://discuss.gradle.org/t/share-dependency-versions-across-multiple-version-catalogs/43145
Related
I have some code in my settings.gradle file to dynamically create references to version catalogs:
// list of catalogs is actually loaded from a file
def catalogs = [ "com.example:mycatalog:1.0" ]
dependencyResolutionManagement {
versionCatalogs {
catalogs.each { String catalog ->
def catalogName = catalog.split(":")[1] + "Libs"
logger.info "Add version catalog ${catalogName} = ${catalog}"
create(catalogName, { from(catalog) })
}
}
}
And now I want to share that as a Gradle plugin.
I know that I can write a project plugin as a precompiled script plugin with *.gradle files in src/main/groovy directory.
But then Gradle always builds a Plugin<Project> plugin.
How can I declare that I want to a have Plugin<Settings> plugin? Or is this not even possible?
I'm refactoring a multi module project with version catalogs and I have to add a dependency that is currently like this:
implementation com.mygroup:my-artifact:1.0.0:debug#aar
Since version catalogs doesn't allow to specify the aar type, a workaround would be to specify it directly in the gradle file like this:
implementation(libs.myDependency) { artifact { type = 'aar' } }
This works, but there's an extra complexity: I need to also specify the build type, in the example from above is debug, I cannot find a way to add it.
What I've tried is:
TOML
[libraries]
myDependency = { module = "com.mygroup:my-artifact", version = "1.0.0:debug" }
Gradle
implementation(libs.myDependency) { artifact { type = 'aar' } }
For some reason this doesn't work, how can I also specify the build type?
Found a way to do this! Need to add the classifier into the artifact.
So for the given regular declaration:
build.gradle
dependencies {
implementation com.mygroup:my-artifact:1.0.0:debug#aar
}
The version catalogs way would be:
TOML
[libraries]
myDependency = { module = "com.mygroup:my-artifact", version = "1.0.0" }
build.gradle
dependencies {
implementation(libs.myDependency) { artifact { classifier = 'debug'; type = 'aar' } }
}
or (multiline)
build.gradle
dependencies {
implementation(libs.myDependency) {
artifact {
classifier = 'debug'
type = 'aar'
}
}
}
I have published maven bom and imported it in top level build.gradle.kts as:
allProjects {
dependencies {
implementation(platform("com.example:some-dependencies:1.2.3"))
}
}
And then in libs.versions.toml:
[libraries]
some-bom = { group = "com.example", name="some-dependencies", version="1.2.3" }
When I change first code sample to:
allProjects {
dependencies {
implementation(platform(libs.some.bom))
}
}
I get:
Could not resolve: javax.xml.bind:jaxb-api
Could not resolve: org.springframework.boot:spring-boot-starter-test
...
Is there any way to use Gradle 7 version catalogs with boms?
In my case, it just worked. I'm working on Android project and my script is just like below:
//libs.versions.toml
[libraries]
deps_okhttp_bom = "com.squareup.okhttp3:okhttp-bom:4.9.1"
deps_okhttp_lib = { module ="com.squareup.okhttp3:okhttp" }
deps_okhttp_logging_interceptor = { module= "com.squareup.okhttp3:logging-interceptor"}
//build.xml
dependencies {
implementation platform(libs.deps.okhttp.bom)
implementation libs.deps.okhttp.lib
implementation libs.deps.okhttp.logging.interceptor
}
In your example, you just added dependency for BOM. But as BOM is just an spec sheet which describes versions for each libraries, you need to add dependencies for specific libraries.
Latest Gradle version, 7.0, introduced a feature of central declaration of dependencies. You can now declare your dependencies (versions, libraries or even sets of related libraries - bundles) in a separate file and use them across whole, even multi-module, project:
# libs.versions.toml
[versions]
kotlin = "1.4.32"
tgbotapi = "0.33.3"
[libraries]
tgbotapi-core = { group = "dev.inmo", name = "tgbotapi.core", version.ref = "tgbotapi" }
[bundles]
tgbotapi = ["tgbotapi-core"]
// And then in your build.gradle.kts
dependencies {
implementation(libs.bundles.tgbotapi)
}
However, I cannot make this feature work with the plugins block:
plugins {
kotlin("jvm").version(libs.versions.kotlin).apply(false) // Unresolved reference: libs
}
How do i use this central declaration for plugins?
I made a decision to migrate from Dependency Management Plugin to Gradle built-in BOM import support. Since Gradle built-in BOM import support has better performance But
I run into the issue:
I cannot find alternatives for dependency and dependencySet in native Gradle:
dependencyManagement {
dependencies {
dependency("org.springframework:spring-core:4.0.3.RELEASE")
}
}
//or
dependencyManagement {
dependencies {
dependencySet(group:'org.slf4j', version: '1.7.7') {
entry 'slf4j-api'
entry 'slf4j-simple'
}
}
}
and then I could use dependency without version
dependencies {
compile 'org.springframework:spring-core'
}
How can I get the same behavior in naive Gradle? I mean: I'd like to define a version once as I did it when using Dependency Management Plugin
Solution below helps to avoid versions copy-paste. However it isn't the same with Dependency Management plugin.
For Gradle Kotlin Dsl:
You can create buildSrc with you own code, when you can place any constants.
Algorithm:
Create folder buildSrc/src/main/kotlin
Create file buildSrc/src/main/kotlin/Versions.kt with content:
object Versions {
const val junitVersion = "5.5.5" // just example
}
Create file buildSrc/build.gradle.kts with content:
plugins {
`kotlin-dsl`
}
Use the following syntax in your gradle.kts files:
dependencies {
testImplementation("org.junit.jupiter:junit-jupiter:${Versions.junitVersion}")
}
For Gradle Groovy:
Create file gradle.properties
Put versions there with syntax like okhttp_version=4.2.0
Use the following syntax in your gradle files:
dependencies {
compile group: 'com.squareup.okhttp3', name: 'okhttp', version: okhttp_version
}
You can do so on the gradle.properties file. I.e.:
# APPLICATION PROPERTIES
name=projectName
group=com.domain
version=1.0.0
description=A brief description
gradleScripts=https://raw.githubusercontent.com/hexagonkt/hexagon/1.2.0/gradle
# DEPENDENCIES VERSIONS
kotlinVersion=1.3.61
kotlinCoroutinesVersion=1.3.2
Or in settings.gradle if you don't want to create another file:
rootProject.name = "hexagon-contact-application"
gradle.rootProject {
allprojects {
version = "1.0.0"
group = "org.hexagonkt"
description = "Contact application backend api"
}
extensions.gradleScripts = "https://raw.githubusercontent.com/hexagonkt/hexagon/1.0.18/gradle"
extensions.kotlinVersion = "1.3.50"
extensions.kotlinCoroutinesVersion = "1.3.2"
extensions.hexagonVersion = "1.0.21"
extensions.logbackVersion = "1.2.3"
extensions.bcryptVersion="0.8.0"
extensions.javaJwtVersion="3.8.2"
}
And if you want to avoid adding the version variable to all related dependencies, you can create a method in the build file:
plugins {
id 'org.jetbrains.kotlin.jvm' version '1.3.50'
}
apply from: "$gradleScripts/kotlin.gradle"
apply from: "$gradleScripts/service.gradle"
apply from: "$gradleScripts/junit.gradle"
defaultTasks("test")
mainClassName = 'com.hexagonkt.contact.ApplicationKt'
applicationDefaultJvmArgs = ["-Xms64M", "-Xmx2G", "-XX:+UseNUMA", "-XX:+UseParallelGC"]
dependencies {
httpkt(it, "http_server_jetty")
httpkt(it, "store_mongodb")
httpkt(it, "hexagon_web")
implementation("at.favre.lib:bcrypt:$bcryptVersion")
implementation("com.auth0:java-jwt:$javaJwtVersion")
testImplementation("com.hexagonkt:port_http_client:$hexagonVersion")
}
private void httpkt(final def dependencies, final String artifact) {
dependencies.implementation("com.hexagonkt:$artifact:$hexagonVersion")
}