Using Gradle build cache with Kotlin
Table of Contents
Introduction
A build cache allows Gradle to reuse task output from any previous invocation, including those from other machines. Kotlin 1.2.21 allows Kotlin projects to make use of build caching.
The build cache works by storing compiled classes, test outputs, and other build artifacts in a cache, taking into account all task inputs, including input file contents, relevant classpaths, and task configuration.
This frequently results in faster builds. The following chart shows aggregated build time with and without the build cache for part of Gradle’s CI:
In this post, we’ll explain how you can use Gradle’s build cache to avoid unnecessary Kotlin compilation to speed up your builds.
Quick demo with Spek #
You can try out build caching with Gradle right now. Just follow these steps:
Clone Spek #
git clone https://github.com/spekframework/spek.git
cd spek
The Spek 2.x
branch (which is the default) already has all prerequisites for build caching that we’ll describe later.
Build and populate cache #
The following command builds Spek and populates the local build cache.
❯ ./gradlew assemble --build-cache
BUILD SUCCESSFUL in 10s
21 actionable tasks: 21 executed
Using the --build-cache
flag is one way to tell Gradle to store outputs in a separate task output cache.
Remove/change build outputs #
This simulates being on another machine or perhaps making a change and stash
ing it. The quickest way to demonstrate is use the clean
task.
❯ ./gradlew clean
Re-build and resolve from build cache #
This time when we re-build, all Kotlin compiled sources are pulled from the build cache.
❯ ./gradlew assemble --build-cache
BUILD SUCCESSFUL in 2s
21 actionable tasks: 11 executed, 10 from cache
Voilà! You just used Gradle’s build cache to reuse Kotlin compiled classes instead of recompiling again! The build was about 5x faster!
You can see from this build scan that Kotlin compile tasks were pulled from the build cache; :jar
and :processResources
tasks were not because it’s faster to generate JARs and copy files locally than pull from a cache. Note that caching :test
tasks is also supported.
The Gradle build cache is particularly effective when a CI instance populates a shared build cache, which developers can pull from. Links to more resources for achieving this are listed below.
Enabling the build cache for your projects #
I hope you’re excited to try this out on your project — you can follow these steps to enable the build cache.
First, you need to ensure you’re using Gradle 4.3 or above, so the Kotlin Gradle Plugin can opt-in to using new APIs in Gradle. You can upgrade Gradle easily using the Gradle wrapper.
Next, we need to ensure we are compiling with Kotlin version 1.2.20 or above. You might have something like this declared in your buildscript {}
block in build.gradle
:
dependencies {
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:1.2.21"
}
Next, we need to tell Gradle to use the build cache. There are 3 ways to do this:
- Enable for the current build using
--build-cache
on the command-line. - Enable for the project by adding
org.gradle.caching=true
to$PROJECT_ROOT/gradle.properties
. - Enable for all builds for the current user by adding
org.gradle.caching=true
to$GRADLE_HOME/gradle.properties
.
NOTE: Android developers still need to do this even if android.enableBuildCache=true
is set, because Gradle’s build cache is separate from the Android build cache.
We can optionally take advantage of the build cache from IDEs by delegating run and test actions to Gradle.
Enabling build caching in IntelliJ #
If you use IntelliJ to execute Gradle actions, you will need to “Delegate IDE build/run actions to Gradle” in your IDE settings to take advantage of build caching when building and running tests from IntelliJ.
NOTE: Android Studio does this by default.
Caching kapt tasks #
Caching for kapt
is currently disabled by default, even with --build-cache
, because Gradle does not yet have a way to map inputs and outputs for annotation processors. You can explicitly enable use of the build cache for Kotlin annotation processing tasks by setting useBuildCache
to true
in kapt
configuration.
kapt {
useBuildCache = true
}
Further reading #
You can learn more about leveraging the Gradle build cache through these resources:
- Configuring the build cache
- Setting up a shared, remote build cache ⚡️
- Debugging build cache misses
- Developing cacheable custom tasks
Conclusion #
Compiling Kotlin code using kotlin-gradle-plugin
version 1.2.20 and above can take advantage of Gradle’s --build-cache
feature to speed up your development cycle. Work continues to expand the set of tasks that support build caching.
Onward!