by Adam Arold
My first impressions of Gradle Kotlin DSL
The Kotlin DSL for writing Gradle build scripts has been around for some time. In this article, we’ll take a look at it and see how useful it is.
The first question you might ask when someone adds a new supported language to their tool is why they introduced it in the first place. I think this is a perfectly valid question in this case as well, so let’s take a look at some of the pain points with Groovy.
If you are a Java developer and you have worked with Maven before, it is probable that Gradle will be a little weird. The first problem is that we don’t just write some
xml, but we write actual code. This in itself can be a huge burden for someone who is used to the declarative configuration Maven gives us.
On top of this, the default language to use with Gradle is Groovy, which is a dynamic language. So Gradle not only takes away the declarative nature of xml, but the static nature as well.
The IDE support for editing Groovy files is also a bit lacking, so we don’t get features like refactoring. This is especially bad when we mistype a name somewhere and it is not visible in the IDE.
Groovy never took off, so finding developers who know the language is very hard. Therefore, most of us need to learn at least a bit of Groovy along the way, which leads to a lot of half-versed developers who tend to fumble when some language issue arises.
Enter kotlin-dsl, which adds Kotlin support for Gradle. The rationale behind this project is that we already have superb IDE support for Kotlin, so let’s just use it instead of Groovy. Then we’ll get auto-completion, refactoring, and a statically-typed language which is suited for building DSLs. Let’s take a look at how it works.
A quick glance
If you check the samples in the kotlin-dsl repository, you’ll see some very good, but rather simplistic examples:
Looks familiar? On the surface, kotlin-dsl is rather similar to the old Groovy config, but there are some minor differences. Let’s take a look at some of them.
Applying built-in plugins
Anything which is in the official Gradle plugin repository can be applied with the
The same with kotlin-dsl looks like this:
Wait, what happens here? Where does
application come from? If we take a look at the source, it becomes clear:
This clever trick lets us configure built-in plugins in a very simple way, and it is also compile-checked. Mistyped strings won’t be a problem anymore.
What if I want to use a non-built-in plugin? Well, there is still the old way:
and in Kotlin:
Declaring dependencies is a very important part of a Gradle script, so let’s take a look at the differences:
and with Kotlin:
Again, very similar, but a little more readable.
After plugins and dependencies, tasks might be the next in the list of important things in a Gradle config file. This is simple enough in Groovy:
but with Kotlin there is a little more magic involved:
What happens here is that kotlin-dsl provides some delegates for us:
If you are interested in more examples, check here.
So it seems that kotlin-dsl is the next big thing, right? We can finally refactor the configuration, we have code completion, everything works, so we can ditch Groovy. Well, not quite.
While the samples in the kotlin-dsl project are very good and most of the articles on the internet praise kotlin-dsl, there are some very real downsides to it in practice.
Issues with kotlin-dsl
Slow IDE support
The first one I bumped into when I started using kotlin-dsl is the relative slow speed with which the IDE picks up the configuration changes. I added a
buildSrc to my multiplatform project along with some
objects to hold the versions and the library dependencies. For some reason it took IDEA 3 minutes to recognize the changes. I tried it on 3 different computers on 2 different platforms, but I had the same experience on all of them.
Plugin configurations are equally slow. If we add a plugin using the
plugins block, the plugin configuration is available in the local scope so we can configure it like in Groovy:
In practice, the IDE support is a bit wonky. Sometimes it needs to be restarted in order for the configuration options to be visible, but it always takes minutes.
Lack of code examples
Gradle has a ton of Groovy samples which we can just copy-paste and customize to get things done. With kotlin-dsl, there are not a lot of them around, and this is worse with custom plugins. Most projects have Groovy-only examples of how to use them.
I checked dozens of project pages and I am yet to find a single one which has kotlin-dsl examples. This leads to the next problem:
Custom task type problems
Sometimes when you try to use a plugin which has custom tasks, you need to take a look at the source code of the plugin to figure out the actual types it uses. For example, to convert this Groovy snippet to Kotlin:
we need to specify the class of the task:
and this means digging into the source code of it.
This might not look like a big problem, but it takes time and adds up quickly.
Is it worth it?
We’ve seen that kotlin-dsl brings some powerful tools to the table, but they are not inherently Kotlin advantages. For example, we could have refactor support for Groovy as well, but it is just not there.
On the flip side, there are some big disadvantages, which in practice will lead to a lot of head scratching when trying to configure custom plugins.
Overall kotlin-dsl is a very useful tool, but it is just not mature enough. I would not recommend using it until it gets adopted by more people. Most of its downsides come from this, and there is no reason to think that it won’t get better in time. We are just not there yet.
Of course if you are a pioneer type, or just hate Groovy, then by all means go forth and use kotlin-dsl with impunity!
Thanks for reading! You can read more of my articles on my blog.