I spent a bit of time understanding why the CI of #2386 was failing on the Android steps, and Claude helped me figure out that, basically, we can't really use Java 17's record unless the minSDK is set to 35. It currently is set to 26.
Here's some detail from Claude's analysis:
The chain of cause:
- java.lang.Record is a Java 16 feature; on Android it's only available natively from API 35 (Android 15).
- it-android has minSdk = 26, so D8 must desugar the records — replacing the java.lang.Record superclass with a synthetic stand-in.
- That synthetic class is a "global synthetic" (shared across the dex output), and D8 needs a "global-synthetics consumer" wired up to receive it.
- The transform AGP picks here is DexingNoClasspathTransform — note the attribute string in the error includes enableGlobalSynthetics=false. That transform variant has no consumer, so D8 refuses to emit the synthetic and the build aborts.
Fix options (in order of how invasive they are):
- Convert the two records back to regular final classes with the same source(), scope(), etc. accessor names — preserves
the public API, no build-system changes, works on every AGP/JDK combination. Most defensible for a library that supports
old Android targets.
- Force AGP onto a transform that has a global-synthetics consumer — e.g. set
android.enableGlobalSyntheticsGeneration=true in gradle.properties, or enable core library desugaring on it-android.
Lighter touch on the source code, but couples Rhino's release artifact compatibility to AGP behavior across plugin
versions.
- Bump it-android minSdk to 35 — not realistic given the workflow tests API 26/28/30/34.
I think the only sensible option is to go with option 1 and forbid the usage of record anywhere in Rhino, sadly.
I spent a bit of time understanding why the CI of #2386 was failing on the Android steps, and Claude helped me figure out that, basically, we can't really use Java 17's
recordunless the minSDK is set to 35. It currently is set to 26.Here's some detail from Claude's analysis:
The chain of cause:
Fix options (in order of how invasive they are):
the public API, no build-system changes, works on every AGP/JDK combination. Most defensible for a library that supports
old Android targets.
android.enableGlobalSyntheticsGeneration=true in gradle.properties, or enable core library desugaring on it-android.
Lighter touch on the source code, but couples Rhino's release artifact compatibility to AGP behavior across plugin
versions.
I think the only sensible option is to go with option 1 and forbid the usage of
recordanywhere in Rhino, sadly.