amzn / kotlin-inject-anvil

Extensions for the kotlin-inject dependency injection framework
Apache License 2.0
274 stars 8 forks source link

Unable to Build iOS App: KLIB resolver: Could not find <anvil runtime> #70

Closed kezc closed 2 weeks ago

kezc commented 3 weeks ago

I'm encountering an issue with building my iOS app in a Kotlin Multiplatform (KMP) project after upgrading the library to version 0.1.0. My setup worked fine with version 0.0.5, but since the update, I’m seeing the following compilation error:

> Task :composeApp:kspKotlinIosSimulatorArm64 FAILED
error: KLIB resolver: Could not find "kotlin-inject-anvil-runtime" in [/Users/Wojtek/StudioProjects/ProjectName, /Users/Wojtek/.konan/klib, /Users/Wojtek/.konan/kotlin-native-prebuilt-macos-aarch64-2.0.21/klib/common, /Users/Wojtek/.konan/kotlin-native-prebuilt-macos-aarch64-2.0.21/klib/platform/ios_simulator_arm64]
error: Compilation finished with errors

I am using only iosSimulatorArm64 since I saw this issue https://github.com/amzn/kotlin-inject-anvil/issues/20. Other dependencies versions:

kotlin = "2.0.21"
kotlin-inject = "0.7.2"
kotlin-inject-anvil = "0.1.0"
ksp = "2.0.21-1.0.26"

kotlin-inject-compiler = { module = "me.tatarka.inject:kotlin-inject-compiler-ksp", version.ref = "kotlin-inject" }
kotlin-inject-runtime = { module = "me.tatarka.inject:kotlin-inject-runtime", version.ref = "kotlin-inject" }
kotlin-inject-anvil-compiler = { module = "software.amazon.lastmile.kotlin.inject.anvil:compiler", version.ref = "kotlin-inject-anvil" }
kotlin-inject-anvil-runtime = { module = "software.amazon.lastmile.kotlin.inject.anvil:runtime", version.ref = "kotlin-inject-anvil" }
kotlin-inject-anvil-runtimeoptional = { module = "software.amazon.lastmile.kotlin.inject.anvil:runtime-optional", version.ref = "kotlin-inject-anvil" }

Dependency Setup: Here are the relevant dependency configurations in my build.gradle.kts:

kotlin {
    listOf(
        iosSimulatorArm64()
    ).forEach { iosTarget ->
        iosTarget.binaries.framework {
            baseName = "ComposeApp"
            isStatic = true
        }
    }

  sourceSets {
     commonMain.dependencies {
          implementation(libs.kotlin.inject.runtime)
          implementation(libs.kotlin.inject.anvil.runtime)
          implementation(libs.kotlin.inject.anvil.runtimeoptional)
    }
  }
}

dependencies {
    kspCommonMainMetadata(libs.kotlin.inject.compiler)
    kspCommonMainMetadata(libs.kotlin.inject.anvil.compiler)
}

addKspDependencyForAllTargets(libs.kotlin.inject.compiler)
addKspDependencyForAllTargets(libs.kotlin.inject.anvil.compiler)

// source: https://github.com/chrisbanes/tivi/tree/main
fun Project.addKspDependencyForAllTargets(dependencyNotation: Any) = addKspDependencyForAllTargets("", dependencyNotation)
fun Project.addKspTestDependencyForAllTargets(dependencyNotation: Any) = addKspDependencyForAllTargets("Test", dependencyNotation)

private fun Project.addKspDependencyForAllTargets(
    configurationNameSuffix: String,
    dependencyNotation: Any,
) {
    val kmpExtension = extensions.getByType<KotlinMultiplatformExtension>()
    dependencies {
        kmpExtension.targets
            .asSequence()
            .filter { target ->
                // Don't add KSP for common target, only final platforms
                target.platformType != KotlinPlatformType.common
            }
            .forEach { target ->
                add(
                    "ksp${target.targetName.capitalized()}$configurationNameSuffix",
                    dependencyNotation,
                )
            }
    }
}
...

Any insights or guidance on resolving this issue would be greatly appreciated. Thank you for your help!

vRallev commented 2 weeks ago

As far as I can tell, this is not a kotlin-inject-anvil issue, but a problem in how you configure KMP and KSP together with the changes of Kotlin 2.0. Please take a look at: https://github.com/evant/kotlin-inject/blob/main/docs/multiplatform.md

Your setup is a little confusing to me. On the one hand you have this:

// Don't add KSP for common target, only final platforms
target.platformType != KotlinPlatformType.common

But then you also do this:

dependencies {
    kspCommonMainMetadata(libs.kotlin.inject.compiler)
    kspCommonMainMetadata(libs.kotlin.inject.anvil.compiler)
}

Consider taking a look at the sample app: https://github.com/amzn/kotlin-inject-anvil/blob/main/sample/lib/build.gradle If you still think this is an issue in the library, then please provide a sample project.

kezc commented 2 weeks ago

In the link you've sent there's a section where they have configured it the same way as I did: https://github.com/evant/kotlin-inject/blob/main/docs/multiplatform.md#adding-the-compiler-dependencies (for every final platform kspXXX and kspCommonMainMetadata) I'll try to break the sample or I'll share my project later this week

kezc commented 2 weeks ago

It's an issue in Circuit library. I am closing this ticket and going to open a new one in relevant repo

EDIT: https://github.com/slackhq/circuit/issues/1790

aaalaniz commented 2 weeks ago

Hey 👋🏼

I have yet to make time to investigate, but I am seeing this issue in a personal project in this PR. In the change, I am trying to remove the workaround for accessing the component creator function in the iOS source set. The only thing that changed was the anvil dependency and a few others.

I'll try to resolve the issue and post back here.

avatsav commented 1 week ago

Hello there, I ran into this issue myself and dug a bit deeper. It seems to be an issue stemming from incompatibility with the 0.1.0 version of kotlin-inject-anvil and circuit 0.25.0.

After importing circuit-codegen into my repo and using it with kotlin-inject-anvil: 0.1.0, the errors were resolved. I'm unfamiliar as to why this incompatibility exists, but the upcoming version of circuit should fix it I believe. The kotlin-inject-anvil update has already been merged into the circuit repo: https://github.com/slackhq/circuit/pull/1780