[EXTERNAL] fix(android): skip explicit Kotlin plugin when AGP registers the kotlin extension - #1934
Conversation
8d53220 to
d73f157
Compare
|
Thanks, this is the same issue we hit in Capacitor (RevenueCat/purchases-capacitor#860) and Flutter (RevenueCat/purchases-flutter#1765). We went with checking whether AGP already registered the kotlin extension instead of deriving it from the AGP version and property: if (project.extensions.findByName('kotlin') == null) {
apply plugin: 'kotlin-android'
}It tests the exact condition that fails, so there's no version table to keep in sync with AGP and is simpler. Mind switching both files to that? I'll handle CI coverage for AGP 9 separately. |
Oh sure, that seems simpler; let me update it |
…in extension AGP 9 ships built-in Kotlin support and registers the `kotlin` extension itself. Applying kotlin-android on top of it fails configuration with "Cannot add extension with name 'kotlin'". Check for the extension directly rather than deriving it from the AGP version and the android.builtInKotlin property, so there is no version table to keep in sync.
d73f157 to
8bff8b9
Compare
|
Done — both files now use the extension check, and I've updated the PR title and description to match. if (project.extensions.findByName('kotlin') == null) {
apply plugin: 'kotlin-android'
}Agreed it's the better shape: it tests the condition that actually fails, and it covers AGP 10 for free without a version table — which the version-based guard needed a special case for. One thing I wanted to confirm rather than assume, since the whole approach rests on it: that AGP has registered the
I also checked both branches genuinely execute rather than one path always being taken: with the flags off, Still haven't run this repo's own CI — thanks for picking up the AGP 9 coverage. For context on where this came from: it surfaced in a sweep of 157 popular React Native libraries against the AGP 9 defaults. 34 failed with the new DSL on, and 29 of those failed on exactly this collision. I'd used a version-and-property guard across those PRs; I'll take your simpler version back to the others. |
|
Cool! As per our security policy I'll be merging this PR into an intermediate branch to run CI on while keeping credit to you. Thanks again for your contribution! |
22131fc
into
RevenueCat:external/gabrieldonadel/agp9-built-in-kotlin
…isters the kotlin extension (#1934) via @gabrieldonadel (#1939) External contribution from @gabrieldonadel, merged into this branch to run CI. Original PR: #1934 <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Low Risk** > Gradle plugin wiring only; no runtime or security impact, with behavior unchanged on pre-AGP-9 toolchains. > > **Overview** > Fixes Android Gradle Plugin 9 builds that fail with **"Cannot add extension with name 'kotlin'"** when both AGP’s built-in Kotlin support and the `kotlin-android` plugin run together. > > In **`android/build.gradle`** and **`react-native-purchases-ui/android/build.gradle`**, `kotlin-android` is no longer applied unconditionally. It is applied only when `project.extensions.findByName('kotlin')` is null, so older AGP setups still get the plugin while AGP 9 can rely on its own `kotlin` extension. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit 22131fc. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> <!-- /CURSOR_SUMMARY --> Co-authored-by: Gabriel Donadel Dall'Agnol <donadeldev@gmail.com>
Problem
Android Gradle Plugin 9 ships built-in Kotlin support and enables it by default, so AGP
registers the
kotlinextension itself. When a library also applieskotlin-androidexplicitly, the two collide and configuration fails before anything compiles:
The apply is unconditional in both files, so on an AGP 9 project this library cannot be
built at all. There is no consumer-side workaround short of patching the file — setting
android.builtInKotlin=falseproject-wide just to build one dependency is not areasonable ask, and that escape hatch is removed in AGP 10.
Change
Apply the plugin only when nothing has registered the
kotlinextension yet:Files changed:
android/build.gradlereact-native-purchases-ui/android/build.gradleThis checks the exact condition that fails, so there is no AGP version table to keep in
sync. It follows the approach already used in
purchases-capacitor#860 and
purchases-flutter#1765, per
maintainer review on this PR.
Behaviour across configurations:
android.builtInKotlinkotlinextensionfalsetruefalseThe check sits after
apply plugin: 'com.android.library'in both files, so AGP hasalready registered its extensions by the time it runs.
What I verified, and what I did not
9.2.1 and Gradle 9.4.1:
:app:assembleDebugsucceeds both with-Pandroid.newDsl=true -Pandroid.builtInKotlin=trueand with both flags off.taken: with the flags off,
:<module>:compileDebugKotlinruns from the explicitlyapplied plugin; with them on, the build succeeds without it, which it could not do if
the plugin were still being applied.
Phases.CONVERSION.coverage separately.
Found while sweeping 157 popular React Native libraries for AGP 9 new-DSL compatibility.
34 failed with the new DSL enabled, and 29 of those failed on exactly this — it is the
most common blocker by a wide margin.