Gradle's central declaration for plugins block? - gradle

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?

Related

Share dependency versions across multiple Version Catalogs

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

Gradle 7.0 Version Catalog for maven bom

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.

How to define dependency version only once for whole Gradle multi-module project?

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")
}

How to Make Kotlin Gradle Plugin not Manage Version

When I use Kotlin Gradle Plugin and consume Kotlin BOM at the same time it seems that the plugin version takes in priority for kotlin-stdlib, how do I make the plugin not manage my dependency?
plugins {
kotlin("jvm") version "1.2.50"
}
dependencies {
implementation(platform("some-bom:0.3")) // this has API dependency to kotlin-bom 1.3.50
implementation(kotlin("stdlib")) // this resolves to 1.2.50 (plugin version) instead of 1.3.50 (BOM version)
}
Project is using Gradle 5.2.1
I can't reproduce it, it looks like a bug. As a workaround you can enforce a particular version by specify isForce = true:
implementation("org.jetbrains.kotlin:kotlin-stdlib:1.2.50") {
isForce = true
}
implementation("org.jetbrains.kotlin:kotlin-stdlib-common:1.3.10"){
isForce = true
}
isForce is not transitive, so you have to specify all the transitive kotlin dependencies explicitly with isForce flag true or create a virtual platform:
open class KotlinAlignmentRule : ComponentMetadataRule {
override fun execute(ctx: ComponentMetadataContext) {
ctx.details.run {
if (id.group == "org.jetbrains.kotlin") {
belongsTo("org.jetbrains.kotlin:kotlin-platform:${id.version}")
}
}
}
}
And add it to your dependencies block:
dependencies {
components.all(KotlinAlignmentRule::class.java)
implementation(platform("some-bom:0.3"))
implementation("org.jetbrains.kotlin:kotlin-stdlib:1.2.50") {
isForce = true
}
}
This last solution is the best imo.

package fat jar using gradle with transitive dependencies

I would like to create fat jar using gradle. I am using the shadowJar plugin(com.github.johnrengelman.shadow).
The problem that I am facing is that I cannot find a way to instruct the plugin to package a certain libraries with their transitive dependencies.
For example: I am using hive-jdbc which depends on org.apache.httpcomponents:httpclient:4.5.2, however the final jar packaged by shadowJar does not include httpclient
Another option is to drop the shadowJar section from the gradle.build file, but then the plugin will include everything that is part of the compile classpath and huge jar file will be created.
I am using this build file in order to package a jar for spark-submmit that includes many libraries as part of the runtime environment, so I do not need all the compile dependencies to be packaged (just the ones I am specifying explicitly and their transitive dependencies)
build.gradle:
import com.github.jengelman.gradle.plugins.shadow.transformers.AppendingTransformer
plugins {
id "com.github.johnrengelman.shadow" version "2.0.3"
}
apply from: "../Parent_2.2/build.gradle"
group 'com.ebates.bigdata'
version '1.0-SNAPSHOT'
dependencies{
compile("com.databricks:spark-avro_2.11:4.0.0"){force = true}
compile("org.apache.hadoop:hadoop-client:2.6.5"){force = true}
compile("org.apache.hadoop:hadoop-aws:2.6.5"){force = true}
compile("org.postgresql:postgresql:9.4.1207"){force = true}
compile("org.apache.hive:hive-jdbc:2.2.0"){force = true}
}
configurations.all {
resolutionStrategy.cacheChangingModulesFor 0, 'seconds'
}
shadowJar {
mergeServiceFiles()
transform(AppendingTransformer) {
resource = 'reference.conf'
shadowJar.classifier = ""
zip64 true
dependencies {
include(dependency("com.databricks:spark-avro_2.11:4.0.0"))
include(dependency("org.postgresql:postgresql:9.4.1207"))
include(dependency("org.apache.hive:hive-jdbc:2.2.0"))
}
}
}

Resources