https://kotlinlang.org logo
#multiplatform
Title
# multiplatform
k

Kirill Zhukov

10/31/2023, 7:44 PM
What’s the process for addressing issues like this in Kotlin Native?
Copy code
Undefined symbols for architecture arm64:
  "_OBJC_CLASS_$_Bugsnag", referenced from:
      objc-class-ref in libco.touchlab.crashkios:bugsnag-cache.a(result.o)
  "_OBJC_CLASS_$_BugsnagError", referenced from:
      objc-class-ref in libco.touchlab.crashkios:bugsnag-cache.a(result.o)
  "_OBJC_CLASS_$_BugsnagFeatureFlag", referenced from:
      objc-class-ref in libco.touchlab.crashkios:bugsnag-cache.a(result.o)
  "_OBJC_CLASS_$_BugsnagStackframe", referenced from:
      objc-class-ref in libco.touchlab.crashkios:bugsnag-cache.a(result.o)
ld: symbol(s) not found for architecture arm64
We started seeing this after enabling K/N build cache (removing
kotlin.native.cacheKind=none
basically)
k

Kirill Zhukov

10/31/2023, 8:30 PM
We already apply this plugin in the Gradle module that builds XC Framework 🤔
Does it need to be applied in all modules perhaps?
r

Rick Clephas

10/31/2023, 8:35 PM
Good question, I want to say that should be enough, but not 100% sure. @kpgalligan?
k

kpgalligan

10/31/2023, 8:59 PM
It's complicated 🙂
The task that is failing with that message will tell you a lot. You should only need that plugin in the module making a framework, and only if it's a dynamic framework. However, tests are the complex part. Disabling the compiler cache used to allow tests to work. Before that, as long as you didn't reference anything from bugsnag in your test code (including setup, any referenced code, etc), the Kotlin compiler would simply strip out the code that held references to bugsnag, and you'd be fine. At some point in the last few versions, tests started to be built with dynamic binaries, so they include all of your code. This presumably sped up the compilation for tests, but forced symbol resolution. Our recent issue is, as much as I'd rather not disable the cache, that also appears to not work anymore.
Solutions are still being discussed (but our backlog is currently pretty long, so I'm not sure when we'll sort that out). • Add bugsnag with CocoaPods in Kotlin. Not a good way to go, for a number of reasons, but that will make the symbols available. • Create a "stub" binary to satisfy the linker for the test compilation. Assuming you never call it (and in a test, you probably shouldn't), that would work. We were doing something like that 1+ years ago. • Figure out if we can just call the Objc dynamically for Bugsnag and Crashlytics, then you don't really have to worry about any of this, and it solves another current issue we have that most don't.
If you're using an "umbrella" module to create the framework, and you don't need to test any code there, just make sure there are no tests for K/N to run, and it should skip that step.
But, step one, which task is failing? That'll dictate the options.
k

Kirill Zhukov

10/31/2023, 10:05 PM
This failure is from a non-umbrella module that does not apply the plugin but it does depend on
co.touchlab.crashkios:bugsnag
lib
k

kpgalligan

10/31/2023, 10:23 PM
Well, if you have bugsnag in there and are running tests in the module, that liker issue will happen. As mentioned, our previous workaround was turning off caching, which again, isn't ideal, but otherwise the linker fails. That was working, but in very recent versions, it stopped in our test app. I'm not entirely sure if that's just a misconfiguration, or if the test compiler changed again. The problem in this case is there's no way to simply say "don't worry about that" or, say, use CocoaPods to just pull in the binary for testing. Another option would be to grab the Bugsnag framework directly and link to it just for testing, but that kind of config is non-trivial. An "elegant" resolution is still TBD.
👍 1
If you're not running tests in that module, but you are exporting a framework (it doesn't need to be an umbrella module), the linker plugin should work, but if you're using that and its not working, I assume the test build is failing.
k

Kirill Zhukov

10/31/2023, 10:31 PM
The strange thing is that it fails on CI (on a mac worker, I think it’s a mac mini with apple silicon/arm64?) but works locally (m1 max - arm64) 😵‍💫
But yeah, it’s the
linkDebugTestIosSimulatorArm64
task that fails
Perhaps we did not define the
iosTest
task correctly? We have this “umbrella” task defined:
Copy code
project.tasks.register("iosTest") {
  description = "Executes Kotlin/Native unit tests for all available targets."
  group = "Verification"

  // For running tests on an arm64 compatible host.
  project.tasks.findByName("iosX64Test")?.let {
    dependsOn(it)
  }

  // For running tests on host that are arm64 compatible.
  // For running tests on a non-arm64 compatible host.
  project.tasks.findByName("iosSimulatorArm64Test")?.let {
    dependsOn(it)
  }
}
This was set up before we enabled hierarchical project structure. It doesn’t look like
iosTest
Gradle is provided out of the box either way.
Thinking through how to go about disabling K/N tests on a specific module
Disabling K/N tests for the module fixes that particular problem but now Compose Multiplatform linking breaks 😃
k

kpgalligan

10/31/2023, 11:10 PM
Hard to say much more without more detail about the module and app structure. Is that module making the framework for iOS?
k

Kirill Zhukov

10/31/2023, 11:11 PM
It is not, it just adds a crashkios dependency (does not apply the plugin).
k

kpgalligan

10/31/2023, 11:12 PM
Same module, or do multiple include the dependency?
k

Kirill Zhukov

10/31/2023, 11:14 PM
So we have
:shared:bugsnag
module that adds
co.touchlab.crashkios:bugsnag
dependency, does not depend on Crashkios plugin. And we have a
:shared:xc-framework
umbrella module that builds the XC Framework. Depends on and exports
:shared:bugsnag
, also applies the craskhios plugin.
This is our baseline set up right now. I ended up doing following: • enabled K/N build cache • set
isStatic = true
on the XC Framework module • remove applying crashkios plugin • Disable K/N tests for the
:shared:bugsnag
module Everything compiles fine but getting Compose Multiplatform linking warnings now and a runtime crash on iOS:
Copy code
w: <bitkey.shared.state-machine.ui:public> @ /Users/zhukov/Development/wallet/app/shared/state-machine/ui/public/src/iosMain/kotlin/build/wallet/statemachine/recovery/cloud/CloudSignInUiStateMachineImpl.kt:37:5: Function 'LaunchedEffect' can not be called: No function found for symbol 'androidx.compose.runtime/LaunchedEffect|-576771147392862334[0]'
w: <missing declarations>: No function found for symbol 'app.cash.molecule/launchMolecule|-7305106088441339121[0]'
w: <missing declarations>: No function found for symbol 'androidx.compose.runtime/remember|1835138394250687683[0]'
w: <missing declarations>: No function found for symbol 'androidx.compose.runtime/remember|-2596345568877061727[0]'
Unrelated to Crashkios at this point.
k

kpgalligan

10/31/2023, 11:21 PM
weird. What version of Kotlin?
k

Kirill Zhukov

10/31/2023, 11:22 PM
Kotlin 1.9.10, Compose Multiplatform 1.5.3
k

kpgalligan

10/31/2023, 11:24 PM
The last message said 1.9.20 would work. We were using 1.8.20 for Droidcon, but I just bumped that to 1.9.20 and things seem to be working well there. https://github.com/touchlab/DroidconKotlin. Well, 1.9.20-RC, but will update that soon.
k

Kirill Zhukov

10/31/2023, 11:25 PM
> The last message said 1.9.20 would work Missed that! Going to wait for stable Compose Multiplatform version to support 1.9.20, and will give it another try 🙂
Thanks!
k
Second message says something about the compiler
11 Views