GitLiveApp / firebase-kotlin-sdk

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

Undefined symbols for architecture x86_64 FirebaseFunctions #66

Closed corrado4eyes closed 4 years ago

corrado4eyes commented 4 years ago

Description: Hi guys, I'm getting the following error during linkDebugFrameworkIos task:

Undefined symbols for architecture x86_64:
  "_OBJC_CLASS_$_GTMSessionFetcherService", referenced from:
      objc-class-ref in FirebaseFunctions(FIRFunctions.o)
  "_kGTMSessionFetcherStatusDomain", referenced from:
      ___67-[FIRFunctions callFunction:withObject:timeout:context:completion:]_block_invoke.129 in FirebaseFunctions(FIRFunctions.o)
ld: symbol(s) not found for architecture x86_64

I had the same problem described in #36 and I could solve it as suggested (And since I'm using FirebaseFunctions, I did the same for it).

I've been trying a bunch of solution found on the web like adding $(inherited) in Other Linker Flags, or cleaning DerivedData, but none of them worked.

Then I could solve it downloading the latest version of Firebase sdk and adding linkerOpts in my build.gradle.kts (the shared one), but when I call the cloud function from shared code, I get this error:

dev.gitlive.firebase.functions.FirebaseFunctionsException: Error Domain=com.google.GTMSessionFetcher Code=-1 "(null)" UserInfo={NSErrorFailingURLStringKey=(missing URL)}

This is my build.gradle.kts:

import com.android.build.gradle.internal.cxx.configure.gradleLocalProperties
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinNativeTarget
import com.codingfeline.buildkonfig.compiler.FieldSpec.Type

plugins {
    kotlin("multiplatform")
    id("co.touchlab.native.cocoapods")
    id("com.android.library")
    id("kotlinx-serialization")
    id("com.codingfeline.buildkonfig")
}

android {
    compileSdkVersion(29)
    defaultConfig {
        minSdkVersion(21)
        targetSdkVersion(29)
        versionCode = 1
        versionName = "1.0"
        testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
    }
}

kotlin {
    android()
    //Revert to just ios() when gradle plugin can properly resolve it
    val onPhone = System.getenv("SDK_NAME")?.startsWith("iphoneos") ?: false
    if (onPhone) {
        iosArm64("ios")
    } else {
        iosX64("ios")
    }
    targets.getByName<KotlinNativeTarget>("ios").compilations["main"].kotlinOptions.freeCompilerArgs +=
        listOf("-Xobjc-generics", "-Xg0")
    version = "1.1"

    sourceSets {
        all {
            languageSettings.apply {
                useExperimentalAnnotation("kotlinx.coroutines.ExperimentalCoroutinesApi")
            }
        }

        val kotlinVersion: String by project
        val appCompatVersion: String by project
        val commonKoinVersion: String by project
        val nativeCoroutinesVersion: String by project
        val ktorVersion: String by project
        val kmpSettingsVersion: String by project
        val commonFirebaseVersion: String by project
        val firebaseFunctionsVersion: String by project

        val commonMain by getting {
            dependencies {
                implementation(kotlin("stdlib-common", kotlinVersion))

                // Common Deps

                // Touchlab
                implementation("co.touchlab:stately-common:1.0.3")
                implementation("co.touchlab:stately-concurrency:1.0.3")

                // Ktor
                implementation("io.ktor:ktor-client-core:$ktorVersion")
                implementation("io.ktor:ktor-client-json:$ktorVersion")
                implementation("io.ktor:ktor-client-serialization:$ktorVersion")
                implementation("io.ktor:ktor-client-gson:$ktorVersion")
                implementation("io.ktor:ktor-client-logging:$ktorVersion")

                // Coroutines
                implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core-common:1.3.6")

                // Koin
                implementation("org.koin:koin-core:$commonKoinVersion")

                // Multiplatform Settings
                implementation("com.russhwolf:multiplatform-settings:$kmpSettingsVersion")

                //Firebase
                implementation("dev.gitlive:firebase-functions:$commonFirebaseVersion")
                implementation("com.google.firebase:firebase-functions:$firebaseFunctionsVersion")

            }
        }

        val androidMain by getting {
            dependsOn(commonMain)

            dependencies {
                // Android Deps

                implementation(kotlin("stdlib", kotlinVersion))
                implementation("androidx.appcompat:appcompat:$appCompatVersion")

                // Ktor
                implementation("io.ktor:ktor-client-okhttp:$ktorVersion")
                implementation("io.ktor:ktor-client-json-jvm:$ktorVersion")
                implementation("io.ktor:ktor-client-core-jvm:$ktorVersion")
                implementation("io.ktor:ktor-client-serialization-jvm:$ktorVersion")
                implementation("io.ktor:ktor-client-logging-jvm:$ktorVersion")

                // Coroutines
                implementation("org.jetbrains.kotlinx:kotlinx-coroutines-android:1.3.7")
            }
        }

        val iosMain by getting {
            dependsOn(commonMain)

            dependencies {
                // iOS Deps

                // Ktor
                implementation("io.ktor:ktor-client-ios:$ktorVersion")
                implementation("io.ktor:ktor-client-core-native:$ktorVersion")
                implementation("io.ktor:ktor-client-json-native:$ktorVersion")
                implementation("io.ktor:ktor-client-serialization-native:$ktorVersion")
                implementation("io.ktor:ktor-client-logging-native:$ktorVersion")

                //Koin
                implementation("org.koin:koin-core:$commonKoinVersion")

                // Coroutines
                implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core-native:$nativeCoroutinesVersion") {
                    version {
                        strictly(nativeCoroutinesVersion)
                    }
                }
            }
        }

    }

    cocoapodsext {
        summary = "Summary"
        homepage = "homepage"
        framework {
            isStatic = false
//         Latest Firebase Version (6.28.1)
            linkerOpts("-F/path/to/Firebase_latest/FirebaseAnalytics/FirebaseCore.xcframework/ios-i386_x86_64-simulator/")
            linkerOpts("-F/path/to/Firebase_latest/FirebaseAnalytics/FirebaseCoreDiagnostics.xcframework/ios-i386_x86_64-simulator/")
            linkerOpts("-F/path/to/Firebase_latest/FirebaseAnalytics/GoogleDataTransport.xcframework/ios-i386_x86_64-simulator/")
            linkerOpts("-F/path/to/Firebase_latest/FirebaseAnalytics/FirebaseInstallations.xcframework/ios-i386_x86_64-simulator/")
            linkerOpts("-F/path/to/Firebase_latest/FirebaseAnalytics/")

            linkerOpts("-F/path/to/Firebase_latest/FirebaseFunctions/FirebaseFunctions.xcframework/ios-i386_x86_64-simulator/")
            linkerOpts("-F/path/to/Firebase_latest/FirebaseFunctions/GTMSessionFetcher.xcframework/ios-i386_x86_64-simulator/")

            linkerOpts("-F/path/to/Firebase_latest/FirebaseMessaging/FirebaseInstanceID.xcframework/ios-i386_x86_64-simulator/")

//            Same Firebase Version as firebase-kotlin-sdk
//            linkerOpts("-F/path/to/Firebase/FirebaseAnalytics/")
//            linkerOpts("-F/path/to/sdks/Firebase/FirebaseFunctions/")
//            linkerOpts("-F/path/to/Firebase/FirebaseRemoteConfig")
        }
    }

}

buildkonfig {
    packageName = "com.corrado4eyes.zoomdemoandroid.shared"

    val firebaseApiKey: String = gradleLocalProperties(rootDir).getProperty("firebaseApiKey")
    val firebaseDbUrl: String = gradleLocalProperties(rootDir).getProperty("firebaseDbUrl")
    val storageBucket: String = gradleLocalProperties(rootDir).getProperty("storageBucket")
    val firebaseProjectId: String = gradleLocalProperties(rootDir).getProperty("firebaseProjectId")
    val firebaseAppName: String = gradleLocalProperties(rootDir).getProperty("firebaseAppName")

    defaultConfigs {
        buildConfigField(Type.STRING, "BASE_URL", "https://api.zoom.us/")
        buildConfigField(Type.STRING, "FIREBASE_API_KEY", firebaseApiKey)
        buildConfigField(Type.STRING, "FIREBASE_DB_URL", firebaseDbUrl)
        buildConfigField(Type.STRING, "STORAGE_BUCKET", storageBucket)
        buildConfigField(Type.STRING, "FIREBASE_PROJECT_ID", firebaseProjectId)
        buildConfigField(Type.STRING, "FIREBASE_APP_NAME", firebaseAppName)

    }
}

Kotlin Version: 1.3.72. Android Studio Version: 4.0. Xcode Version: 11.6.

I hope I gave you enough info and that they're relevant. Thanks in advance!

corrado4eyes commented 4 years ago

In the end I solved my problem, but using the latest version of Firebase sdk (so I still get this Undefined symbols for architecture x86_64 using older version). Basically I'm using BuildKonfig to inject parameter like in Android's BuildConfig and I defined n-values in my local.properties as:

firebaseApiKey="apiKey"
firebaseProjectId="projectId"
firebaseDbUrl="dbUrl"
firebaseAppName="appName"
storageBucket="storageBucket"

Apparently Android could handle the double quotes since no Exception was thrown or message printed and I could normally call my cloud functions, but ios couldn't. The error was thrown with the double quotes on firebaseProjectId value, removing those solved this error:

dev.gitlive.firebase.functions.FirebaseFunctionsException: Error Domain=com.google.GTMSessionFetcher Code=-1 "(null)" UserInfo={NSErrorFailingURLStringKey=(missing URL)}
leoull commented 1 year ago

I had similar issue. This post worked for me