Kotlin DSL: Import a versions.gradle.kts into another build.gradle.kts - gradle

I have created a versions.gradle.kts just like that:
object Defines {
const val kotlinVersion = "1.2.61"
const val junitVersion = "5.3.0"
}
Now I want to import and use that files like that:
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
group = "io.github.deglans"
version = "0.0.1-SNAPSHOT"
plugins {
application
kotlin("jvm") version Defines.kotlinVersion
}
application {
mainClassName = "io.github.deglans.polishnotation.MainKt"
}
dependencies {
compile(kotlin("stdlib-jdk8"))
testCompile("org.junit.jupiter", "junit-jupiter-api", Defines.junitVersion)
testRuntime("org.junit.jupiter", "junit-jupiter-engine", Defines.junitVersion)
}
tasks.withType<KotlinCompile> {
kotlinOptions.jvmTarget = "1.8"
}
How can I do that?
NOTE:
I have already seen this post but it is not exactly that I search...

While I think it should be possible to import another gradle.kts file, I couldn't get it to work properly.
However, I did manage to define my dependencies in a separate Kotlin file in the buildSrc directory.
Create a buildSrc folder in the root of your project (same level as build.gradle.kts)
Add a build.gradle.kts in that buildSrc folder. Here, you need to define the kotlin-dsl plugin. You also need to define the repository where to get the plugin.
plugins {
`kotlin-dsl`
}
repositories {
mavenCentral()
}
Create a Kotlin file where you define your dependencies in src/main/kotlin inside the buildSrcfolder. You need to create a normal Kotlin .kt file, not a gradle.kts.
Reimport your Gradle config and you can now use the variables you defined in your Kotlin file created in step #3 in your build.gradle.kts.

Related

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 do I use the native JUnit 5 support in Gradle with the Kotlin DSL?

I want to use the built-in JUnit 5 with the Gradle Kotlin DSL, because during build I get this warning:
WARNING: The junit-platform-gradle-plugin is deprecated and will be discontinued in JUnit Platform 1.3.
Please use Gradle's native support for running tests on the JUnit Platform (requires Gradle 4.6 or higher):
https://junit.org/junit5/docs/current/user-guide/#running-tests-build-gradle
That links tells me to put
test {
useJUnitPlatform()
}
in my build.gradle, but what is the syntax for build.gradle.kts?
My current build file is
import org.gradle.api.plugins.ExtensionAware
import org.junit.platform.gradle.plugin.FiltersExtension
import org.junit.platform.gradle.plugin.EnginesExtension
import org.junit.platform.gradle.plugin.JUnitPlatformExtension
group = "com.example"
version = "0.0"
// JUnit 5
buildscript {
repositories {
mavenCentral()
jcenter()
}
dependencies {
classpath("org.junit.platform:junit-platform-gradle-plugin:1.2.0")
}
}
apply {
plugin("org.junit.platform.gradle.plugin")
}
// Kotlin configuration.
plugins {
val kotlinVersion = "1.2.41"
application
kotlin("jvm") version kotlinVersion
java // Required by at least JUnit.
// Plugin which checks for dependency updates with help/dependencyUpdates task.
id("com.github.ben-manes.versions") version "0.17.0"
// Plugin which can update Gradle dependencies, use help/useLatestVersions
id("se.patrikerdes.use-latest-versions") version "0.2.1"
}
application {
mainClassName = "com.example.HelloWorld"
}
dependencies {
compile(kotlin("stdlib"))
// To "prevent strange errors".
compile(kotlin("reflect"))
// Kotlin reflection.
compile(kotlin("test"))
compile(kotlin("test-junit"))
// JUnit 5
testImplementation("org.junit.jupiter:junit-jupiter-api:5.2.0")
testRuntimeOnly("org.junit.jupiter:junit-jupiter-engine:5.2.0")
testRuntime("org.junit.platform:junit-platform-console:1.2.0")
// Kotlintest
testCompile("io.kotlintest:kotlintest-core:3.1.0-RC2")
testCompile("io.kotlintest:kotlintest-assertions:3.1.0-RC2")
testCompile("io.kotlintest:kotlintest-runner-junit5:3.1.0-RC2")
}
repositories {
mavenCentral()
mavenLocal()
jcenter()
}
(The following is some blabla because this question 'contains mostly code').
I tried to find documentation on how to customize tasks in the Kotlin DSL, but I couldn't find any. In normal Groovy you can just write the name of the task and then change things in the block, but the Kotlin DSL doesn't recognise the task as such, unresolved reference.
Also, this question is related but asks for creating of new tasks, instead of customize existing tasks: How do I overwrite a task in gradle kotlin-dsl
Here is a solution for normal Gradle.
[Edit april 2019] As Pedro has found, three months after I asked this question Gradle actually created a user guide for the Kotlin DSL which can be visited at https://docs.gradle.org/current/userguide/kotlin_dsl.html
They also added a migration guide from Groovy to Kotlin at https://guides.gradle.org/migrating-build-logic-from-groovy-to-kotlin/
Answer:
The syntax you ask for is
tasks.test {
// Use the built-in JUnit support of Gradle.
useJUnitPlatform()
}
which I figured out from this example file from the Kotlin DSL GitHub, or you can use
tasks.withType<Test> {
useJUnitPlatform()
}
which is used in the this official userguide which was created a couple of months after this answer was written (thanks to Pedro's answer for noting this).
But in any case you actually are still using the buildscript block, which is a bit deprecated itself, use the new plugins DSL instead (docs). New build.gradle.kts becomes
group = "com.example"
version = "0.0"
plugins {
val kotlinVersion = "1.2.41"
application
kotlin("jvm") version kotlinVersion
java // Required by at least JUnit.
// Plugin which checks for dependency updates with help/dependencyUpdates task.
id("com.github.ben-manes.versions") version "0.17.0"
// Plugin which can update Gradle dependencies, use help/useLatestVersions
id("se.patrikerdes.use-latest-versions") version "0.2.1"
}
application {
mainClassName = "com.example.HelloWorld"
}
dependencies {
compile(kotlin("stdlib"))
// To "prevent strange errors".
compile(kotlin("reflect"))
// Kotlin reflection.
compile(kotlin("test"))
compile(kotlin("test-junit"))
// JUnit 5
testImplementation("org.junit.jupiter:junit-jupiter-api:5.2.0")
testRuntimeOnly("org.junit.jupiter:junit-jupiter-engine:5.2.0")
testRuntime("org.junit.platform:junit-platform-console:1.2.0")
// Kotlintest
testCompile("io.kotlintest:kotlintest-core:3.1.0-RC2")
testCompile("io.kotlintest:kotlintest-assertions:3.1.0-RC2")
testCompile("io.kotlintest:kotlintest-runner-junit5:3.1.0-RC2")
}
repositories {
mavenCentral()
mavenLocal()
jcenter()
}
tasks {
// Use the native JUnit support of Gradle.
"test"(Test::class) {
useJUnitPlatform()
}
}
(Since the Gradle Kotlin DSL has almost no documentation at all except a few (undocumented) example files on GitHub, I'm documenting a few common examples here.)
(Complete example project at GitHub, self-promotion...)
Adding on top of accepted answer, it is also possible to use typed task configuration like:
tasks.withType<Test> {
useJUnitPlatform()
}
Update:
Gradle docs for reference here. Specifically Example 19 which has:
tasks.withType<JavaCompile> {
options.isWarnings = true
// ...
}
this worked for me till now...
plugins {
kotlin("jvm") version "1.7.10"
}
group = "org.example"
version = "1.0-SNAPSHOT"
repositories {
mavenCentral()
}
dependencies {
testImplementation(kotlin("test"))
testImplementation("org.junit.jupiter:junit-jupiter:5.9.0")
testRuntimeOnly("org.junit.jupiter:junit-jupiter-engine:5.9.0")
}
tasks.test {
useJUnitPlatform()
}
tasks.withType<KotlinCompile> {
kotlinOptions.jvmTarget = "1.8"
}

Building a Gradle Kotlin project with Java 9/10 and Gradle's Kotlin DSL

This is kind of a follow up to Building a Kotlin + Java 9 project with Gradle. In the linked post Gradle with Groovy is used. In my case Kotlin DSL is used.
Basically I have a gradle project with the following structure (only relevant content here):
src/
| main/
| | kotlin/
| | | com/example/testproject/
| | | | Main.kt
| | | module-info.java
build.gradle.kts
settings.gradle
Usually I would run gradle run on it, but that results in the following error:
module-info.java:3: error: module not found: kotlin.stdlib
requires kotlin.stdlib;
Now this is what my build file currently looks like
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
buildscript {
var kotlin_version: String by extra
kotlin_version = "1.2.41"
repositories {
mavenCentral()
}
dependencies {
classpath(kotlin("gradle-plugin", kotlin_version))
}
}
repositories {
mavenCentral()
}
plugins {
kotlin("jvm") version "1.2.41"
application
}
val kotlin_version: String by extra
dependencies {
implementation(kotlin("stdlib", kotlin_version))
implementation(kotlin("stdlib-jdk8", kotlin_version))
implementation(kotlin("runtime", kotlin_version))
implementation(kotlin("reflect", kotlin_version))
}
val group = "com.example"
application {
mainClassName = "$group.testproject.Main"
}
java {
sourceCompatibility = JavaVersion.VERSION_1_10
targetCompatibility = sourceCompatibility
sourceSets {
"main" {
java.srcDirs("src/main/kotlin")
}
}
}
tasks.withType<KotlinCompile> {
kotlinOptions.jvmTarget = "1.8"
}
And this is my module-info.java:
module com.example.testproject {
// Kotlin compatibility
requires kotlin.stdlib;
exports com.example.testproject;
}
Question: How to get the solution provided in the linked post (or any other solution) running, so that a Kotlin project with Gradle's Kotlin DSL can be compiled using a Java 9/10 environment?
This is kind of a self-answer (I do not full understand that matter, so the explanations might not be correct). The conclusions I draw here are purely empiric and based on a conversion from Kotlin DSL to Gradle's Groovy and back.
The first problem I encountered was that I had two conflicting providers for the Kotlin functions in:
implementation(kotlin("stdlib", kotlin_version))
implementation(kotlin("runtime", kotlin_version))
I solved that by deciding to go with stdlib. All other dependencies did not conflict with each other.
The more severe problem was something different: The compileJava task did not find the correct classes (from the project) and modules (from the distribution). Therefore I needed to adapt the paths as in the following example:
val compileKotlin: KotlinCompile by tasks
val compileJava: JavaCompile by tasks
compileJava.destinationDir = compileKotlin.destinationDir
This basically compiles the Java classes within Kotlins compiled output and makes Java find the classes from the project.
The last problem could finally be solved by the following non-idiomatic piece of Kotlin Script:
tasks {
"compileJava" {
dependsOn(":compileKotlin")
if (JavaVersion.current() >= JavaVersion.VERSION_1_9) {
inputs.property("moduleName", ext["moduleName"])
doFirst {
compileJava.options.compilerArgs = listOf(
// include Gradle dependencies as modules
"--module-path", java.sourceSets["main"].compileClasspath.asPath,
)
java.sourceSets["main"].compileClasspath = files()
}
}
}
}
This basically lets the compileJava task use an empty classpath and sets module path as compiler option to the currently set compileClasspath of the main source set (the Kotlin source set which is also added as Java source set).

Unable to resolve library using Gradle. Resolved using Grape

I'm fairly new to Groovy and I'm trying to wrap my head around Gradle. If I import the org.jvnet.hudson.plugins through Grapes it works perfectly and the dependency is resolved. But if I try to retrieve the dependency using Gradle the dependency is not resolved.
The package org.eclipse.hudson:hudson-core:3.2.1 works with both Gradle and Grape.
A dependency that is not resolved using Gradle
compile 'org.jvnet.hudson.plugins:checkstyle:3.42'
A dependency which is resolved using Grape
#Grab('org.jvnet.hudson.plugins:checkstyle:3.42')
A dependency which is resolved using Gradle
compile 'org.eclipse.hudson:hudson-core:3.2.1'
Error during Gradle build
line 3, column 1.
import hudson.plugins.checkstyle.CheckStyleResultAction;
^
The build.gradle
apply plugin: 'groovy'
repositories {
mavenCentral()
maven {
url "http://repo.jenkins-ci.org/releases/"
}
}
configurations {
ivy
}
sourceSets {
main {
groovy {
srcDirs = ['src/']
}
}
test {
groovy {
srcDirs = ['test/']
}
}
}
dependencies {
compile 'org.codehaus.groovy:groovy-all:2.4.11'
compile "org.apache.ivy:ivy:2.4.0"
ivy "org.apache.ivy:ivy:2.3.0"
// Works
compile 'org.eclipse.hudson:hudson-core:3.2.1'
// Does not work
compile 'org.jvnet.hudson.plugins:checkstyle:3.42'
}
tasks.withType(GroovyCompile) {
groovyClasspath += configurations.ivy
}
You're probably not actually downloading the jar you think you are. Looks like the default artifact that comes back from the org.jvnet.hudson.plugins:checkstyle:3.42 dependency is actually a file named checkstyle-3.42.hpi.
To get the jar which contains the classes instead, use:
compile group: 'org.jvnet.hudson.plugins', name: 'checkstyle', version:'3.42', ext: 'jar'
Then that class will be found on your classpath (and you'll be on to locating the next missing dependency).

ext in buildscript can not be recognised by Gradle Kotlin DSL

In these days, I am trying to write some codes to experience the Spring reactive features and kotlin extension in Spring 5, and I also prepared a gradle Kotlin DSL build.gradle.kt to configure the gradle build.
The build.gradle.kt is converted from Spring Boot template codes generated by http://start.spring.io.
But the ext in the buildscript can not be detected by Gradle.
buildscript {
ext { }
}
The ext will cause Gradle build error.
To make the variables in classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlinVersion") and compile("org.jetbrains.kotlin:kotlin-stdlib-jre8:$kotlinVersion") work, I added the variables in the hard way.
val kotlinVersion = "1.1.4"
val springBootVersion = "2.0.0.M3"
But I have to declare them in global top location and duplicate them in the buildscript.
Code: https://github.com/hantsy/spring-reactive-sample/blob/master/kotlin-gradle/build.gradle.kts
Is there a graceful approach to make ext work?
Update: There are some ugly approaches:
From Gradle Kotlin DSL example, https://github.com/gradle/kotlin-dsl/tree/master/samples/project-properties, declares the properties in gradel.properties.
kotlinVersion = 1.1.4
springBootVersion = 2.0.0.M3
And use it in build.gradle.kts.
buildScript{
val kotlinVersion by project
}
val kotlinVersion by project //another declare out of buildscript block.
Similar with above declare them in buildScript block:
buildScript{
extra["kotlinVersion"] = "1.1.4"
extra["springBootVersion"] = "2.0.0.M3"
val kotlinVersion: String by extra
}
val kotlinVersion: String by extra//another declare out of buildscript block.
How can I avoid the duplication of val kotlinVersion: String by extra?
With Kotlin DSL ext has been changed to extra and it can be used under buildscript.
Eg :-
buildscript {
// Define versions in a single place
extra.apply{
set("minSdkVersion", 26)
set("targetSdkVersion", 27)
}
}
It is possible to use constants defined in .kt file in .gradle.kts files.
create buildSrc folder in root folder of your project
create buildSrc/build.gradle.kts file with the following content
plugins {
`kotlin-dsl`
}
repositories {
mavenCentral()
}
create file buildSrc/src/main/kotlin/Constants.kt with the following content
object Constants {
const val kotlinVersion = "1.3.70"
const val targetSdkVersion = 28
}
Synchronize. Now you may reference created constants in various .gradle.kts files like this
...
classpath(kotlin("gradle-plugin", version = Constants.kotlinVersion))
...
...
targetSdkVersion(Constants.targetSdkVersion)
...
What is working for me is using ext in allprojects instead of buildscript, so in your top-level build.gradle.kts
allprojects {
ext {
set("supportLibraryVersion", "26.0.1")
}
}
then you can use it in build.gradle.kts files in modules like this:
val supportLibraryVersion = ext.get("supportLibraryVersion") as String
None of these answers felt clear to me.
So here's my explanation:
/build.gradle.kts:
buildscript {
extra.apply {
set("compose_version", "1.0.3")
}
...
}
/app/build.gradle.kts:
val composeVersion = rootProject.extra["compose_version"]
implementation("androidx.compose.ui:ui:$composeVersion")
implementation("androidx.compose.material:material:$composeVersion")
There is a new possibility with Kotlin we can use:
object DependencyVersions {
const val JETTY_VERSION = "9.4.12.v20180830"
}
dependencies{
implementation("org.eclipse.jetty:jettyserver:${DependencyVersions.JETTY_VERSION}")
}
Here, DependencyVersions is a name I chose. You can choose another name,
like "MyProjectVariables". This is a way to avoid using the extra or ext properties.
Global properties in kotlin-gradle-dsl:
https://stackoverflow.com/a/53594357/3557894
Kotlin version is embedded into kotlin-gradle-dsl.
You can use dependecies with embedded version as follows:
implementation(embeddedKotlin("stdlib-jdk7"))
classpath(embeddedKotlin("gradle-plugin"))
val junitVersion by extra("4.13.2")
testImplementation("junit:junit:$junitVersion")
In Kotlin, the way to do this is with by extra or an ext block.
With by extra:
val kotlinVersion = "95" by extra
val kotlinCompiler = true by extra
With ext:
ext {
set("kotlinVersion", "95")
set("kotlinCompiler", true)
}
Set it like this:
val kotlinVersion by extra("1.1.4")
Use it like this:
val kotlinVersion: String by rootProject.extra
It's a possibility to define global properties within gradle.properties:
xyzVersion=1.0.0
And then use them in your module's build.gradle.kts:
val xyzVersion: String by project

Resources