touchlab / Kermit

Kermit by Touchlab is a Kotlin Multiplatform centralized logging utility.
https://kermit.touchlab.co
Apache License 2.0
699 stars 40 forks source link

Cannot build iOS with co.touchlab:kermit-crashlytics #388

Closed boldtrn closed 7 months ago

boldtrn commented 7 months ago

We followed to docs to add kermit crashlytics to our code base.

commonMain {
    dependencies {
        implementation("co.touchlab:kermit-crashlytics:2.0.2")
    }
}

With only the dependency, it still works and we can build the iOS app.

Once we use the dependency, our build fails:

Logger.setLogWriters(CrashlyticsLogWriter())

The build failure is rather generic:

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

I don't see any other error messages. Once we delete the line:

Logger.setLogWriters(CrashlyticsLogWriter())

Our build works again. Did we miss anything?

BTW: Android works fine, this is only failing on iOS.

kpgalligan commented 7 months ago

The error is from ld. That's a linker issue. It expects the Crashlytics binary but can't find it. That can happen in multiple places.

How are you building the app? Where do you see this error? CLI, Xcode, Android Studio?

There is more to the error somewhere. Specifically what ld is expecting, but I can guess (it's missing Crashlytics).

What's your other config? CocoaPods? SPM? Direct linking (the JetBrains recommended method)?

Then other things. Kotlin version?

The short answer on why it builds without that line, the Kotlin compiler is smart enough to not include the link to Crashlitics if you're not using it. Native builds (not just Kotlin, but everything) work somewhat differently than the JVM. If you don't reference it, it's simply not there. It's a bit more complex than that, but use that as the mental model.

boldtrn commented 7 months ago

How are you building the app? Where do you see this error? CLI, Xcode, Android Studio?

The error only occurs in XCode. Running for example Unit tests in AS for iosSimulator works fine.

What's your other config? CocoaPods? SPM? Direct linking (the JetBrains recommended method)?

We are using CocoaPods.

There is more to the error somewhere. Specifically what ld is expecting, but I can guess (it's missing Crashlytics).

Any idea where we can find this? Xcode unfortunately only shows the error I posted above.

Then other things. Kotlin version?

Kotlin: 1.9.22 Kermit: 2.0.2 XCode: 15.1

Do you need any other info? Or is there an option I can further debug this?

kpgalligan commented 7 months ago

Did you add Crashlytics to your Podfile?

https://cocoapods.org/pods/FirebaseCrashlytics

Example: https://github.com/touchlab/DroidconKotlin/blob/main/ios/Droidcon/Podfile

target 'Droidcon' do
    pod 'DroidconKit', :path => '../'
    pod 'Kingfisher', '~> 7.8.1'
    pod 'Firebase/Analytics'
    pod 'Firebase/Crashlytics'
end
boldtrn commented 7 months ago

Yes we have firebase integrated and already working.

I think I found a solution. We had to add isStatic=true to the build.gradle. I don't really understand why, maybe you could shed some light? If this is correct, maybe we should also update the docs?

kpgalligan commented 7 months ago

@boldtrn

https://crashkios.touchlab.co/docs/crashlytics#step-3---setup-dynamic-linking-optional

Step 3 - Setup Dynamic Linking (Optional) If you're ok with using static frameworks for your shared code, you're done with setup. If you want to export a dynamic framework then you'll see an error like this:

In summary, when building a dynamic framework, the Kotlin compiler wants to satisfy all links at build time. That is where your failure was coming from. For static frameworks, the Kotlin compiler is happy to assume the linked code will be there eventually. If you want to use dynamic frameworks, follow the doc linked above.

However, this won't work for Kotlin tests. The Kotlin compiler used to get around this, but the way they build tests now will run into the same issue. I have a way to get around all of this, but it would be a significant change to CrashKiOS and there are only so many hours in the day, so we haven't gotten to it yet.