· 4 min read Posted by Kevin Galligan

Debugging Kotlin in Xcode with SPM Builds

Virtually all native mobile teams integrate Kotlin Multiplatform by publishing Xcode binaries, usually with SPM. This is generally easy to integrate, but prevented iOS developers from browsing or debugging Kotlin. Today we have fixed that situation.

Most native mobile teams start integrating KMP into their builds by publishing Xcode binaries using Swift Package Manager (SPM). This is such a common approach, we have built KMMBridge to streamline the process of implementing this workflow.

However, there are significant downsides to this approach. The most immediate and critical is that iOS developers cannot browse or debug the Kotlin code. Debugging is not possible because of how lldb in general, and the Kotlin compiler specifically, generate debugging info. Especially for teams who plan to scale their usage of KMP, this is such a big problem that our recommendation has been to share source code instead and build Kotlin locally.

Today, we have updated both SKIE and KMMBridge to support the ability to debug SPM builds locally, using the Xcode Kotlin plugin, without any need for locally compiling or configuring your KMP dependencies.

What’s Changed?

It was previously possible to add some build-time config to CI to override debug paths embedded by the Kotlin compiler, then locally remap those paths to point to a local copy of your KMP code. The detailed process of doing that is complex enough that you’d have a much easier time just building your code locally. We never went beyond the proof-of-concept phase.

SPM has an interesting design detail that simplified one part of this process. It uses git repos as the “unit” of a dependency. When you include an SPM dependency, the source code is pulled by SPM, and Xcode makes that source code available. You don’t need to clone it or add it separately.

SPM Folder with Kotlin Code

You can browse the Kotlin from here, and because SPM grabs a specific version of the dependency, the code should always reflect the dependency version you are using.

However, the lldb path issue prevented debugging this code.

Tadeas from our team applied some deep llvm/Apple-platform magic to the problem, and, well, the paths aren’t a problem anymore.

How To Use This?

You first need to install the Xcode Kotlin plugin, which allows you to debug Kotlin directly in Xcode. If you already use this plugin, there are no updates related to locally debugging binary builds. You’re good. The plugin has had significant performance and feature updates recently, though, so be sure to update to the latest if you haven’t already.

Second, the “magic” happens in SKIE. Add the following SKIE config to the KMP module that publishes your Xcode frameworks:

skie {
    build {
        produceDistributableFramework()
    }
}

You could configure path mappings directly to enable local debugging without SKIE, but using SKIE automates the process. We may in the future add some tooling to enable debugging for builds without SKIE, but we’d like to get feedback and address any possible issues first.

Third, if you are using KMMBridge to publish SPM, you need to make sure you are creating DEBUG builds. KMMBridge defaults to RELEASE builds. You will need to update your CI flow to enable DEBUG for dev builds and RELEASE for release builds.

Our KMMBridge SPM Quick Start tutorial and template repo have been updated to support local debugging. You can reference those for change details, or create a new shared KMP repo with debugging enabled by default.

These updates came together pretty fast. Some documentation for the KMMBridge 1.2.0 release is still in flight to reflect the relevant updates. All KMMBridge reference docs should be updated by early next week, but the SPM Quick Start has been updated and published.

Best-practice Implications

If the plan for your team is to involve iOS devs with Kotlin development directly, I still think it would be better to use Kotlin source code rather than published binaries. However, the argument that teams should start that way is no longer very compelling. One of the major reasons for our recommendation was the inability of iOS developers to see or debug Kotlin code. That ensured a significantly worse developer experience for the members of the team who were already suffering from multiple disadvantages.

With the ability to locally debug KMP code, starting with published binaries and SPM is also fine. Doing so removes a significant point of friction, and for teams who don’t plan on getting all iOS developers editing Kotlin, or not right away, being able to browse and debug the code without needing to build it locally is a much better option.

For teams who plan to scale KMP development, we’ll have some updates early next week. We have alternative development workflow models that should mitigate the mismatch between using versioned libraries for feature development. You should still plan on quickly figuring out how to use source code directly, but the updated workflow models will significantly improve the process of scaled KMP development with published binaries and SPM.

As always, feedback welcome. Find us on the Kotlin slack, hit the various contact options on this website, or join the conversation on Bluesky.

Comments

Reply on Bluesky here to join the conversation.

's avatar
@pablusconi.bsky.social
🔥🔥🔥
Kevin Galligan's avatar
Kevin Galligan@kpgalligan.bsky.social
Prior to this update, developers looking to debug Kotlin for iOS (and other Apple targets) needed to build KMP locally. Being able to debug published builds directly in Xcode helps reduce the significant disparity between the KMP developer experience for Android and iOS teams.
Kevin Galligan's avatar
Kevin Galligan@kpgalligan.bsky.social
Early next week, we'll have some other updates. See the post for more hints. Also, we've added Bluesky integration to the Touchlab website, so discussions here will show up on the blog post page! Well, after I post this, get the URL, then update the post on the website, but still. Pretty nice!