Migrate your build configuration from Groovy to Kotlin

Android Gradle plugin 4.0 added support for using Kotlin in your Gradle build configuration as a replacement for Groovy, the programming language traditionally used in Gradle configuration files.

Kotlin is preferred over the Groovy for writing Gradle scripts because Kotlin is more readable and offers better compile-time checking and IDE support.

Although Kotlin currently offers better integration in Android Studio’s code editor when compared to Groovy, builds using Kotlin tend to be slower than builds using Groovy, so consider build performance when deciding whether to migrate.

This page provides basic information about converting your Android app's Gradle build files from Groovy to Kotlin. For a more comprehensive migration guide, see Gradle’s official documentation.

Timeline

Starting with Android Studio Giraffe, new projects use the Kotlin DSL (build.gradle.kts) by default for build configuration. This offers a better editing experience than the Groovy DSL (build.gradle) with syntax highlighting, code completion, and navigation to declarations. To learn more, see the Gradle Kotlin DSL Primer.

Common terms

Kotlin DSL: Refers primarily to the Android Gradle plugin Kotlin DSL or, occasionally, to the underlying Gradle Kotlin DSL.

In this migration guide, "Kotlin" and "Kotlin DSL" are used interchangeably. Likewise, "Groovy" and "Groovy DSL" are used interchangeably.

Script file naming

Script file extension names are based on the language the build file is written in:

  • Gradle build files written in Groovy use the .gradle file name extension.
  • Gradle build files written in Kotlin use the .gradle.kts file name extension.

Convert the syntax

There are some general differences in syntax between Groovy and Kotlin, so you need to apply these changes throughout your build scripts.

Add parentheses to method calls

Groovy lets you to omit parentheses in method calls, while Kotlin requires them. To migrate your configuration, add parentheses to these sorts of method calls. This code shows how to configure a setting in Groovy:

compileSdkVersion 30

This is the same code written in Kotlin:

compileSdkVersion(30)

Add = to assignment calls

The Groovy DSL lets you to omit the assignment operator = when assigning properties, whereas Kotlin requires it. This code shows how to assign properties in Groovy:

java {
    sourceCompatibility JavaVersion.VERSION_17
    targetCompatibility JavaVersion.VERSION_17
}

This code shows how to assign properties in Kotlin:

java {
    sourceCompatibility = JavaVersion.VERSION_17
    targetCompatibility = JavaVersion.VERSION_17
}

Convert strings

Here are the string differences between Groovy and Kotlin:

  • Double quotes for strings: While Groovy allows strings to be defined using single quotes, Kotlin requires double quotes.
  • String interpolation on dotted expressions: In Groovy, you can use just the $ prefix for string interpolations on dotted expressions, but Kotlin requires that you wrap the dotted expressions with curly braces. For example, in Groovy you can use $project.rootDir as shown in the following snippet:

        myRootDirectory = "$project.rootDir/tools/proguard-rules-debug.pro"
        

    In Kotlin, however, the preceding code calls toString() on project, not on project.rootDir. To get the value of the root directory, wrap the ${project.rootDir} expression with curly braces:

        myRootDirectory = "${project.rootDir}/tools/proguard-rules-debug.pro"
        

    To learn more, see String templates in the Kotlin documentation.

Rename file extensions

Append .kts to each build file as you migrate its contents. For example, select a build file, like the settings.gradle file. Rename the file to settings.gradle.kts and convert the file's contents to Kotlin. Make sure your project still compiles after the migration of each build file.

Migrate your smallest files first, gain experience, and then move on. You can have a mix of Kotlin and Groovy build files in a project, so take your time to carefully make the move.

Replace def with val or var

Replace def with val or var, which is how you define variables in Kotlin. This is a variable declaration in Groovy:

def building64Bit = false

This is the same code written in Kotlin:

val building64Bit = false

Prefix boolean properties with is

Groovy uses property deduction logic based on the property names. For a boolean property foo, its deduced methods can be getFoo, setFoo, or isFoo. Thus once converted to Kotlin, you need to change the property names to the deduced methods that are not supported by Kotlin. For example, for buildTypes DSL boolean elements, you need to prefix them with is. This code shows how to set boolean properties in Groovy:

android {
    buildTypes {
        release {
            minifyEnabled true
            shrinkResources true
            ...
        }
        debug {
            debuggable true
            ...
        }
    ...

The following is the same code in Kotlin. Note that the properties are prefixed by is.

android {
    buildTypes {
        getByName("release") {
            isMinifyEnabled = true
            isShrinkResources = true
            ...
        }
        getByName("debug") {
            isDebuggable = true
            ...
        }
    ...

Convert lists and maps

Lists and maps in Groovy and Kotlin are defined using different syntax. Groovy uses [], while Kotlin calls collection creation methods explicitly using listOf or mapOf. Make sure to replace [] with listOf or mapOf when migrating.

Here's how to define a list in Groovy versus Kotlin:

jvmOptions += ["-Xms4000m", "-Xmx4000m", "-XX:+HeapDumpOnOutOfMemoryError</code>"]

This is the same code written in Kotlin:

jvmOptions += listOf("-Xms4000m", "-Xmx4000m", "-XX:+HeapDumpOnOutOfMemoryError")

Here's how to define a map in Groovy versus Kotlin:

def myMap = [key1: 'value1', key2: 'value2']

This is the same code written in Kotlin:

val myMap = mapOf("key1" to "value1", "key2" to "value2")

Configure build types

In the Kotlin DSL only the debug and release build types are available implicitly. All other custom build types must be created manually.

In Groovy you can use the debug, release, and certain other build types without creating them first. The following code snippet shows a configuration with the debug, release, and benchmark build types in Groovy.

buildTypes {
 debug {
   ...
 }
 release {
   ...
 }
 benchmark {
   ...
 }
}

To create the equivalent configuration in Kotlin, you must explicitly create the benchmark build type.

buildTypes {
 debug {
   ...
 }

 release {
   ...
 }
 register("benchmark") {
    ...
 }
}

Migrate from buildscript to plugins block

If your build uses the buildscript {} block to add plugins to the project, you should refactor to use the plugins {} block instead. The plugins {} block makes it easier to apply plugins, and it works well with version catalogs.

In addition, when you use the plugins {} block in your build files, Android Studio is aware of the context even when the build fails. This context helps make fixes to your Kotlin DSL files because it allows the Studio IDE to perform code completion and provide other helpful suggestions.

Find the plugin IDs

While the buildscript {} block adds the plugins to the build classpath using the Maven coordinates of the plugin, for example com.android.tools.build:gradle:7.4.0, the plugins {} block uses the plugin IDs instead.

For most plugins, the plugin ID is the string used when you apply them using apply plugin. For example, the following plugin IDs are part of Android Gradle Plugin:

  • com.android.application
  • com.android.library
  • com.android.lint
  • com.android.test

You can find the full plugin list in the Google Maven repository.

Kotlin plugins can be referenced by multiple plugin IDs. We recommend using the namespaced plugin ID, and refactor from shorthand to namespaced plugin ID by the following table:

Shorthand plugin IDs Namespaced plugin IDs
kotlin org.jetbrains.kotlin.jvm
kotlin-android org.jetbrains.kotlin.android
kotlin-kapt org.jetbrains.kotlin.kapt
kotlin-parcelize org.jetbrains.kotlin.plugin.parcelize

You can also search for plugins on the Gradle Plugin Portal, the Maven Central Repository and the Google Maven repository. Read Developing Custom Gradle Plugins to learn more about how plugin IDs work.

Perform the refactoring

Once you know the IDs of the plugins you use, perform the following steps:

  1. If you still have repositories for plugins declared in the buildscript {} block, move them to the settings.gradle file instead.

  2. Add the plugins to the plugins {} block in the top-level build.gradle file. You need to specify the ID and the version of the plugin here. If the plugin doesn't need to be applied to the root project, use apply false.

  3. Remove the classpath entries from the top-level build.gradle.kts file.

  4. Apply the plugins by adding them to the plugins {} block in the module-level build.gradle file. You only need to specify the plugin's ID here because the version is inherited from the root project.

  5. Remove the apply plugin call for the plugin from the module-level build.gradle file.

For example, this setup uses the buildscript {} block:

// Top-level build.gradle file
buildscript {
    repositories {
        google()
        mavenCentral()
        gradlePluginPortal()
    }
    dependencies {
        classpath("com.android.tools.build:gradle:7.4.0")
        classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:1.8.0")
        ...
    }
}

// Module-level build.gradle file
apply(plugin: "com.android.application")
apply(plugin: "kotlin-android")

This is an equivalent setup using the plugins {} block:

// Top-level build.gradle file
plugins {
   id 'com.android.application' version '7.4.0' apply false
   id 'org.jetbrains.kotlin.android' version '1.8.0' apply false
   ...
}

// Module-level build.gradle file
plugins {
   id 'com.android.application'
   id 'org.jetbrains.kotlin.android'
   ...
}

// settings.gradle
pluginManagement {
    repositories {
        google()
        mavenCentral()
        gradlePluginPortal()
    }
}

Convert the plugins block

Applying plugins from the plugins {} block is similar in Groovy and Kotlin. The following code shows how to apply plugins in Groovy when you're using version catalogs:

// Top-level build.gradle file
plugins {
   alias libs.plugins.android.application apply false
   ...
}

// Module-level build.gradle file
plugins {
   alias libs.plugins.android.application
   ...
}

The following code shows how to do the same in Kotlin:

// Top-level build.gradle.kts file
plugins {
   alias(libs.plugins.android.application) apply false
   ...
}

// Module-level build.gradle.kts file
plugins {
   alias(libs.plugins.android.application)
   ...
}

The following code shows how to apply plugins in Groovy when you're not using version catalogs:

// Top-level build.gradle file
plugins {
   id 'com.android.application' version '7.3.0' apply false
   ...
}

// Module-level build.gradle file
plugins {
   id 'com.android.application'
   ...
}

The following code shows how to do the same in Kotlin:

// Top-level build.gradle.kts file
plugins {
   id("com.android.application") version "7.3.0" apply false
   ...
}

// Module-level build.gradle.kts file
plugins {
   id("com.android.application")
   ...
}

For more details about the plugins {} block, see Applying plugins in the Gradle documentation.

Miscellaneous

For Kotlin code samples for other functionalities, see the following documentation pages:

Known issues

At present, a known issue is that build speed might be slower with Kotlin than with Groovy.

How to report issues

For instructions on how to provide the info we need to triage your issue, see Details for build tools and Gradle bugs. Then, file a bug using the Google public issue tracker.

More resources

For a working example of Gradle build files written with Kotlin, see the Now In Android sample app on GitHub.