Migrating to Kotlin DSL & Version Catalog

João Ferreira
João Ferreira
Nov 10 2023
Posted in Engineering & Technology

A step-by-step guide for a stress-free migration

Migrating to Kotlin DSL & Version Catalog

With the release of Android Studio Giraffe, Kotlin DSL became the default Gradle build scripts in Android development, as it offers more readable code, compile-time checking and IDE support.

Migrating from your old Groovy DSL projects may seem daunting, but in this step-by-step guide we'll go through everything that needs to be changed, ensuring a stress-free migration.

We'll also take a look at Version Catalog, a powerful way to keep all your dependencies organized.

Migrating to Kotlin DSL

Identify Files to Convert

Whether your project is the classic single-module, or a multi-module one, identifying our groovy-based Gradle files, that we want to convert, is the first step.

Typically, every project has a settings.gradle, the project level build.gradle, and module level build.gradle files. Additional gradle files also need converting.

Convert the Syntax

One of the main differences from Groovy to Kotlin is the syntax. Before changing the script file name, apply these changes throughout your build files:

  • Use double quotes for strings
    While Groovy lets you use single quotes to define strings, Kotlin requires double quotes.
    The following example in Groovy:

    implementation 're.notifica:notificare:3.6.1'

    should be changed to:

    implementation "re.notifica:notificare:3.6.1"

    💡 Pro Tip: Finding all usages of ' and replacing them for " makes this job much easier!

  • Add parenthesis to method calls
    While Groovy lets you omit parenthesis, Kotlin methods require them.
    So, back to the previous example, from Groovy:

    implementation "re.notifica:notificare:3.6.1"

    to Kotlin:

    implementation("re.notifica:notificare:3.6.1")
  • Add = to assignment calls
    While Groovy lets you omit the assigment operator, Kotlin requires them.
    Take the following example from Groovy:

    applicationId "re.notifica.go"

    In Kotlin:

    applicationId = "re.notifica.go"
  • Define variables the Kotlin way
    Replace the Groovy variable keyword def with the Kotlin keywords val or var. From Groovy:

    def notificare_version = "3.6.1"

    To Kotlin:

    val notificare_version = "3.6.1"
  • Prefix Booleans
    Groovy deducts methods based on the property names. In Kotlin, however, we need to change the property names to the non-supported deduced methods. In the buildTypes DSL, for example:

    android {
        buildTypes {
            release {
                minifyEnabled true
                ...
            }
            ...

    Boolean properties should be prefixed with is

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

We recommend you start with your simplest files first, and, after some practice, go through the more complex ones.

Rename Script Files

By now, all general changes were made, so you can start renaming you .gradle file extensions to .gradle.kts. However, you may notice that changes specific to each file still need to be made.

Clean Task on the Project Level Build File

Every project level build file has a clean task. You might notice that after changing the file extension to .gradle.kts, Android Studio marks the old usage as an error. Kotlin does things differently. From the old Groovy syntax:

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

To the new Kotlin one:

tasks.register("clean",Delete::class){
    delete(rootProject.buildDir)
}

You should also take this opportunity to resolve the deprecated getter for the build directory. Instead of:

rootProject.buildDir

do:

rootProject.layout.buildDirectory

Configure Build Types

You might have noticed in a previous example, that made use of the buildTypes DSL, that things were a little different.

In Kotlin, build types must be one of the default, such as release and debug, accessed by the getByName(buildType) method, or a new one created using the create(buildType) method.

As such, what would be the norm in Groovy:

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

Is now, in Kotlin:

buildTypes {
    getByName("debug") {
        ...
    }
    getByName("release") {
        ...
    }
    create("benchmark") {
        ...
    }
}

If you're wondering how this changes the signinConfigs block, fear not. The conversion is the same. However, only the debug configuration comes by default, meaning you have to create the remaining ones.

Additional Conversions

Every project is different. Therefore, different functionalities may be present in yours. If any of those functionalities are not covered in this guide, we recommend taking a look at both migration guides from Google and Gradle.

Version Catalog

Another new Gradle functionality that greatly improves maintainability of your project dependencies and plugins is the Version Catalog. Especially in multi-module projects, declaring or upgrading a dependency can be a hassle, looking for all hardcoded usages and maintaining consistent versioning throughout every individual build file.

To make this process easier, you can create a central Version Catalog that all your build files can reference.

Creating a Version Catalog File

In your project's gradle folder, start by creating a file called libs.versions.toml.

Here, we define 3 categories, as such:

[versions]

[libraries]

[plugins]

Migrate Your Dependencies

With your file set up, you can start migrating your old dependency declarations into your central catalog.

A dependency on your build.gradle.kts file:

dependencies {
    implementation("re.notifica:notificare:3.6.1")
}

Can be cataloged as such:

[versions]
notificare = "3.6.1"

[libraries]
notificare = { module = "re.notifica:notificare", version.ref = "notificare" }

and declared in your build.gradle.kts:

dependencies {
    implementation(libs.notificare)
}

Additionally, you can declare groups of dependencies often used together as a bundle, minimizing declarations on your build.gradle.kts file, as such:

[bundles]
notificare-geo = ["notificare-geo", "notificare-geo-gms", "notificare-geo-beacons"]
dependencies {
    implementation(libs.bundles.notificare.geo)
}

Migrate Your Plugins

Migrating your plugin declarations is relatively similar to migrating your dependencies, with a few caveats.

The declaration should be done in the plugins category of your version catalog and use the alias keyword in your build file, like so:

[versions]
kotlin = "1.9.1"

[plugins]
kotlin-android = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" }
plugins {
    alias(libs.plugins.kotlin.android)
}

That's it. You now have a central catalog for all your dependencies. The next time you have to update your dependencies, changing a single file sure makes the job easier!

Conclusion

In this blog post, we guided you through the migration process to Kotlin DSL and to a centralized Version Catalog. With Kotlin DSL, you can expect a better editing experience, and with a central version catalog, maintain coherent versioning throughout your project. Adopting these build technologies promotes the readability and scalability of your project build files, ensuring easy and stress-free maintenance.

As always, we hope you liked this article, and if you have anything to add, we are available via our Support Channel.

Keep up-to-date with the latest news