Gradle Kotlin DSL Tutorial

In this tutorial you will use Gradle Kotlin DSL (GKD) in a new Kotlin project to script Gradle builds. Gradle Inc first announced GKD in May 17 2016. Since then some organisations like JetBrains have started to use GKD in production which makes it a great time to start using it, even in non production level projects.

The following software will be used in this tutorial:

  • Kotlin 1.2.10
  • JDK 8
  • Gradle 4.4.1
  • Intellij >= 2017.3.1

Getting Started

First off a calculator project will be created which will also have unit tests that will be covered later on in the tutorial. Open Intellij and create a new project. In the New Project wizard do the following:

  1. Select Gradle option in the list
  2. Uncheck everything under Additional Libraries and Frameworks
  3. Click Next button
  4. Enter in org.example for GroupId
  5. Enter in calculator for ArtifactId
  6. Click Next button
  7. Check Use auto-import
  8. Set Gradle JVM to the JDK 8 version that is installed
  9. Click Next button
  10. Click Finish button

After the project is created Gradle will need to be updated to 4.4.1 in order to ensure that a recent version of GKD is used. Update Gradle by running the following in a terminal: ./gradlew wrapper — gradle-version 4.4.1. Check that the right version of Gradle is used by running the following in a terminal: ./gradlew -v.

Settings File

Some Gradle projects using GKD can use a settings file (settings.gradle.kts) to store project level settings. This file is optional but it is considered good practise to include one in a project. For this tutorial create the file with the following:

rootProject.name = “calculator”

After creating the file remove the conflicting settings.gradle file.

Build Script

Every Gradle project that uses GKD must include a build file called build.gradle.kts in the root directory of the project, and Gradle wrapper version 4.1.1. Some Kotlinic (idiomatic Kotlin — aka “The Kotlin way”) examples are shown in the tutorial. Before proceeding remove the old build file (build.gradle) and create the new build file (build.gradle.kts) which will be used in the following sub sections.

Project Information

All key information about the project must be specified at the top of the build file. Only group and version properties (can’t be included in the settings file) need to be set. Append the following:

group = “org.example”
version = “0.1-SNAPSHOT”

Project Meta Data

Very useful to specify extra project meta data (in the extra Map) that will be be used in the entire build script in multiple places, especially when defining versions used in project dependencies. Any specified meta data must be defined in a buildscript block. Append the following:

buildscript {
@Suppress(“ASSIGNED_BUT_NEVER_ACCESSED_VARIABLE”)
var kotlinVer: String by extra
@Suppress(“ASSIGNED_BUT_NEVER_ACCESSED_VARIABLE”)
var kotlinTestVer: String by extra

@Suppress(“UNUSED_VALUE”)
kotlinVer = “1.2.10”
@Suppress(“UNUSED_VALUE”)
kotlinTestVer = “2.0.7”
}
val kotlinVer: String by extra
val kotlinTestVer: String by extra

Adding Repositories

Repositories need to be added before getting any needed Gradle plugins and library dependencies. Append the following:

repositories {
jcenter()
}

Using Gradle Plugins

In order to use a Gradle plugin a plugins block needs to be defined after the buildscript block. Append the following:

plugins {
kotlin(“jvm”) version “1.2.10”
application
}

Configuring A Gradle Plugin

Once a Gradle plugin is applied it is configured after the plugins block. Here is an example of the application plugin being configured. Append the following:

application {
mainClassName = “org.example.calculator.CalculatorKt”
}

Note that some plugins need to be imported first before they can be configured.

Adding Dependencies

Project dependencies are added in the dependencies block. Append the following:

dependencies {
compile(kotlin(module = “stdlib-jre8”, version = kotlinVer))
testCompile(“io.kotlintest:kotlintest:$kotlinTestVer”)
}

A standard project dependency (library) is included using the compile function, and a test dependency (test library) is included using the testCompile function. Both functions take a Dependency Notation which is a String that is comprised of the following parts:

groupId:artifactId:version

Gradle Tasks

Gradle can run tasks which can be thought of as build actions (eg compileKotlin — Compile Kotlin source files). Usually when you run Gradle a task is specified that is to be executed when running a build. It is good practice when customising/creating multiple Gradle tasks to do it within the tasks block, which is positioned after the dependencies block.

Often you will find it useful to customise some Gradle tasks (ones supplied by Gradle and/or a third party Gradle plugin). In order to customise a task it needs to be fetched first (via a lookup). Append the following:

val compileKotlin by tasks.getting(KotlinCompile::class) {
// Customise the “compileKotlin” task.
kotlinOptions.jvmTarget = “1.8”
doLast { println(“Finished compiling Kotlin source code”) }
}
val compileTestKotlin by tasks.getting(KotlinCompile::class) {
// Customise the “compileTestKotlin” task.
kotlinOptions.jvmTarget = “1.8”
doLast { println(“Finished compiling Kotlin source code for testing”) }
}

Remember to include the following import in the build file:

import org.jetbrains.kotlin.gradle.tasks.KotlinCompile

Initial Project Setup

After setting up the build and settings files the project can now be setup before running a Gradle build. All Kotlin source files in a Gradle project by convention must go in the src/main/kotlin directory; create this directory. In the new directory create a new package called org.example.calculator. Create a new Kotlin source file in the new package called calculator.kt, and include the following:

package org.example.calculator
fun main(args: Array<String>) = println(“Calculator logic goes in this file.”)

Run the program in Gradle via the terminal by running the following: ./gradlew run. If Kotlin Home error appears (e: Kotlin home does not exist or is not a directory:) then stop the Gradle daemon by running the following in a terminal: ./gradlew — stop, and run the program again. Congratulations, you have successfully done your first Gradle build using GKD.

Project Testing

After doing a Gradle build it is time to cover basic software testing with Gradle. In the calculator.kt file append the following:

fun add(num1: Double, num2: Double): Double {
return 0.0
}
fun subtract(num1: Double, num2: Double): Double {
return 0.0
}
fun multiply(num1: Double, num2: Double): Double {
return 0.0
}
fun divide(num1: Double, num2: Double): Double {
return 0.0
}

Just like with Kotlin source files Gradle has a standard convention for Kotlin source files used for software testing which must be placed in the src/test/kotlin directory; create this directory. In the new directory create a new package called org.example.calculator. Create a new Kotlin source file called CalculatorTest.kt in the new package, and include the following:

package org.example.calculator
import io.kotlintest.matchers.exactly
import io.kotlintest.matchers.shouldBe
import io.kotlintest.specs.FunSpec
class CalculatorTest : FunSpec() {
init {
testAdd()
testSubtract()
testDivide()
testMultiply()
}
fun testAdd() = test(“add returns the correct result”) {
val expected = 6.0
add(2.0, 4.0) shouldBe exactly(expected)
}
fun testSubtract() = test(“subtract returns the correct result”) {
val expected = 2.0
subtract(4.0, 2.0) shouldBe exactly(expected)
}
fun testDivide() = test(“divide returns the correct result”) {
val expected = 5.0
subtract(10.0, 2.0) shouldBe exactly(expected)
}
fun testMultiply() = test(“multiply returns the correct result”) {
val expected = 27.9
subtract(6.2, 4.5) shouldBe exactly(expected)
}
}

Test the program in Gradle via the terminal by running the following: ./gradlew test. After running the command all tests should fail as expected. In the calculator.kt file replace the add, subtract, multiply, and divide functions with the following:

fun add(num1: Double, num2: Double): Double {
return num1 + num2
}
fun subtract(num1: Double, num2: Double): Double {
return num1 — num2
}
fun multiply(num1: Double, num2: Double): Double {
return “%.2f”.format(num1 * num2).toDouble()
}
fun divide(num1: Double, num2: Double): Double {
return “%.2f”.format(num1 / num2).toDouble()
}

Run the program and all tests should pass.

Conclusion

After going through this tutorial you will now have a basic understanding of using GKD to do Gradle builds. GKD will have a stable release in Q1 2018. There is no word on when Google will support GKD.