Build Gradle with Kotlin DSL

A migration guide from groovy to KOTLIN DSL

TheBotBox
TheBotBox
May 1 · 5 min read

Enough has been said about Kotlin DSL and how it empower developers to use familiar syntax of Kotlin instead of Groovy in Gradle scripts, its proper IDE support for auto-completion, jump to source code etc. But without digging deep into its pros and cons, we will try to migrate from Groovy to Kotlin DSL while keeping it as simple as possible.

Image for post
Image for post

This article is only a implementation guide & expects to have a bit of prior knowledge on the topic.

Using Kotlin to build your Gradle files in Android for the first time can be a pain in hand😉(at least it was for me) due to lack of proper documentation. Hence, I decided to break it down into simple steps.

STEP 1: Gradle Version

Try keeping gradle wrapper version to as latest as possible because it will include the latest Kotlin DSL version. I am using 5.6.4 .

distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-5.6.4-all.zip

STEP 2: settings.gradle.kts

Rename your root settings.gradle to settings.gradle.kts . Now open the same file and start making the below changes from

rootProject.name='ChatBot'
include ':app', ':NetworkEngine', 'BotManager'

to

rootProject.name=("ChatBot")
include(":app", ":NetworkEngine", ":BotManager")

and sync the project now.

STEP 3: root build.gradle

Again rename your root build.gradle to build.gradle.kts . Now again open the same file and start making the below changes from

buildscript {
repositories {
google()
jcenter()

}
dependencies {
classpath 'com.android.tools.build:gradle:3.6.3'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:1.3.61"

// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
}
}

allprojects {
repositories {
google()
jcenter()
maven{ url 'https://jitpack.io' }
}
}

task clean(type: Delete) {
delete rootProject.buildDir
}

to

buildscript {
repositories {
google()
jcenter()

}
dependencies {
classpath("com.android.tools.build:gradle:3.6.3")
classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:1.3.70")


// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
}
}

allprojects {
repositories {
google()
jcenter()
maven { url = uri("https://jitpack.io") }
}
}

tasks {
val clean by registering(Delete::class) {
delete(buildDir)
}
}

sync again.

STEP 4: module build.gradle

Again rename your module’s build.gradle to build.gradle.kts . Now again open the same file and start making the below changes from

a.) plugin block before:

apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions'
apply plugin: 'kotlin-kapt'

plugin block after:

plugins {
id("com.android.application")
kotlin("android")
kotlin("android.extensions")
kotlin("kapt")
}

b.) android block before:

android {
compileSdkVersion 29
buildToolsVersion "29.0.3"

defaultConfig {
applicationId "bot.box.ChatBot"
minSdkVersion 21
targetSdkVersion 29
versionCode 1
versionName "1.0"

testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}

buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}

}

android block after:

android {
compileSdkVersion(29)
buildToolsVersion("29.0.3")

defaultConfig {
applicationId = "bot.box.ChatBot"
minSdkVersion(21)
targetSdkVersion(29)
versionCode = 1
versionName = "1.0"

testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
}

buildTypes {
getByName("release") {
isMinifyEnabled = false
proguardFiles(getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro")
}
}

}

c.) dependencies block before:

dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.3.61"
implementation 'androidx.appcompat:appcompat:1.1.0'
implementation 'androidx.core:core-ktx:1.2.0'
implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
testImplementation 'junit:junit:4.12'
androidTestImplementation 'androidx.test.ext:junit:1.1.1'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'
}

dependencies block after:

dependencies {
implementation(fileTree(mapOf("dir" to "libs", "include" to listOf("*.jar"))))
implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.3.61")
implementation("androidx.appcompat:appcompat:1.1.0")
implementation("androidx.core:core-ktx:1.2.0")
implementation("androidx.constraintlayout:constraintlayout:1.1.3")
testImplementation("junit:junit:4.12")
androidTestImplementation("androidx.test.ext:junit:1.1.1'")
androidTestImplementation("androidx.test.espresso:espresso-core:3.2.0")
}

sync again.

Step 5: buildSrcdirectory

Now create buildSrc folder in the root directory of your workspace.

  1. Inside buildSrc folder, create a new build.gradle.kts file.
  2. Create another file in same directory with name Config.kt (could be of any name followed by .kt) inside /src/main/kotlin/Config.kt as shown below
Image for post
Image for post
buildSrc directory structure

STEP 6: buildSrc/build.gradle.kts

Open build.gradle.kts file from buildSrc directory that we have created recently and paste the following

repositories {
jcenter()
}

plugins {
`kotlin-dsl`
}

STEP 7: buildSrc/src/main/kotlin/Config.kts

Now we will have to open and configure our Config.kts file with respect to all the versions and dependencies that we are using on our whole application.

const val kotlinVersion = "1.3.70"

object BuildConfig {
object Versions {
const val buildToolsVersion = "3.6.3"
}

const val androidToolBuild = "com.android.tools.build:gradle:${Versions.buildToolsVersion}"
const val kotlinGradlePlugin = "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlinVersion"
}

object AndroidConfig {
const val compileSdkVersion = 29
const val buildToolsVersion = "29.0.3"

const val applicationId = "bot.box.ChatBot"
const val minSdkVersion = 21
const val targetSdkVersion = 29
const val versionCode = 1
const val versionName = "1.0"
}

object Dependencies {
private object Versions {
const val appCompat = "1.1.0"
const val coreKtx = "1.2.0"
const val constraint = "1.1.3"
}

const val kotlinStdLib = "org.jetbrains.kotlin:kotlin-stdlib-jdk7:${kotlinVersion}"
const val appCompatLib = "androidx.appcompat:appcompat:${Dependencies.Versions.appCompat}"
const val coreKtxLib = "androidx.core:core-ktx:${Dependencies.Versions.coreKtx}"
const val constraintLib =
"androidx.constraintlayout:constraintlayout:${Dependencies.Versions.constraint}"

}

object TestDependencies {
private object Versions {
const val jUnit = "4.12"
const val jUnitExt = "1.1.1"
const val espresso = "3.2.0"
}

const val jUnitTestLib = "junit:junit:${TestDependencies.Versions.jUnit}"
const val jUnitExtLib = "androidx.test.ext:junit:${TestDependencies.Versions.jUnitExt}"
const val espressoLib =
"androidx.test.espresso:espresso-core:${TestDependencies.Versions.espresso}"
}

STEP 8: root build.gradle.kts

For the final time open root build.gradle.kts file and simply call the required androidToolBuild and kotlinGradlePlugin variables by replacing the previous hard coded classpath

Before:

buildscript {

repositories {
google()
jcenter()

}
dependencies {
classpath("com.android.tools.build:gradle:3.6.2")
classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:1.3.61")

// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
}
}

After:

buildscript {

repositories {
google()
jcenter()

}
dependencies {
classpath(BuildConfig.androidToolBuild)
classpath(BuildConfig.kotlinGradlePlugin)


// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
}
}

Final Step 9: module build.gradle.kts

For the last time now, open module build.gradle.kts file & simply start typing the respective variables from Config.kt

final build.gradle.kts will now look like below

plugins {
id("com.android.application")
kotlin("android")
kotlin("android.extensions")
kotlin("kapt")
}

android {
compileSdkVersion(AndroidConfig.compileSdkVersion)
buildToolsVersion(AndroidConfig.buildToolsVersion)

defaultConfig {
applicationId = AndroidConfig.applicationId
minSdkVersion(AndroidConfig.minSdkVersion)
targetSdkVersion(AndroidConfig.targetSdkVersion)
versionCode = AndroidConfig.versionCode
versionName = AndroidConfig.versionName

testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
}

buildTypes {
getByName("release") {
isMinifyEnabled = false
proguardFiles(getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro")
}
}

}

dependencies {
implementation(fileTree(mapOf("dir" to "libs", "include" to listOf("*.jar"))))
implementation(Dependencies.kotlinStdLib)
implementation(Dependencies.appCompatLib)
implementation(Dependencies.coreKtxLib)
implementation(Dependencies.constraintLib)
testImplementation(TestDependencies.jUnitTestLib)
androidTestImplementation(TestDependencies.jUnitExtLib)
androidTestImplementation(TestDependencies.espressoLib)
}

and that is all. Thanks for reading. 😃

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch

Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore

Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store