diff --git a/_posts/2024-01-18-Oh-Nio.md b/_posts/2024-01-18-Oh-Nio.md new file mode 100644 index 0000000..a509820 --- /dev/null +++ b/_posts/2024-01-18-Oh-Nio.md @@ -0,0 +1,60 @@ +--- +layout: post +title: OH NIO! What is this system property? +header: header-eng +--- + +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](https://r.android.com/2915203) +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](https://medium.com/@mathjeff/preventing-log-creep-968b9d55720c) +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: +![Configuration cache report showing idea.io.use.nio2 being read by PomResolver class](/assets/2024-01-18-cache-report.png) + +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](https://github.com/spdx/spdx-gradle-plugin/blob/ce133bafb1faea5a85846a2784bac1a645360b55/src/main/java/org/spdx/sbom/gradle/maven/PomResolver.java#L203C5-L203C66) +from SPDX gradle plugin gets every system property through +`.putAll(System.getProperties())` call. + +![JVM Debugger stacktrace showing PomResolver reading nio2 property](/assets/2024-01-18-read-property.png){:width="600px"} + +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`](https://cs.android.com/android-studio/kotlin/+/master:compiler/cli/cli-common/src/org/jetbrains/kotlin/cli/common/environment/util.kt;l=20;drc=bffe94e48a4bf6dfe6d959ae840010745bbc7077) +and [`configureKotlinCompilerIoForWindowsSupport`](https://cs.android.com/android-studio/gradle/+/master:build-logic-commons/basics/src/main/kotlin/gradlebuild/basics/util/KotlinSourceParser.kt;l=97;drc=3bd08a5483b20d08d2853a532f5b34767d8ca0a4) +that seemed suspect. To confirm my hunch, I attached a debugger with a +breakpoint on `System.setProperty`: + +![JVM Debugger stacktrace showing setIdeaIoUseFallback setting nio2 property](/assets/2024-01-18-set-property.png){:width="600px"} + +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](https://github.com/spdx/spdx-gradle-plugin/issues/94) +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. diff --git a/assets/2024-01-18-cache-report.png b/assets/2024-01-18-cache-report.png new file mode 100644 index 0000000..70fb80c Binary files /dev/null and b/assets/2024-01-18-cache-report.png differ diff --git a/assets/2024-01-18-read-property.png b/assets/2024-01-18-read-property.png new file mode 100644 index 0000000..ab60786 Binary files /dev/null and b/assets/2024-01-18-read-property.png differ diff --git a/assets/2024-01-18-set-property.png b/assets/2024-01-18-set-property.png new file mode 100644 index 0000000..7a39fe9 Binary files /dev/null and b/assets/2024-01-18-set-property.png differ