AndroidX wanted to take a dip into a beautiful world of build.gradle.kts
after
years of using good-ole-speedy-Groovy build.gradle
. The smallest step towards
that was converting a single build.gradle
file
and see how that affects our builds, especially the time before the task
execution phase. It all looked good locally.
Enter our CI failing with:
The new output:
Calculating task graph as configuration cache cannot be reused because system property 'idea.io.use.nio2' has changed.
Our log creep detection system
spotted a brand-new warning indicating that the task up-to-date validation run
(androidx runs our build twice to make sure that tasks do nothing the second
time they run). This warning means that we did not have a configuration cache
hit the second time Gradle is invoked, and the reason was that there was a
change to idea.io.use.nio2
system property. This is bad as it means we
unexpectedly rerun the configuration phase in the second invocation making
overall build CI slower, but also slowing down AndroidX devs locally in the
same way too.
There are two questions that arise: 1. why is AndroidX build reading this system property at configuration time? 2. why is the value of the system property changing?
For where it is being read, Gradle gives you a breadcrumb in configuration cache report:
Sadly, this does not give you a stacktrace, so you have to use a debugger
with a breakpoint on ConfigurationCacheFingerprintWriter#systemPropertyRead
in Gradle to find that PomResolver#resolveEffectivePom
from SPDX gradle plugin gets every system property through
.putAll(System.getProperties())
call.
The second part, on what sets it and why it only happens in the first build
Gradle does not really help you. I quickly did a search through Gradle,
Android Gradle Plugin, and Kotlin codebases and spotted setIdeaIoUseFallback
and configureKotlinCompilerIoForWindowsSupport
that seemed suspect. To confirm my hunch, I attached a debugger with a
breakpoint on System.setProperty
:
Gradle only sets this value when it detects usage of build.gradle.kts
and it
is compiling these scripts. On the second run, the scripts are already compiled,
so it never calls this code.
To get out of this situation, we have created an issue for SPDX gradle plugin to remove reading of all properties at configuration time. Ideally, Gradle also would not go toggling properties, as this specific one is a workaround for Windows but is run on other OSes as well.