Skip to content

Update to support AGP 9.1.0 - #282

Open
fegan104 wants to merge 6 commits into
gobley:mainfrom
fegan104:fegan104/agp9
Open

Update to support AGP 9.1.0#282
fegan104 wants to merge 6 commits into
gobley:mainfrom
fegan104:fegan104/agp9

Conversation

@fegan104

@fegan104 fegan104 commented Mar 8, 2026

Copy link
Copy Markdown

Changes

This commit updates now deprecated gradle logic around Kotlin Multiplatform and Android library configurations to support AGP 9.1.0, updates the Rust toolchain, and refactors several build/test plugins to use modern Gradle lazy properties.

rust-toolchain.toml

  • Bumped the Rust toolchain channel from 1.83.0 to 1.85.0. I am not much a Rust dev and didn't even have Cargo installed on my machine. So I might be doing something wrong but I was not able to get the project to build using 1.83.0, I always received an error about having to do with getrandom not being compatible. Bumping to toolchain version fixed that. If this is unacceptable for this PR I can just drop the change.

Build Logic & Plugins

CargoPlugin.kt

  • Task Config: Refactored Cargo tasks to utilize modern Task Provider APIs for cleaner configurations and lazier evaluation.

UniFfiPlugin.kt

  • Lazy Outputs Configuration: Replaced dynamic output directory lookups (mainBindingsDirectory, commonBindingsDirectory, etc.) with explicit flatMap resolutions mapped directly from the BuildUniffiBindingsTask output properties (e.g. buildBindings.flatMap { it.commonMainOutputDir }). This satisfies modern Gradle/AGP isolation requirements.
  • Dependency Registration: Refactored JNA and Coroutines dependency wiring to better handle diverse target plugins (KMP vs standard Android/JVM). Introduces a new addSingleTargetDependency helper for resolving properties independently without aggressively initializing Kotlin SourceSets.

GobleyAndroidCommonExtensionDelegate.kt

  • renamed from GobleyAndroidBaseExtension.kt because the BaseExtension has been remove in AGP 9.

GobleyAndroidKotlinMultiplatformExtensionDelegate.kt

  • Added a new implementation of GobleyAndroidExtensionDelegate for KMP modules with andorid targets.

Example App Configuration

  • Now that you cannot combine KMP module and the andorid application plugin I added new Android example apps that consume the original KMP module. I suppose it would make sense to rename the old app modules to be something alon gthe lines of audio-cpp-lib or todolist-lib instead of app since they aren't really app modules any more but that's not necessary to do now.

Testing

I ran through every unit test, android integration test, and ran example apps on JVM, Android, iOS.

Issues Fixed

Fixes: #153

@fegan104 fegan104 changed the title Fegan104/agp9 Update to support AGP 9.1.0 Mar 8, 2026
@fegan104
fegan104 force-pushed the fegan104/agp9 branch 4 times, most recently from 4dab62b to f0f8493 Compare March 16, 2026 03:28
@Jessewb786

Copy link
Copy Markdown

In Kotlin KMP, how can we pass along the NDK to the cargo plugin when there is no android {} block now?

@fegan104

Copy link
Copy Markdown
Author

In Kotlin KMP, how can we pass along the NDK to the cargo plugin when there is no android {} block now?

The android { ... } block still exists but it's nested inside of the kotlin { ... } block. https://developer.android.com/kotlin/multiplatform/plugin#migrate

You can still get a reference to ndkDirectory with KotlinMultiplatformAndroidComponentsExtension that cargoPlugin can leverage in KMP modules.

That being said the api changed very substantially, and native support is more limited for android in KMP Google recommends:

Alternatively, if you need native build support via externalNativeBuild, our recommendation is to create a separate standalone com.android.library module where you can integrate native code, and consume that standalone library from your Kotlin Multiplatform library project's androidMain source set

Happy to discuss the approach taken in this PR and very open to alternatives suggestions

@fegan104
fegan104 force-pushed the fegan104/agp9 branch 4 times, most recently from 1617f4e to a4c73b8 Compare March 19, 2026 01:33
action: OnVariantAction,
) {
kotlinMultiplatformLibraryExtension.onVariants { agpVariant ->
val isReleaseRequest = project.providers.gradleProperty("gobley.android.release")

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Now that KMP module can no longer use debug/release variants, I'm not sure how else to configure release mode. It looks like you use a CONFIGuRATION env var for XCode builds should we try to do the same here?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For Xcode builds, it is guaranteed that Xcode initializes specific environment variables, but for Android builds, there's no such thing. Currently, Gobley exposes properties like cargo.jvmVariant and cargo.jvmPublishingVariant, so the users can use their preferred Cargo profiles. I'm thinking of making this part read cargo.jvmVariant or cargo.jvmPublishingVariant, I'm just not sure where there will be any scenario that the user wants to build the dev version for Android while the release version for Desktop Java, or vice versa.

@fegan104
fegan104 force-pushed the fegan104/agp9 branch 2 times, most recently from de445b8 to b90f619 Compare March 19, 2026 02:34
@fegan104

Copy link
Copy Markdown
Author

Also I understand this is an outrageously large PR submitted as a single commit, so I can potentially break it up into multiple PRs to make it more reviewable if desired.

@fegan104
fegan104 marked this pull request as ready for review March 19, 2026 02:38
@paxbun

paxbun commented Mar 30, 2026

Copy link
Copy Markdown
Member

Sorry for the late reply. I'll review this by tomorrow. Thanks for waiting and sorry for making you wait again :(

@fegan104

Copy link
Copy Markdown
Author

Sorry for the late reply. I'll review this by tomorrow. Thanks for waiting and sorry for making you wait again :(

Oh no worries, this was a huge change the the gradle API

@paxbun paxbun added this to the 0.3.8 milestone Mar 31, 2026
action: OnVariantAction,
) {
kotlinMultiplatformLibraryExtension.onVariants { agpVariant ->
val isReleaseRequest = project.providers.gradleProperty("gobley.android.release")

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For Xcode builds, it is guaranteed that Xcode initializes specific environment variables, but for Android builds, there's no such thing. Currently, Gobley exposes properties like cargo.jvmVariant and cargo.jvmPublishingVariant, so the users can use their preferred Cargo profiles. I'm thinking of making this part read cargo.jvmVariant or cargo.jvmPublishingVariant, I'm just not sure where there will be any scenario that the user wants to build the dev version for Android while the release version for Desktop Java, or vice versa.

else -> dependencyProject.path
}
}
get() = path

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I want to keep the compatibility between Gobley and older versions of Gradle; is this part for fixing compilation error due to missing ProjectDependency.dependencyProject?


// Ensures getNumAlive() always returns deterministic value
private val coverallLock = ReentrantLock()
private val coverallLock = reentrantLock()

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does the compiler complain about this?

@paxbun

paxbun commented Apr 1, 2026

Copy link
Copy Markdown
Member

I was going to include this in 0.3.8, but this will cause a lot of changes in binary APIs. Will it be possible to minimize the changes and split the PR so some of the fixes are included in 0.3.8 (which will be the final version of 0.3.x) and leave the other for 0.4.0?


For faster onboarding, integration with the AGP application plugin is important. I want to keep the application examples to use the application plugin. I'm planning to re-organize the examples and the plugin directory, do you have any suggestions?

markus2610 added a commit to VisionLab-de/gobley that referenced this pull request May 15, 2026
… AGP 9-compatible onVariants API

AGP 9 sets `MergeSourceSetFolders.variant` to null, causing NPE in
GobleyKotlinAndroidExtensionDelegate that silently drops JNI lib wiring.
Fixes librival_sdk.so missing from debug APK.

Port of gobley PR gobley#282: introduce GobleyAndroidCommonExtensionDelegate and
GobleyAndroidKotlinMultiplatformExtensionDelegate that use
`androidComponents.onVariants { agpVariant ->
  agpVariant.sources.jniLibs?.addGeneratedSourceDirectory(task) { it.outputDir }
}`
instead of task graph introspection. Delete GobleyKotlinAndroidExtensionDelegate.
Add InjectJniLibsTask with typed outputDir property.
@mtpdog

mtpdog commented May 27, 2026

Copy link
Copy Markdown

This commit updates now deprecated gradle logic around Kotlin Multiplatform and Android library configurations to support AGP 9.1.0, updates the Rust toolchain, and refactors several build/test plugins to use modern Gradle lazy properties.

This is great! Could you please publish your fork to Maven as a temporary fix for AGP 9+ cases? It is so needed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add support for the com.android.kotlin.multiplatform.library plugin

4 participants