Skip to content

Commit d588a6b

Browse files
authored
chore: remove BCV plugin (incompatible with AGP 9) (#214)
## Summary - Remove Binary Compatibility Validator (BCV) plugin from all modules — it silently stopped working after the AGP 9 upgrade - AGP 9 rejects `kotlin-android` plugin, which BCV hooks into for task registration - Neither BCV nor KGP's `abiValidation` currently support AGP 9's built-in Kotlin - Keep existing `.api` files as historical reference ### Upstream issue [Kotlin/binary-compatibility-validator#312](Kotlin/binary-compatibility-validator#312) — BCV tasks not registered with AGP 9 (open, no fix)
1 parent 64c927e commit d588a6b

6 files changed

Lines changed: 33 additions & 122 deletions

File tree

API_COMPATIBILITY.md

Lines changed: 33 additions & 96 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,37 @@
11
# API Compatibility
22

3-
This project uses [Binary Compatibility Validator](https://github.com/Kotlin/binary-compatibility-validator) (BCV) to track public API changes and prevent accidental breaking changes.
3+
## Current Status: Temporarily Disabled
4+
5+
API compatibility validation is **temporarily disabled** due to an incompatibility between AGP 9's built-in Kotlin support and the [Binary Compatibility Validator](https://github.com/Kotlin/binary-compatibility-validator) (BCV) plugin.
6+
7+
### What happened
8+
9+
AGP 9 introduced built-in Kotlin compilation support and actively rejects the `org.jetbrains.kotlin.android` plugin. BCV hooks into that plugin to register its `apiCheck`/`apiDump` tasks. Without it, BCV applies silently but registers no tasks — API validation was broken since the AGP 9 upgrade with no visible error.
10+
11+
The intended replacement — Kotlin Gradle Plugin's built-in `abiValidation` — has the same limitation: it requires `KotlinAndroidProjectExtension` which AGP 9's built-in Kotlin does not provide.
12+
13+
### Upstream issues
14+
15+
- [Kotlin/binary-compatibility-validator#312](https://github.com/Kotlin/binary-compatibility-validator/issues/312) — BCV tasks not registered with AGP 9 (open, no maintainer response)
16+
- [KT-81117](https://youtrack.jetbrains.com/issue/KT-81117) — KGP conflicts with AGP 9 built-in Kotlin
17+
- BCV is in [maintenance mode](https://github.com/Kotlin/binary-compatibility-validator#readme), superseded by KGP's `abiValidation` (experimental since Kotlin 2.1.20)
18+
19+
### Workarounds considered
20+
21+
| Approach | Status |
22+
|----------|--------|
23+
| `android.builtInKotlin=false` | Works but temporary — removed in AGP 10 |
24+
| Manual BCV task registration ([OkHttp approach](https://github.com/square/okhttp/pull/9375)) | KMP-specific, fragile |
25+
| Fork BCV and fix | Maintaining a fork of a deprecated plugin is not worthwhile |
26+
| KGP `abiValidation` | Requires `kotlin-android` plugin which AGP 9 rejects |
27+
28+
### Plan
29+
30+
1. Keep the existing `.api` files as a historical reference of the last validated public API surface
31+
2. Monitor upstream issues for a fix in BCV, KGP, or AGP
32+
3. Re-enable validation when the ecosystem supports AGP 9
33+
34+
---
435

536
## Why It Matters
637

@@ -21,57 +52,7 @@ debugoverlay-extension-okhttp/api/debugoverlay-extension-okhttp.api
2152
debugoverlay-extension-timber/api/debugoverlay-extension-timber.api
2253
```
2354

24-
These files are checked into version control and serve as the "golden" reference for the public API.
25-
26-
## Gradle Tasks
27-
28-
| Task | Purpose |
29-
|------|---------|
30-
| `./gradlew apiCheck` | Compares current API against `.api` files. Fails if there are differences. Runs automatically as part of `check`. |
31-
| `./gradlew apiDump` | Regenerates `.api` files from current code. Use after making intentional API changes. |
32-
33-
### Module-specific tasks
34-
35-
```bash
36-
# Check a specific module
37-
./gradlew :debugoverlay-core:apiCheck
38-
39-
# Update a specific module's API dump
40-
./gradlew :debugoverlay-core:apiDump
41-
```
42-
43-
## Workflow
44-
45-
### Making API Changes
46-
47-
1. **Make your changes** to the public API (add/modify/remove public classes, methods, etc.)
48-
49-
2. **Run `apiCheck`** to see what changed:
50-
```bash
51-
./gradlew apiCheck
52-
```
53-
This will fail and show the differences.
54-
55-
3. **Review the diff** to ensure changes are intentional:
56-
- Adding new public API is generally safe
57-
- Removing or modifying existing API is a breaking change
58-
59-
4. **Update the API dump** if changes are intentional:
60-
```bash
61-
./gradlew apiDump
62-
```
63-
64-
5. **Commit both** your code changes and the updated `.api` files together.
65-
66-
### CI Failures
67-
68-
If CI fails on `apiCheck`:
69-
70-
1. **Accidental change?** - Revert unintended public API exposure (e.g., missing `internal` modifier)
71-
72-
2. **Intentional change?** - Run `apiDump` locally and commit the updated `.api` files
73-
74-
3. **Merge conflict in `.api` files?** - Regenerate with `apiDump` after resolving code conflicts
55+
These files are checked into version control. While validation is disabled, they serve as a reference but are not automatically checked against the current code.
7556

7657
## Handling Breaking Changes
7758

@@ -84,16 +65,6 @@ existing implementers (they must implement the new member). However, since Debug
8465
provides concrete implementations (e.g., `DebugOverlayTimberTree` for `LogSource`),
8566
consumers typically don't implement these interfaces directly.
8667

87-
```kotlin
88-
// Adding a new class (safe)
89-
public class NewFeature { ... }
90-
91-
// Adding a new method to an object (safe)
92-
public object DebugOverlay {
93-
public fun newMethod() { ... } // New - existing code unaffected
94-
}
95-
```
96-
9768
### Removing/Changing API (Breaking)
9869

9970
Breaking changes require careful consideration:
@@ -126,21 +97,6 @@ v2.2.0 - Change deprecation to ERROR level
12697
v3.0.0 - Remove deprecated API
12798
```
12899

129-
## Configuration
130-
131-
BCV is configured in each module's `build.gradle.kts`:
132-
133-
```kotlin
134-
plugins {
135-
alias(libs.plugins.bcv)
136-
}
137-
138-
apiValidation {
139-
// Exclude classes annotated with this from API tracking
140-
nonPublicMarkers.add("com.ms.square.debugoverlay.internal.InternalDebugOverlayApi")
141-
}
142-
```
143-
144100
### Excluding Internal APIs
145101

146102
Use `@InternalDebugOverlayApi` annotation to mark APIs that are public in bytecode but not intended for external use:
@@ -149,22 +105,3 @@ Use `@InternalDebugOverlayApi` annotation to mark APIs that are public in byteco
149105
@InternalDebugOverlayApi
150106
public class SomeInternalHelper { ... }
151107
```
152-
153-
## Common Scenarios
154-
155-
### "I added a new public method but didn't mean to"
156-
157-
Make the method `internal` or `private`, then verify with `apiCheck`.
158-
159-
### "I need to expose internal classes temporarily"
160-
161-
Don't. Instead, design a proper public API or use `@InternalDebugOverlayApi` to signal "use at your own risk."
162-
163-
### "The API dump shows generated classes like `ComposableSingletons$*`"
164-
165-
In debugoverlay-core, these are filtered out via `apiValidation.ignoredPackages` to reduce noise.
166-
If you see them in other modules, they're Compose compiler artifacts and don't affect consumers.
167-
168-
### "Merge conflicts in `.api` files"
169-
170-
Don't manually resolve - just run `apiDump` after resolving code conflicts.

debugoverlay-core/build.gradle.kts

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ plugins {
44
alias(libs.plugins.kotlin.serialization)
55
alias(libs.plugins.dexcount)
66
alias(libs.plugins.mavenPublish)
7-
alias(libs.plugins.bcv)
87
id("jacoco")
98
}
109

@@ -18,14 +17,6 @@ kotlin {
1817
explicitApi()
1918
}
2019

21-
apiValidation {
22-
nonPublicMarkers.add("com.ms.square.debugoverlay.internal.InternalDebugOverlayApi")
23-
ignoredClasses.add("com.ms.square.debugoverlay.core.BuildConfig")
24-
// to ignore ComposableSingletons - unavoidable Compose compiler noise
25-
ignoredPackages.add("com.ms.square.debugoverlay.internal.ui")
26-
ignoredPackages.add("com.ms.square.debugoverlay.internal.bugreport.ui")
27-
}
28-
2920
android {
3021
namespace = "com.ms.square.debugoverlay.core"
3122

debugoverlay-extension-okhttp/build.gradle.kts

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ plugins {
22
alias(libs.plugins.androidLibrary)
33
alias(libs.plugins.dexcount)
44
alias(libs.plugins.mavenPublish)
5-
alias(libs.plugins.bcv)
65
id("jacoco")
76
}
87

@@ -16,10 +15,6 @@ kotlin {
1615
explicitApi()
1716
}
1817

19-
apiValidation {
20-
nonPublicMarkers.add("com.ms.square.debugoverlay.internal.InternalDebugOverlayApi")
21-
}
22-
2318
android {
2419
namespace = "com.ms.square.debugoverlay.extension.okhttp"
2520

debugoverlay-extension-timber/build.gradle.kts

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ plugins {
22
alias(libs.plugins.androidLibrary)
33
alias(libs.plugins.dexcount)
44
alias(libs.plugins.mavenPublish)
5-
alias(libs.plugins.bcv)
65
id("jacoco")
76
}
87

@@ -16,10 +15,6 @@ kotlin {
1615
explicitApi()
1716
}
1817

19-
apiValidation {
20-
nonPublicMarkers.add("com.ms.square.debugoverlay.internal.InternalDebugOverlayApi")
21-
}
22-
2318
android {
2419
namespace = "com.ms.square.debugoverlay.extension.timber"
2520

debugoverlay/build.gradle.kts

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ plugins {
22
alias(libs.plugins.androidLibrary)
33
alias(libs.plugins.dexcount)
44
alias(libs.plugins.mavenPublish)
5-
alias(libs.plugins.bcv)
65
id("jacoco")
76
}
87

@@ -16,10 +15,6 @@ kotlin {
1615
explicitApi()
1716
}
1817

19-
apiValidation {
20-
nonPublicMarkers.add("com.ms.square.debugoverlay.internal.InternalDebugOverlayApi")
21-
}
22-
2318
android {
2419
namespace = "com.ms.square.debugoverlay"
2520
compileSdk = libs.versions.androidCompileSdk.get().toInt()

gradle/libs.versions.toml

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22
# Plugins
33
agp = "9.0.1"
44
jacoco = "0.8.12"
5-
bcv = "0.18.1"
65
dexcount = "4.0.0"
76
kotlinxSerializationJson = "1.10.0"
87
maven-publish = "0.36.0"
@@ -118,7 +117,6 @@ robolectric = { module = "org.robolectric:robolectric", version.ref = "robolectr
118117
[plugins]
119118
androidApplication = { id = "com.android.application", version.ref = "agp" }
120119
androidLibrary = { id = "com.android.library", version.ref = "agp" }
121-
bcv = { id = "org.jetbrains.kotlinx.binary-compatibility-validator", version.ref = "bcv" }
122120
kotlin-compose = { id = "org.jetbrains.kotlin.plugin.compose", version.ref = "kotlin" }
123121
kotlin-serialization = { id = "org.jetbrains.kotlin.plugin.serialization", version.ref = "kotlin" }
124122
hilt-android = { id = "com.google.dagger.hilt.android", version.ref = "hilt" }

0 commit comments

Comments
 (0)