GitLiveApp / firebase-kotlin-sdk

A Kotlin-first SDK for Firebase
https://gitliveapp.github.io/firebase-kotlin-sdk/
Apache License 2.0
1.08k stars 153 forks source link

Always getting gradle build error for iOS cocapods #428

Closed EchoEllet closed 2 months ago

EchoEllet commented 10 months ago

Hi, I'm trying to create a new module/library in this SDK but first I need to get it in a state where the gradle build doesn't fail

> Task :firebase-firestore:podBuildFirebaseFirestoreIphonesimulator FAILED

For more info:

> Task :firebase-firestore:transformIosTestCInteropDependenciesMetadataForIde
Exception in thread "main" java.lang.Error: /Users/userName/development/playground/framework_based/kmp/firebase-kotlin-sdk/firebase-firestore/build/cocoapods/synthetic/IOS/build/Release-iphoneos/FirebaseFirestore/FirebaseFirestore.framework/Headers/FIRFirestoreSettings.h:46:1: error: property with 'retain (or strong)' attribute must be of object type
    at org.jetbrains.kotlin.native.interop.indexer.ModuleSupportKt.getModulesASTFiles(ModuleSupport.kt:74)
    at org.jetbrains.kotlin.native.interop.indexer.ModuleSupportKt.getModulesInfo(ModuleSupport.kt:14)
    at org.jetbrains.kotlin.native.interop.gen.jvm.MainKt.buildNativeLibrary(main.kt:563)
    at org.jetbrains.kotlin.native.interop.gen.jvm.MainKt.processCLib(main.kt:317)
    at org.jetbrains.kotlin.native.interop.gen.jvm.MainKt.processCLibSafe(main.kt:242)
    at org.jetbrains.kotlin.native.interop.gen.jvm.MainKt.access$processCLibSafe(main.kt:1)
    at org.jetbrains.kotlin.native.interop.gen.jvm.Interop.interop(main.kt:100)
    at org.jetbrains.kotlin.cli.utilities.InteropCompilerKt.invokeInterop(InteropCompiler.kt:45)
    at org.jetbrains.kotlin.cli.utilities.MainKt.mainImpl(main.kt:23)
    at org.jetbrains.kotlin.cli.utilities.MainKt.main(main.kt:45)

I'm not sure how to get this error but I'm pretty sure I started clean and didn't make any changes at all

but if there is more information required I'm ready to provide it

running pod --version

get this output

pod --version
Ignoring ffi-1.16.3 because its extensions are not built. Try: gem pristine ffi --version 1.16.3
Ignoring ffi-1.16.3 because its extensions are not built. Try: gem pristine ffi --version 1.16.3
1.13.0
userName@MacBook-Pro freshtechtips % which pod
/opt/homebrew/bin/pod
userName@Ahmeds-MacBook-Pro freshtechtips % 

I'm using the latest version of Xcode 15

EchoEllet commented 10 months ago

Also, it would be helpful to provide us with information about how to create more libraries for this SDK even though most developers know that already, the docs could require the info about common steps for all modules that could be easily avoided.

Official documentation would be helpful for everyone.

EliasMazz commented 10 months ago

I'm also getting the same error on iOS after updating android and multiplatform the stable version version 1.9.20

Showing Recent Messages The /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/ld command returned non-zero exit code: 1.

output:

/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/ld invocation reported errors

ld: Undefined symbols:

_FIRFirestoreErrorDomain, referenced from:

  _cocoapods_FirebaseFirestore_FIRFirestoreErrorDomain_getter_wrapper0 in MultiPlatformLibrary.framework.o

_OBJCCLASS$_FIRDocumentChange, referenced from:

   in MultiPlatformLibrary.framework.o

_OBJCCLASS$_FIRDocumentSnapshot, referenced from:

   in MultiPlatformLibrary.framework.o

_OBJCCLASS$_FIRFieldPath, referenced from:

   in MultiPlatformLibrary.framework.o

_OBJCCLASS$_FIRFieldValue, referenced from:

   in MultiPlatformLibrary.framework.o

_OBJCCLASS$_FIRFirestore, referenced from:

   in MultiPlatformLibrary.framework.o

_OBJCCLASS$_FIRFirestoreSettings, referenced from:

   in MultiPlatformLibrary.framework.o

_OBJCCLASS$_FIRQuerySnapshot, referenced from:

   in MultiPlatformLibrary.framework.o

_OBJCCLASS$_FIRTimestamp, referenced from:

   in MultiPlatformLibrary.framework.o

/Users/elias.mazzocco/Documents/KMM-Firebase-Messaging/iosApp/Pods/ld:1:1: ignoring duplicate libraries: '-ldl', '-lobjc'

This is my build.gradle file:

plugins { kotlin("multiplatform") kotlin("native.cocoapods") kotlin("plugin.serialization") version "1.8.0" id("com.android.library") id("dev.icerock.mobile.multiplatform-resources") id("dev.icerock.moko.kswift") }

@OptIn(org.jetbrains.kotlin.gradle.ExperimentalKotlinGradlePluginApi::class) kotlin { targetHierarchy.default()

android {
    compilations.all {
        kotlinOptions {
            jvmTarget = "1.8"
        }
    }
}

iosX64()
iosArm64()
iosSimulatorArm64()

cocoapods {
    summary = "Some description for the Shared Module"
    homepage = "Link to the Shared Module homepage"
    version = "1.0"
    ios.deploymentTarget = "14.1"
    podfile = project.file("../iosApp/Podfile")
    framework {
        baseName = "MultiPlatformLibrary"
        // this fixes firestore, but breaks MOKO
        //isStatic = true
        export("dev.icerock.moko:resources:0.23.0")
        export("dev.icerock.moko:mvvm-core:0.16.1")
        export("dev.icerock.moko:mvvm-flow:0.16.1")
        export("dev.icerock.moko:graphics:0.9.0")
    }
    pod("FirebaseAnalyticsSwift")
    pod("FirebaseInAppMessagingSwift", "> 10.12-beta")
    // ld: framework not found FirebaseFirestore
    // To fix this issue, we can use the `linkOnly` parameter in the gradle pod dsl.
    // From the KMM docs: this parameter instructs the CocoaPods plugin to use Pod dependencies
    // with dynamic frameworks without generating cinterop bindings.
    pod("FirebaseFirestore") {
        linkOnly = true
    }
    pod("FirebaseUI/Google")
    pod("FirebaseUI/OAuth")
    pod("FirebaseMessaging")
}

sourceSets {

    val androidMain by getting {
        //dependsOn(commonMain.get())

        dependencies {
            implementation(libs.ktor.client.android)
            implementation(libs.koin.androidx.compose)
            implementation(libs.koin.android)
        }
    }

    val iosMain by getting {
        //dependsOn(commonMain.get())
        dependencies {
            implementation(libs.ktor.ios)
        }
    }

    val commonMain by getting {
        dependencies {
            //put your multiplatform dependencies here

            implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.7.1")

            implementation(libs.kermit)
            implementation(libs.bundles.ktor)
            api(libs.shareResources)
            implementation(libs.koin.core)
            implementation(libs.androidx.datastore.preferences.core)

            api("dev.icerock.moko:mvvm-core:0.16.1") // only ViewModel, EventsDispatcher, Dispatchers.UI
            api("dev.icerock.moko:mvvm-flow:0.16.1") // api mvvm-core, CFlow for native and binding extensions
            api("dev.icerock.moko:mvvm-flow-resources:0.16.1") // api mvvm-core, moko-resources, extensions for Flow with moko-resources
            api("dev.icerock.moko:kswift-runtime:0.6.1") // if you want use annotations

            // Update: To use this, you need to set `isStatic = true` in your
            // cocopods framework. BUT, then MOKO breaks, because MOKO MVVM
            // needs to use a dynamic framework.
            implementation("dev.gitlive:firebase-firestore:1.8.0")
            implementation("dev.gitlive:firebase-auth:1.8.0")

        }
    }
    val commonTest by getting {
        dependencies {
            implementation(kotlin("test"))
        }
    }

}

}

android { namespace = "com.santansarah.kmmfirebasemessaging" compileSdk = 33 defaultConfig { minSdk = 29 } }

multiplatformResources { multiplatformResourcesPackage = "com.santansarah.kmmfirebasemessaging" multiplatformResourcesClassName = "SharedRes" }

kswift { install(dev.icerock.moko.kswift.plugin.feature.SealedToSwiftEnumFeature) }

EliasMazz commented 10 months ago

Ok, I found a workaround for this problem, you can use isStatic = true on cocoapods this will fix firestore.

But the problem is when you cant use isStatic = true like in my case when I use it it breaks MOKO libraries.

So I had to do an workaround, I added

pod("FirebaseFirestore"){ version = "10.12" linkOnly = true }

So it would have the oficial FirebaseFirestore library together with gitlive one, its not ideal but it was the only way I could find to solve this issue:

Here is the build.gradle file that I'm using:

plugins { kotlin("multiplatform") kotlin("native.cocoapods") kotlin("plugin.serialization") version "1.9.20" id("com.android.library") id("dev.icerock.mobile.multiplatform-resources") id("dev.icerock.moko.kswift") }

@OptIn(org.jetbrains.kotlin.gradle.ExperimentalKotlinGradlePluginApi::class) kotlin { targetHierarchy.default()

android {
    compilations.all {
        kotlinOptions {
            jvmTarget = "1.8"
        }
    }
}
iosX64()
iosArm64()
iosSimulatorArm64()

cocoapods {
    summary = "Some description for the Shared Module"
    homepage = "Link to the Shared Module homepage"
    version = "1.0"
    ios.deploymentTarget = "14.1"
    podfile = project.file("../iosApp/Podfile")
    framework {
        baseName = "MultiPlatformLibrary"
        // this fixes firestore, but breaks MOKO
        //isStatic = true
        export("dev.icerock.moko:resources:0.23.0")
        export("dev.icerock.moko:mvvm-core:0.16.1")
        export("dev.icerock.moko:mvvm-flow:0.16.1")
        export("dev.icerock.moko:graphics:0.9.0")
    }
    pod("FirebaseAnalyticsSwift")
    pod("FirebaseInAppMessagingSwift", "> 10.12-beta")
    // ld: framework not found FirebaseFirestore
    // To fix this issue, we can use the `linkOnly` parameter in the gradle pod dsl.
    // From the KMM docs: this parameter instructs the CocoaPods plugin to use Pod dependencies
    // with dynamic frameworks without generating cinterop bindings.
   // This workaround to fix issues with firestore gitlab and avoid  isStatic = true 
    pod("FirebaseFirestore"){
        version = "10.12"
        linkOnly = true
    }
    pod("FirebaseUI/Google"){
        linkOnly = true
    }
    pod("FirebaseUI/OAuth"){
        linkOnly = true
    }
    pod("FirebaseMessaging")
}

sourceSets {

    val androidMain by getting {
        dependencies {
            implementation(libs.ktor.client.android)
            implementation(libs.koin.androidx.compose)
            implementation(libs.koin.android)
        }
    }

    val commonMain by getting {
        dependencies {
            //put your multiplatform dependencies here

            implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.7.1")

            implementation(libs.kermit)
            implementation(libs.bundles.ktor)
            api(libs.shareResources)
            implementation(libs.koin.core)
            implementation(libs.androidx.datastore.preferences.core)

            api("dev.icerock.moko:mvvm-core:0.16.1") // only ViewModel, EventsDispatcher, Dispatchers.UI
            api("dev.icerock.moko:mvvm-flow:0.16.1") // api mvvm-core, CFlow for native and binding extensions
            api("dev.icerock.moko:mvvm-flow-resources:0.16.1") // api mvvm-core, moko-resources, extensions for Flow with moko-resources
            api("dev.icerock.moko:kswift-runtime:0.6.1") // if you want use annotations

            // Update: To use this, you need to set `isStatic = true` in your
            // cocopods framework. BUT, then MOKO breaks, because MOKO MVVM
            // needs to use a dynamic framework.

            implementation("dev.gitlive:firebase-firestore:1.8.0")
            implementation("dev.gitlive:firebase-auth:1.8.0")

        }
    }
    val commonTest by getting {
        dependencies {
            implementation(kotlin("test"))
        }
    }

    val iosMain by getting {
        dependencies {
            implementation(libs.ktor.ios)
        }
    }
}

}

android { namespace = "com.santansarah.kmmfirebasemessaging" compileSdk = 33 defaultConfig { minSdk = 29 } }

multiplatformResources { multiplatformResourcesPackage = "com.santansarah.kmmfirebasemessaging" multiplatformResourcesClassName = "SharedRes" }

kswift { install(dev.icerock.moko.kswift.plugin.feature.SealedToSwiftEnumFeature) }

Qw4z1 commented 9 months ago

@EliasMazz I've set all the iOS things to static (seems to be a Firebase SDK iOS thing) and exported MOKO like so:

    listOf(
        iosX64(),
        iosArm64(),
        iosSimulatorArm64()
    ).forEach { iosTarget ->
        iosTarget.binaries.framework {
            baseName = "shared"
            isStatic = true
            export("dev.icerock.moko:resources:0.23.0")
        }
    }

Then I opened Xcode and copy pasted the Build Phase Script available in the MOKO docs.

Seems to be working well with Kotlin 1.9.20 and Compose 1.5.10.