Skip to content

Commit 5a733d4

Browse files
fix(android): skip explicit Kotlin plugin when AGP registers the kotlin extension (#787)
## Problem Android Gradle Plugin 9 ships built-in Kotlin support and enables it by default, so AGP registers the `kotlin` extension itself. When a library *also* applies `kotlin-android` explicitly, the two collide and configuration fails before anything compiles. AGP words it two ways, both the same problem: ``` > Failed to apply plugin 'kotlin-android'. > Cannot add extension with name 'kotlin', as there is an extension already registered with that name. ``` ``` > The 'kotlin-android' plugin is no longer required for Kotlin support since AGP 9.0. ``` The apply is unconditional in this module, so on an AGP 9 project this cannot be built at all. There is no consumer-side workaround short of patching the file — setting `android.builtInKotlin=false` project-wide just to build one dependency is not a reasonable ask, and that escape hatch is removed in AGP 10. ## Change Apply the plugin only when nothing has registered the `kotlin` extension yet: ```groovy if (project.extensions.findByName('kotlin') == null) { apply plugin: 'kotlin-android' } ``` Files changed: - `android/build.gradle` This tests the condition that actually fails, so there is no AGP version table to keep in sync, and it covers AGP 10 — where the `android.builtInKotlin` opt-out is removed — without a special case. | AGP | `android.builtInKotlin` | `kotlin` extension | explicit apply | |---|---|---|---| | 8.x | unset or `false` | absent | yes (unchanged) | | 9.x | unset or `true` | registered by AGP | no | | 9.x | `false` | absent | yes | | 10+ | n/a (removed) | registered by AGP | no | The guard sits after `apply plugin: 'com.android.library'` in every file it touches, so AGP has already registered its extensions by the time it runs. I checked that ordering per file rather than assuming it. ## What I verified, and what I did not - **Verified end to end** on a real Expo SDK 58 / React Native 0.87 project with AGP 9.2.1 and Gradle 9.4.1: `:app:assembleDebug` succeeds both with `-Pandroid.newDsl=true -Pandroid.builtInKotlin=true` and with both flags off. - Confirmed both branches actually execute rather than one path always winning: with the flags off, `compileDebugKotlin` runs from the explicitly applied plugin; with them on the build completes without it. - Every changed file passes a Groovy `Phases.CONVERSION` syntax check. - **Not run:** this repo's own CI or example app. ## Where this came from A sweep of 500 popular React Native libraries against the AGP 9 defaults. 152 failed with the new DSL enabled, and **144 of those failed on exactly this collision** — by far the most common blocker. Affects `react-native-enriched`, `react-native-enriched-html` here. The same guard shape was accepted in [RevenueCat/react-native-purchases#1934](RevenueCat/react-native-purchases#1934), at that maintainer's suggestion. --------- Co-authored-by: Krystian Sienkiewicz <krystian.sienkiewicz@swmansion.com>
1 parent 237c889 commit 5a733d4

1 file changed

Lines changed: 7 additions & 1 deletion

File tree

android/build.gradle

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,13 @@ buildscript {
2020

2121

2222
apply plugin: "com.android.library"
23-
apply plugin: "kotlin-android"
23+
// AGP 9 ships built-in Kotlin support and registers the `kotlin` extension
24+
// itself. Applying the Kotlin plugin on top of it fails configuration with
25+
// "Cannot add extension with name 'kotlin'". Only apply it when nothing has
26+
// registered that extension yet.
27+
if (project.extensions.findByName('kotlin') == null) {
28+
apply plugin: "kotlin-android"
29+
}
2430

2531
apply plugin: "com.facebook.react"
2632

0 commit comments

Comments
 (0)