<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:cc="http://cyber.law.harvard.edu/rss/creativeCommonsRssModule.html">
    <channel>
        <title><![CDATA[Stories by Kevin Galligan on Medium]]></title>
        <description><![CDATA[Stories by Kevin Galligan on Medium]]></description>
        <link>https://medium.com/@kpgalligan?source=rss-c2f810aa7890------2</link>
        <image>
            <url>https://cdn-images-1.medium.com/fit/c/150/150/1*ZVMJXu5ws0K0ldRsABTglQ.jpeg</url>
            <title>Stories by Kevin Galligan on Medium</title>
            <link>https://medium.com/@kpgalligan?source=rss-c2f810aa7890------2</link>
        </image>
        <generator>Medium</generator>
        <lastBuildDate>Mon, 06 Apr 2026 18:06:21 GMT</lastBuildDate>
        <atom:link href="https://medium.com/@kpgalligan/feed" rel="self" type="application/rss+xml"/>
        <webMaster><![CDATA[yourfriends@medium.com]]></webMaster>
        <atom:link href="http://medium.superfeedr.com" rel="hub"/>
        <item>
            <title><![CDATA[TouchlabOpen Source Updates]]></title>
            <link>https://medium.com/@kpgalligan/touchlabopen-source-updates-13627e8a7afe?source=rss-c2f810aa7890------2</link>
            <guid isPermaLink="false">https://medium.com/p/13627e8a7afe</guid>
            <category><![CDATA[kotlin-multiplatform]]></category>
            <category><![CDATA[kotlin-native]]></category>
            <category><![CDATA[kotlin]]></category>
            <dc:creator><![CDATA[Kevin Galligan]]></dc:creator>
            <pubDate>Fri, 10 Mar 2023 00:00:59 GMT</pubDate>
            <atom:updated>2023-03-10T21:13:44.897Z</atom:updated>
            <content:encoded><![CDATA[<h3>Touchlab Open Source Updates</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/1000/0*5T40oKuJ9B3PH8y7.png" /></figure><p>We’ve been heads down for the last few months working on our new professional offerings: <a href="https://get.touchlab.co/skie-touchlab-pro/">SKIE and Touchlab Pro</a>. We’ll be posting about them soon. While that work has been the major focus, our open source projects have been mostly getting critical updates. As our new projects have been nearing release, we’ve finished a bunch of updates to our open source libraries.</p><h3><a href="https://kmmbridge.touchlab.co/">KMMBridge</a><a href="https://kgalligan.com/blog/2023/3/10/oss-updates#kmmbridge">​</a></h3><p>We’ve had a few tweaks and updates pending for some time. Those have been pushed with version <a href="https://github.com/touchlab/KMMBridge/releases/tag/0.3.7">0.3.7</a>.</p><p>One of the less visible but really important changes is a flag that disables a lot of the “stuff” that needs to happen when actually publishing versions. If you opened a project with earlier versions of KMMBridge on a dev machine, several things might happen in the background that really don’t need to. Now they won’t.</p><p>Also, if you happen to use S3 as your publish target, there’s a bug in the default AWS SDK. This version should fix that for you.</p><p>Finally, the website has been updated: <a href="https://kmmbridge.touchlab.co/">kmmbridge.touchlab.co</a></p><h3><a href="https://kermit.touchlab.co/">Kermit</a><a href="https://kgalligan.com/blog/2023/3/10/oss-updates#kermit">​</a></h3><p>Kermit’s API has gone through a fairly significant update. We’ve released <a href="https://github.com/touchlab/Kermit/releases/tag/2.0.0-RC3">2.0.0-RC3</a> with the new changes. Feedback is welcome.</p><h3>New API<a href="https://kgalligan.com/blog/2023/3/10/oss-updates#new-api">​</a></h3><p>1.x versions had a Logger API that was designed to be called from non-Kotlin environments. For the most part, that meant avoiding default parameters. However, the primary use case is calling from Kotlin. The primary Logger API was updated to be (mostly) source compatible, but now include simpler method definitions with default parameters.</p><p>In simple terms, that means all log calls can have message, a Throwable, and a tag specified.</p><p>For non-Kotlin environments such as Swift and JS, you can export kermit-simple, which provides extension methods to make calling less verbose from those environments (without default parameter support, you&#39;d need to provide each value on each call).</p><h3>Custom API<a href="https://kgalligan.com/blog/2023/3/10/oss-updates#custom-api">​</a></h3><p>We had a lot of feedback about Kermit’s API decisions since releasing it. Some has been incorporated, but some is really just personal preference. For example, full names instead of single letter methods for logging calls (info() instead of i()). You can&#39;t make everybody happy.</p><p>However, most of the functionality has been moved to the module kermit-core. The kemrit module is now fairly small, and just represents the public Logger API. That means you can add your own Logger API on top of the Kermit internals. See <a href="https://kermit.touchlab.co/docs/details/CUSTOM_API">Custom Logger API</a> for more detail.</p><h3>Website Update<a href="https://kgalligan.com/blog/2023/3/10/oss-updates#website-update">​</a></h3><p>And, of course, the website has been updated: <a href="https://kermit.touchlab.co/">kermit.touchlab.co</a></p><h3><a href="https://crashkios.touchlab.co/">CrashKiOS</a><a href="https://kgalligan.com/blog/2023/3/10/oss-updates#crashkios">​</a></h3><p>CrashKiOS has had an interesting history. The library allows Crashlytics and Bugsnag to report symbolicated Kotlin crash reports on iOS (and other Darwin/Apple targets). Most of this functionality was moved into Kermit as we had several requests to support Kermit integration.</p><h3>Changes<a href="https://kgalligan.com/blog/2023/3/10/oss-updates#changes">​</a></h3><p>However, crash reporting has other features unrelated to logging, such as custom key/value pairs, and automatically catching hard crashes. Also, <a href="https://github.com/rickclephas/NSExceptionKt">NSExceptionKt</a> tweaked the method being used for reporting hard crashes. This allows reports to be consolidated rather than the earlier dual report method.</p><p>The crash reporting details from Kermit have been moved back into CrashKiOS, and various parts of NSExceptionKt have been integrated, to support crash reporting as a standalone library again. Kermit&#39;s support has been simplified. You can add log writers for Crashlytics or Bugsnag, but they both delegate to CrashKiOS.</p><h3>New Website<a href="https://kgalligan.com/blog/2023/3/10/oss-updates#new-website">​</a></h3><p>Website also updated: <a href="https://crashkios.touchlab.co/">crashkios.touchlab.co</a></p><h3><a href="https://github.com/touchlab/Stately">Stately</a><a href="https://kgalligan.com/blog/2023/3/10/oss-updates#stately">​</a></h3><p>Stately was designed to help developers work with the original strict memory model of Kotlin/Native. That memory model has been deprecated. We’ve released <a href="https://github.com/touchlab/Stately/releases/tag/1.2.5">one last version of the original Stately</a> built on 1.8.0, for teams that aren’t ready to update everything and who would like to continue using Stately as it was in earlier Kotlin versions.</p><h3>What Now?<a href="https://kgalligan.com/blog/2023/3/10/oss-updates#what-now">​</a></h3><p>Since the strict memory model has been deprecated, Stately’s future has been up in the air. We internally still find some of the concurrency pieces useful, and with the new memory model, there are some utility classes we wanted to have available. It is likely that newer libraries will better handle these cases in the future, but we’ve added them to Stately for now.</p><p>stately-concurrency contains structures like locks and atomics. There is functionality similar to Atomic-Fu, and we may eventually deprecate this support in Stately, but for now we continue to use it in our projects.</p><p>stately-strict contains shared definitions of things like freeze(). This is only for use in projects that still have this code in their projects and don&#39;t want to remove it. Most projects will be running on the new memory model, and freeze() won&#39;t really do anything.</p><p>stately-concurrent-collections is a simple implementation of thread-safe collections. We anticipate somebody will eventually release something more robust, but for now, you can easily include this module to have shared collections in your project.</p><p>Stately did <em>not</em> get a website refresh. The future utility of Stately is up in the air, so we didn’t prioritize the website update.</p><h3>Documentation Sites<a href="https://kgalligan.com/blog/2023/3/10/oss-updates#documentation-sites">​</a></h3><p>We’ve moved several of our open source projects’ documentation to <a href="https://docusaurus.io/">Docusaurus</a>. I have been pretty skeptical of these kinds of site generators, but finally took a look at Docusaurus after several team members mentioned it as an option.</p><p>It is one of my favorite things now. I’ve even moved my personal site to Docusaurus, just for the blog.</p><p>There’s too much going on to explain <em>why</em> I love it, but some highlights (some Docusaurus-specific, some just neat hacks)</p><ul><li>Docusaurus let’s you create custom react components and use them directly in markdown, so we can extend the markdown syntax easily</li><li>Dark and light mode</li><li>Code style is highly customizable. Kotlin code has Intellij/Android Studio colors, while Swift looks like Xcode (see <a href="https://kermit.touchlab.co/docs/configuration/NON_KOTLIN">Kermit docs</a>)</li><li>Our doc build process auto-replaces version strings into code samples. This isn’t Dosusaurus specific, but a nice add on. The CI process gets the latest published release string and replaces a template string in the markdown. Anything in gradle.properties can be swapped as well.</li></ul><p>It’s easy to tweak and extend. It’s just great.</p><p>The home page of each doc site is now using a simple react template (from <a href="https://cruip.com/">cruip.com</a>). That uses tailwind CSS, which is the other new (to me) web thing I’m in love with now. Although there’s <a href="https://github.com/facebook/docusaurus/issues/2961">been discussion</a>, Docusaurus doesn’t have a tailwind theme, so the CSS is bit of a blended hack. Once you get started, though, its really easy to develop with it.</p><p><em>Originally published at </em><a href="https://touchlab.co/open-source-updates/">https://touchlab.co/open-source-updates/</a> <em>on March 10, 2023.</em></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=13627e8a7afe" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[The Evolution of Kotlin Multiplatform Mobile]]></title>
            <link>https://medium.com/@kpgalligan/the-evolution-of-kotlin-multiplatform-mobile-a185eeecccd1?source=rss-c2f810aa7890------2</link>
            <guid isPermaLink="false">https://medium.com/p/a185eeecccd1</guid>
            <category><![CDATA[kotlin-native]]></category>
            <category><![CDATA[kotlin-multiplatform]]></category>
            <category><![CDATA[kotlin]]></category>
            <dc:creator><![CDATA[Kevin Galligan]]></dc:creator>
            <pubDate>Tue, 01 Nov 2022 22:59:16 GMT</pubDate>
            <atom:updated>2022-11-01T22:59:16.040Z</atom:updated>
            <content:encoded><![CDATA[<p>If you’re just checking out KMM, or you’re curious to hear a bit about the history and where things may be headed, check out Russell Wolf’s post <a href="https://touchlab.co/the-evolution-of-kotlin-multiplatform-mobile/">The Evolution of Kotlin Multiplatform Mobile</a>.</p><p>The Touchlab team is working on working on tools for KMM. For teams getting started, check out KMMBridge</p><p><a href="https://github.com/touchlab/KMMBridge">GitHub - touchlab/KMMBridge: KMMBridge is a set of Gradle tooling that facilitates publishing and consuming pre-built KMM (Kotlin Multiplatform Mobile) Xcode Framework binaries. See https://touchlab.github.io/KMMBridge/intro/ to get started.</a></p><p>We have some new things in the works to improve the iOS dev experience, and some experiments a little further down the line for coordinated feature development. If you want to know more about what we’re working on, or maybe want some help building with KMM, reach out at <a href="https://kotlinlang.slack.com/archives/CTJB58X7X">#touchlab-tools</a> in the Kotlin lang slack, or directly at <a href="https://touchlab.co/contact-us/">touchlab.co</a>.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=a185eeecccd1" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Introducing KMMBridge for Teams]]></title>
            <link>https://medium.com/@kpgalligan/introducing-kmmbridge-for-teams-da825da42e81?source=rss-c2f810aa7890------2</link>
            <guid isPermaLink="false">https://medium.com/p/da825da42e81</guid>
            <category><![CDATA[kotlin-multiplatform]]></category>
            <category><![CDATA[kotlin]]></category>
            <category><![CDATA[kotlin-native]]></category>
            <dc:creator><![CDATA[Kevin Galligan]]></dc:creator>
            <pubDate>Mon, 10 Oct 2022 20:10:44 GMT</pubDate>
            <atom:updated>2022-10-25T20:35:42.884Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1000/1*oPk-YRHcwVYdGPooWpbsgg.png" /></figure><p><a href="https://touchlab.co/introducing-kmmbridge-teams/">Today we are announcing KMMBridge</a>, part of Touchlab’s new Faktory* tooling suite. This set of build tools allows mobile teams to successfully publish shared code faster than ever with Kotlin Multiplatform Mobile.</p><p>Specifically targeted at iOS publishing, teams can now implement the Internal SDK Flow approach, today’s best practice to quickly integrate KMM into production app builds.</p><p><a href="https://github.com/touchlab/KMMBridge">GitHub - touchlab/KMMBridge: KMMBridge is a set of Gradle tooling that facilitates publishing and consuming pre-built KMM (Kotlin Multiplatform Mobile) Xcode Framework binaries. See https://touchlab.github.io/KMMBridge/intro/ to get started.</a></p><blockquote><strong><em>KMMBridge allows teams to publish and integrate Kotlin Multiplatform Mobile (KMM) Xcode Frameworks as an internal SDK.</em></strong></blockquote><blockquote>When you’re ready to get started, head to our <a href="https://touchlab.co/quick-start-with-kmmbridge-1-hour-tutorial/">KMMBridge Quick Start Tutorial</a>.</blockquote><h3>Why We Built a Team-Focused Tool</h3><p>Touchlab has spent years working with teams at different stages of their Kotlin Multiplatform journey. Evaluating KMP, putting KMP into production, and yes, even a fair bit of time talking to teams who looked at KMP and decided against it. One of the key lessons we’ve learned seems obvious in retrospect.</p><blockquote><strong><em>Different types of teams work in different ways.</em></strong></blockquote><p>Of course, every team is different. Every situation will be different. However, there are common patterns.</p><p>Out of the box, the KMP and the Kotlin/Native toolkit will let you build an Xcode Framework, then integrate it locally into your Xcode project. This works well if everybody on the team builds Kotlin. And in an ideal world, everybody would be able to build Kotlin.</p><p>But in the real world, most teams who have succeeded followed the Internal SDK Flow approach.</p><h3>The Internal SDK Flow Approach</h3><p>As with adopting any technology on a team, early wins help build momentum and confidence so the team can unlock the full potential over time. The Internal SDK Flow has emerged as the best practice to get faster ROI when adopting KMM. At its simplest, this approach means the Kotlin Xcode Framework is pre-built and published as an internal SDK (a private module shared with your team) so iOS developers can include it without building Kotlin locally.</p><blockquote><strong><em>The Kotlin Xcode Framework is pre-built and published as an internal SDK</em></strong></blockquote><p>Somebody else (a team member, CI, etc.) builds the Kotlin Xcode Framework and publishes it somewhere internal. That Framework is then consumed by Xcode just like any other SDK. The iOS build workflow does not need to add Gradle or Kotlin and does not add to its build time or risk. Our build tools let teams build their way immediately, increasing efficiency and eliminating unnecessary complexity to get started.</p><p>For more context, see Nate Ebel’s talk from Droidcon NYC 2022: <a href="https://www.droidcon.com/2022/09/29/adopting-kotlin-multiplatform-in-brownfield-applications/">Adopting Kotlin Multiplatform in Brownfield Applications</a>. It’s a very good overview of the startup issues teams face.</p><h3>How KMMBridge Works</h3><p>KMMBridge is a set of Gradle tools that integrate with your Kotlin Multiplatform Mobile project to assist with building and publishing KMM Xcode Frameworks. It is built for the Internal SDK Flow, but you can also use it to publish public SDKs as well.</p><p>The basic flow is as follows:</p><ol><li>Edit and test your shared Kotlin code, then push to your source control repo</li><li>Kick off a CI build with KMMBridge. It packages, versions, and publishes your Xcode Framework</li><li>Tell Xcode to update to the new version</li></ol><blockquote><em>The iOS build workflow does not need to add Gradle or Kotlin and does not add to its build time or risk</em></blockquote><figure><img alt="" src="https://cdn-images-1.medium.com/max/1000/0*QZ1A4oHap2RnA45Q.png" /></figure><p>For iOS devs, there is no need to install or learn anything new. KMMBridge supports Cocoapods and Swift Package Manager. It can publish to a few different back ends out of the box, including Github Releases, with more support coming soon.</p><h3>Why Use This Approach?</h3><p>As a leader or a member of a mid-sized-plus mobile team, does any of this sound familiar?</p><ul><li>Most of the Android devs don’t know much about iOS builds</li><li>Most of the iOS devs have never touched Gradle**</li><li>The apps are in separate repos or at least have very different build workflows</li></ul><blockquote><strong><em>Every team that Touchlab has worked with, that has successfully added KMP to their existing iOS app, has started with an internal SDK flow.</em></strong></blockquote><p>Some teams have relatively sophisticated internal module-sharing systems, Artifactory or similar. Most (and you’d be surprised at who) have nothing like that. Even with some kind of artifact sharing in place, there is a lot of custom work that would need to be done to wire up Kotlin Xcode Frameworks to be included into a production iOS build.</p><p>KMMBridge will help most teams speed past this and get started productively with KMM.</p><h3>What Comes After the Internal SDK Flow?</h3><p>What is the next step when you want to scale and get shared code closer to your feature dev flow?</p><p>It can seem simple on the surface but this can get tricky, depending on team structure and how features are developed. One example we’ve seen a bit of: over time both teams could start to edit the code as if it wasn’t shared, and without clear guidance those edits can start to conflict in multiple ways.</p><p>Most teams with Kotlin Multiplatform Mobile in production have used one or more Touchlab solutions. If you are looking to scale your KMM dev (or have already done so), <a href="https://touchlab.co/contact-us">we should chat</a>.</p><p><em>*There is more to the Faktory tooling that is in the works, but we decided to carve out this bit now as it is a necessary entry point for teams adopting KMM. As KMM enters Beta, for continued growth and adoption, there are core capabilities that simply need to exist, and the internal SDK flow is one of them.</em></p><p><em>**Most Android devs try to avoid it, me included (no offense Gradle)</em></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=da825da42e81" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Kermit and Crashlytics]]></title>
            <link>https://medium.com/@kpgalligan/kermit-and-crashlytics-27d7bc953576?source=rss-c2f810aa7890------2</link>
            <guid isPermaLink="false">https://medium.com/p/27d7bc953576</guid>
            <category><![CDATA[kotlin-native]]></category>
            <category><![CDATA[kotlin]]></category>
            <category><![CDATA[kotlin-multiplatform]]></category>
            <dc:creator><![CDATA[Kevin Galligan]]></dc:creator>
            <pubDate>Wed, 05 Jan 2022 19:59:46 GMT</pubDate>
            <atom:updated>2022-01-05T19:59:46.081Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*I70EU89B1VNnbsG7awQN5w.jpeg" /></figure><blockquote>Cross post from <a href="https://touchlab.co/kermit-and-crashlytics/">https://touchlab.co/kermit-and-crashlytics/</a></blockquote><p><a href="https://github.com/touchlab/Kermit">Kermit</a> is a Kotlin Multiplatform logging library. The log is configured on each platform to write to various, potentially platform-specific, outputs, but can be called from shared “common” Kotlin code.</p><p>Crash reporting tools like Crashlytics allow you to get error reports from remote devices running your software. These tools are very common in mobile app development, and in most cases are critical for monitoring application health in production.</p><p>Crash reporting for KMP involves a setup similar to other platform-specific libraries that you want to use in a KMP context. You configure each platform according to the documentation from the software vendor, then have some common Kotlin code that can interact with the platform-specific library.</p><p>Crash reporting is a bit of a special case for iOS. <a href="https://www.kgalligan.com/crash-reporting-and-kmp/">It’s a long story</a>, but the summary is the JVM and Kotlin throw unchecked exceptions up the stack, and if unhandled, eventually wind up in a catch-all handler. On iOS, exceptions don’t work the same way. When a crash happens the runtime essentially stops and a handler is called. The crash library gathers the state of each thread&#39;s stack and sends that to the server.</p><p>If you call a Kotlin function on iOS and an exception is thrown from somewhere in that Kotlin call stack, the Kotlin runtime will bubble the exception up the stack like it would on the JVM. At the “border”, where you first called the Kotlin code, the Kotlin runtime will trigger a crash. If you look at the crash reports you’ll see konan::abort() . That’s the Kotlin runtime (internally called “konan”) force-killing the process.</p><p>That “works”, and if you don’t need symbolicated Kotlin crash info, then you’re done! However, all of the crash reports will lose potentially vital info. Specifically the Kotlin stack and the exception message.</p><p>To get that info, we register an uncaught exception handler with the Kotlin runtime, and when a crash originates in Kotlin code, a custom handled error is sent with the Kotlin stack info and exception message.</p><p>The only major negative here is that each crash will result in 2 separate reports for the same event. One fatal crash that ends with konan::abort() and a non-fatal report with the Kotlin stack and message. There is no way to send a custom fatal crash report, and no way to modify the fatal crash, so we wind up with 2. Hopefully, as KMP becomes more popular, vendors will add direct support for Kotlin. Alternatively, <a href="https://github.com/firebase/firebase-ios-sdk">the Crashlytics client is open source</a>, so maybe somebody from the community wants to give it a shot?</p><h3>Setup</h3><p>First let’s get the dependencies squared away.<em> </em>You can see sample code here:</p><p><a href="https://github.com/touchlab/Kermit/tree/main/samples/sample-crashlytics">Kermit/samples/sample-crashlytics at main · touchlab/Kermit</a></p><p>Add the Kermit dependencies to the common source set.</p><pre>implementation(&quot;co.touchlab:kermit:1.0.3&quot;)<br>implementation(&quot;co.touchlab:kermit-crashlytics:1.0.3&quot;)</pre><blockquote>Just FYI, if you’ll be exporting Kermit to iOS, you’ll need to use api instead of implementation.</blockquote><p>You should add CrashlyticsLogWriter to the Logger config. You can do that with a static logger instance, or add it to the global logger:</p><pre>Logger.addLogWriter(CrashlyticsLogWriter())</pre><p>The log writer adds log statements to the Crashlytics client, so when you send a crash report, you’ll see those statements in the report. You can configure the minimum severity, the minimum <em>crash</em> severity, and whether tags are included in the log statement. By default, the minimum severity is INFO, the minimum crash severity is WARN, and tags are included.</p><p>The minimum severity is the log level that will get logged to Crashlytics. The default again is INFO, so DEBUG statements won’t be sent to Crashlyics, unless you alter the default configuration.</p><p>The minimum <em>crash</em> severity is the minimum log severity that will trigger a handled exception being sent to Crashlytics. By default, it is set to WARN, which means that exception log statements of WARN, ERROR, and ASSERT create handled exceptions in Crashlytics.</p><pre>val ex = SomeException()<br>Logger.e(ex) { &quot;We have a problem...&quot; }</pre><p>If you want to log exceptions but not have them create Crashlytics exceptions, make sure to keep them below the minimum.</p><pre>val ex = NotImportantException()<br>Logger.i(ex) { &quot;We have a problem...&quot; }</pre><h3>iOS Crash Handler</h3><p>On iOS, to capture Kotlin crashes, we need a little extra setup. Kermit defines a convenience function to set up the default handler.</p><pre><em>setupCrashlyticsExceptionHook</em>(Logger)</pre><p>Call that function and pass in a logger instance (in this case, I passed in the global Logger ). <strong>This function is only defined for iOS!!!</strong> You should <a href="https://github.com/touchlab/Kermit/blob/873d862153a61706bc357871733411e33653d372/samples/sample-crashlytics/shared/src/iosMain/kotlin/co/touchlab/kermitsample/Helper.kt#L18">define a function in your iOS source set</a> and <a href="https://github.com/touchlab/Kermit/blob/097cd8ddd77af16374ff1833449ac964e6e5b620/samples/sample-crashlytics/ios/ios/AppDelegate.swift#L18">call it on app start</a> (from Swift/Objc).</p><p>When a crash happens in Kotlin code and bubbles up to Swift/Objc, Kermit will now send a handled report to Crashlytics before allowing execution to continue and the app to crash.</p><h3>Configuration Notes</h3><p>Kermit Crashlytics integration on iOS uses cinterop to talk to the native client. Crashlytics itself needs to be added and linked in your build. The details of how you add and link binary on iOS are a little beyond the scope of this post, but be aware that simply adding the kermit-crashlytics dependency won’t include the iOS Crashlytics SDK.</p><p>You have 2 basic choices of framework type: static and dynamic. We tend to use static in our builds, but you can use either.</p><h4>Static</h4><p>Static is somewhat easier. You only need to link to the Crashlytics binary when actually building your iOS app, or when running Kotlin tests (and in that case, only if you actually use CrashlyticsLogWriter in your tests, which wouldn’t really make sense).</p><p>If your tests are not building because the linker can’t find Crashlytics, you can <a href="https://github.com/touchlab/Kermit/blob/525764206c3bb3d4b164fdcd9a5bd6bafc5f7aef/samples/sample-crashlytics/shared/build.gradle.kts#L56">add our stub dependency</a>. It won’t work if you try to use it, but it will satisfy the linker.</p><pre>dependencies <strong>{<br>    </strong>implementation(&quot;co.touchlab:kermit-crashlytics-test:1.0.3&quot;)<br><strong>}</strong></pre><p>You’ll still need to add Crashlytics to your iOS project, but you can do that with Cocoapods or SPM.</p><h4>Dynamic</h4><p>Dynamic frameworks are a little more complicated. The Crashlytics binary needs to be available at compile time. <a href="https://github.com/touchlab/Kermit/blob/525764206c3bb3d4b164fdcd9a5bd6bafc5f7aef/samples/sample-crashlytics/shared/build.gradle.kts#L74">It is relatively easy to do this with Cocoapods</a>.</p><pre>cocoapods {<br>    //Other config<br>    framework {<br>        isStatic = false<br>    }<br>    pod(&quot;FirebaseCrashlytics&quot;)<br>}</pre><p>However, that will cause Kotlin to generate a whole different cinterop definition for Crashlytics. That’s not a huge technical problem, but since we don’t use it, it’s a waste. On our near-term todo list is adding a way to use cocoapods as strictly a dependency integrator with the ability to disable things like the cinterop, but for now, you’ll need to live with the imperfections (or wire up Crashlytics yourself).</p><p>I should mention, it is also possible to use pod(“FirebaseCrashlytics”) for static frameworks rather than our test stubs, but that will also generate the extra cinterop code.</p><h3>Usage</h3><p>Log messages above the minimum severity will be sent to the Crashlytics log. If a log call includes an exception and is at or above the minimum exception severity, that call will trigger a handled error report with Crashlytics.</p><p>For hard crashes on iOS, as mentioned, you will get 2 reports. One “fatal” one “non-fatal”. The non-fatal one has the extra Kotlin stack and info, and you’ll want to be able to navigate between them. To do that, the crash handler generates a random id and adds it to Crashlytics key/value pairs. You can search for matching reports with that key.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*NhI14txqHjhNeKV48r1kPw.png" /><figcaption>Find the crash key</figcaption></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*dGpVxr7Px85z_RkL-dg86w.gif" /><figcaption>Search for matching reports</figcaption></figure><p>Again, not ideal, but functional. When you get a chance, tweet at the various vendors to let them know you really want first-party KMP crash reporting support. For now, you need to search to find associated reports.</p><p>Assuming you have your project set up correctly, you should start to see symbolicated crash reports for Kotlin on iOS. Correctly configuring Crashlytics can sometimes be fairly difficult, so make sure to test that your reports are being sent to the Crashlytics back end and that your debug/dsym info is getting there.</p><p>If your stack traces look like this, the server doesn’t have some debug info.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/615/1*qJQ2_rT1OE9sO30Ufgxagw.png" /><figcaption>Missing dsyms?</figcaption></figure><p>The Kotlin stack trace should look more like this, with Kotlin source line numbers.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/611/1*SiiVM8l8UMsZrjx564Qjbg.png" /><figcaption>Same exception, with debug info.</figcaption></figure><p>The Kotlin/Native compiler generates a “standard” Xcode framework, so you shouldn’t need any custom configuration to get debug info uploaded. It is one of those things that can be difficult to configure correctly, Kotlin or no Kotlin, and you don’t want to have a production problem and no way to see what’s happening, so just make sure it’s working as expected!</p><h3>Hiring!</h3><p>We’re looking for people to join the KMP team. If you’re interested in the tech, Touchlab is a great place to build your experience.</p><p><a href="https://touchlab.co/careers-3/">Careers at Touchlab - Open positions &amp; apply here | Touchlab</a></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=27d7bc953576" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[KMM Memory Model — when to switch?]]></title>
            <link>https://medium.com/@kpgalligan/kmm-memory-model-when-to-switch-b1bc39867a75?source=rss-c2f810aa7890------2</link>
            <guid isPermaLink="false">https://medium.com/p/b1bc39867a75</guid>
            <category><![CDATA[kotlin]]></category>
            <category><![CDATA[kotlin-multiplatform]]></category>
            <category><![CDATA[kotlin-native]]></category>
            <dc:creator><![CDATA[Kevin Galligan]]></dc:creator>
            <pubDate>Thu, 23 Dec 2021 19:34:40 GMT</pubDate>
            <atom:updated>2021-12-23T19:35:11.864Z</atom:updated>
            <content:encoded><![CDATA[<h3>KMM Memory Model — when to switch?</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/400/1*1HGSLLnCZFlBpLYo2C3_1g.png" /><figcaption>Brain. It’s a brain.</figcaption></figure><blockquote>Cross posted from <a href="https://touchlab.co/kmm-memory-model-when-to-switch/">https://touchlab.co/kmm-memory-model-when-to-switch/</a></blockquote><p>Touchlab will be defaulting to the “new” memory model for anything that’s in dev and/or not hitting production for a few months. That decision will be reviewed if there’s some wild performance issue or bug, but otherwise, we’re just doing it. On Slack, the team collectively decided to make the switch this afternoon.</p><p>Why now? Well, the urgency this morning was <a href="https://github.com/Kotlin/kotlinx.coroutines/issues/462#issuecomment-999557659">largely driven by this</a>.</p><blockquote>1.6.x will be the last series of native-mt releases and we are effectively decommissioning native-mt in the favour of the new memory model that is supported out-of-the-box in 1.6.0 coroutines release.</blockquote><blockquote>…</blockquote><blockquote>We encourage developers to try out and evaluate the new MM: that’s our bet, we are investing our resources, development and testing in it and <strong>the quality of regular coroutine releases</strong> (including pre-release testing, a priority of the bug-fixes, extensive support of existing features and so on) <strong>is much higher than of native-mt builds</strong>.</blockquote><p>The general vibe is to wait until it’s not “experimental”, but if you’ve been working with KMP and Kotlin/Native for any length of time, you’re probably used to “experimental”. If you wait for something resembling “Beta”, the rest of the community will probably have switched long before you did. Such is the life of an early adopter. Also, assuming the new model works “good enough”, more people using it will speed up maturity through feedback.</p><p>That’s for client/app work. There are some decisions we (Touchlab), and other library maintainers, need to make around library decisions.</p><p>Large portions of <a href="https://github.com/touchlab/Stately">Stately</a>, if not all of it, will probably be archived (<a href="https://github.com/touchlab/Stately/discussions/75">discuss</a>). However, we’ll also need at least an OK implementation of concurrent collections. Next, while <a href="https://github.com/Kotlin/kotlinx.atomicfu">Atomic-FU</a> covers a lot of what we’d want for concurrency primitives (atomics, locks, etc), we’ll need a review to see if we want to completely switch over. Stately may continue on as a “simpler” version of some of what Atomic-FU does, or maybe we just need better Atomic-FU samples? TBD.</p><p><a href="https://github.com/InsertKoinIO/koin">Koin</a> has a very special Kotlin/Native implementation that forces you to inject on the main thread. I actually implemented that, trying to do it in a way that cooperated with the strict memory model. That all needs to be unwound for sure, and function pretty much the way the JVM version does.</p><p>If there’s anything else in the library space you think needs a review, reach out. Most libraries will at least need to start testing on the new model. The big concerns I have are: 1) code that explicitly freezes, or 2) code that relies on the strict model to enforce its safe concurrency. Number 1 is more of an immediate problem, as there are a number of libraries that likely do this in code. You may run into it, but it’s not “risky” in the sense that you’ll just crash but you’ll know it, and nothing “wrong” will happen. Number 2 will be an edge case for sure, but part of the point of the strict model was that you could make assumptions that are no longer true, and you don’t really know what assumptions the author made (certainly the runtime won’t). This is, I think, far less likely of a problem, but it kind of gets at the core of what the strict memory model tried to “fix”. Don’t lose sleep over it, but keep an eye out!</p><p>If you are super interested in this kind of stuff, well, <a href="https://touchlab.co/about-us/">we are hiring</a> of course :)</p><p><a href="https://touchlab.co/careers-3/">Careers at Touchlab - Open positions &amp; apply here | Touchlab</a></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=b1bc39867a75" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Kermit KMP Logging 1.0]]></title>
            <link>https://medium.com/@kpgalligan/kermit-kmp-logging-1-0-196bf799b738?source=rss-c2f810aa7890------2</link>
            <guid isPermaLink="false">https://medium.com/p/196bf799b738</guid>
            <category><![CDATA[kotlin]]></category>
            <category><![CDATA[kotlin-multiplatform]]></category>
            <category><![CDATA[kotlin-native]]></category>
            <dc:creator><![CDATA[Kevin Galligan]]></dc:creator>
            <pubDate>Thu, 09 Dec 2021 18:11:15 GMT</pubDate>
            <atom:updated>2021-12-09T18:11:15.771Z</atom:updated>
            <content:encoded><![CDATA[<blockquote>Cross post from <a href="https://touchlab.co/kermit-kmp-logging-1-0/">https://touchlab.co/kermit-kmp-logging-1-0/</a></blockquote><figure><img alt="" src="https://cdn-images-1.medium.com/max/852/1*cEeKOokBqRIRXqfIAeNVnQ.png" /><figcaption>Kermit the Log. That’s where the name came from.</figcaption></figure><p>Today we’re announcing the stable release of our logging library Kermit</p><p><a href="https://github.com/touchlab/Kermit">GitHub - touchlab/Kermit: Kermit by Touchlab is a Kotlin Multiplatform centralized logging utility.</a></p><p>If you’ve been following me, I’ve given a <a href="https://www.droidcon.com/media-detail?video=380843862">few talks on Kotlin KMP library development</a>. In my previous talks I gave some suggestions on what kinds of libraries the community needs. I went out of my way to say avoid building logging libraries. Even way back in 2019, there were already a few options for KMP, so I assumed that topic was handled.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*EnvoJ4uiV_NJ-ff-C0WAzg.jpeg" /><figcaption><em>Don’t build logging libraries</em></figcaption></figure><p>After doing some digging, though, nothing really felt like it was done the way we wanted. Also, in early 2020, due in part due to circumstances we’re all aware of, we had a few more hands available than planned. We had wanted everybody on the team to get a chance to work on a KMP library, and logging libraries are, if nothing else, conceptually straightforward. After some general architecture chats, the team dove in and made a dev version of Kermit.</p><p>The plan was to try it out, get some feedback, then make a 1.0 and tell everybody!</p><p>Then we got super busy.</p><p>The good news is we got some extra time to think about the library design, and a lot more feedback than you’d think for something we never quite announced.</p><p>With that feedback, plus more lessons learned shipping KMP code in the meantime, we sat down and made a plan for Kermit 1.0.</p><h4>Kermit 1.0</h4><p>Kermit has a simple API, is easy to extend, and is focused on performance. Getting started is very easy, but Kermit provides more sophisticated configuration as you move beyond dev into releasing your applications.</p><p>Rather than a single long post that I’ll never finish, we’ll wrap this up with basic setup, then go deep on a few other topics in future posts. The list is subject to change, but look for posts on basic setup and usage, production setup, crash reporting integration, and a deep dive on the performance considerations that went into the design.</p><blockquote><strong>Note: Kotlin 1.6.0 publishing issues</strong></blockquote><blockquote>To clarify some confusion around releases, we originally published 1.0.0 for Kotlin 1.5.31, then this post got delayed a bit. When Kotlin 1.6.0 came out, we ran into some Kotlin/Native stuff that needed fixing, but ultimately pushed Kermit 1.0.2 with Kotlin 1.6.0. However, it turns out <a href="https://twitter.com/kotlin/status/1463129142627553289">Kotlin 1.6.0 has Android publishing issues</a>, so please use Kermit 1.0.0 until Kotlin 1.6.10 releases, which <a href="https://youtrack.jetbrains.com/issue/KTIJ-20305">should be in a couple weeks</a>.</blockquote><h4>Getting Started</h4><p>In your Kotlin Gradle config, add the Kermit dependency in `commonMain`.</p><pre>commonMain {<br>  dependencies {<br>    implementation(&quot;co.touchlab:kermit:1.0.0&quot;)<br>  }<br>}</pre><p>Without any other configuration, you can use the global Logger with default log writers per platform. For Android, it writes to android.util.Log, iOS logs are written with println, and JS goes to console.</p><p>For iOS we replicated a good idea from <a href="https://github.com/AAkira/Napier#darwinios-macos-watchos-tvosintelapple-silicon">Napier</a>. <a href="https://github.com/touchlab/Kermit/issues/183">Color coding the iOS logs</a>. Format is slightly different, but same concept.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/448/1*ahQeR1mp_VK5IDgf6j9v3Q.png" /><figcaption>iOS Color Coded Output</figcaption></figure><p>To write logs with the global logger, just do this:</p><pre>Logger.i { &quot;Hello&quot; }</pre><p>The log calls are lambdas, which will allow us to avoid creating strings if they’re not needed, but you can also call “regular” methods with a string.</p><p>To log an exception:</p><pre>catch(ex:Exception){<br>  Logger.e(ex) { &quot;Something happened&quot; }<br>}</pre><p>To change tags, do this:</p><pre>val l = Logger.withTag(&quot;DifferentTag&quot;)<br>l.i { &quot;New logger, new tag&quot; }</pre><p>That’s it for today. Again, keep an eye out for other posts about Kermit. Please share feedback, star the Github repo if you like it.</p><h3>Work at Touchlab!</h3><p>We’re hiring! If you want to help define the future of Kotlin, and like living a bit on the edge technically speaking, please reach out!</p><p><a href="https://touchlab.co/careers-3/">Careers at Touchlab - Open positions &amp; apply here | Touchlab</a></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=196bf799b738" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Testing the Kotlin Native memory model]]></title>
            <link>https://medium.com/@kpgalligan/testing-the-kotlin-native-memory-model-d3ccd2c2810f?source=rss-c2f810aa7890------2</link>
            <guid isPermaLink="false">https://medium.com/p/d3ccd2c2810f</guid>
            <category><![CDATA[kotlin-native]]></category>
            <category><![CDATA[kotlin]]></category>
            <category><![CDATA[kotlin-multiplatform]]></category>
            <dc:creator><![CDATA[Kevin Galligan]]></dc:creator>
            <pubDate>Sun, 03 Oct 2021 16:35:56 GMT</pubDate>
            <atom:updated>2021-10-03T16:35:56.237Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*Ifp8kjcvHFsm1csdUWYl7A.jpeg" /><figcaption>Memory joke</figcaption></figure><p>Kotlin/Native’s strict memory model has been a common topic of interest and/or concern in the community for some time. The arrival of the new memory model will remove what many consider an adoption blocker. However, creating and testing a new memory model is a significant undertaking.</p><p>It is tempting to wait until the new memory model is “ready”, but the community can help accelerate the maturing of the platform by <a href="https://blog.jetbrains.com/kotlin/2021/08/try-the-new-kotlin-native-memory-manager-development-preview/">testing the new model and reporting bugs</a>.</p><p>We are starting to run our open source library tests against the new memory model. Just turning it on for Kermit found a <a href="https://youtrack.jetbrains.com/issue/KT-49059">relatively minor issue</a>. If you publish a library, it would be great if you could turn on the new memory model and see if things work. Although everybody’s config is different, here’s how we do it.</p><p>Kermit’s Kotlin version is in the gradle.properties file.</p><pre>GROUP=co.touchlab<br>VERSION_NAME=1.0.0-rc4<br>KOTLIN_VERSION=1.5.31<br># etc...</pre><p><a href="https://github.com/touchlab/Kermit/blob/main/gradle.properties#L18">Kermit/gradle.properties at main · touchlab/Kermit</a></p><p>That makes turning on the memory model simple. We can pass in a different Kotlin version and memory model flag, both as gradle properties.</p><p>Currently we run tests 3 times. First with Kotlin 1.5.31, which is our published version. Then Kotlin 1.6.0-M1, but with the strict memory model, then Kotlin 1.6.0-M1 and the new memory model. In the <a href="https://github.com/touchlab/Kermit/blob/kpg/new_memory_model/.github/workflows/build.yml#L38">Github Actions script</a>, here are the lines:</p><pre>- name: Build<br>  run: ./gradlew build --no-daemon --stacktrace<br>- name: Build 1.6<br>  run: ./gradlew build -PKOTLIN_VERSION=1.6.0-M1 --no-daemon --stacktrace<br>- name: Build 1.6 nmm<br>  run: ./gradlew build -PKOTLIN_VERSION=1.6.0-M1 \<br>-Pkotlin.native.binary.memoryModel=experimental --no-daemon \<br>--stacktrace</pre><p>Param -PKOTLIN_VERSION=1.6.0-M1 sets the Kotlin verison, and -Pkotlin.native.binary.memoryModel=experimental turns on the new memory model.</p><p>Also FYI, macos-latest is a little old and has Xcode 12.4. macos-11 has Xcode 12.5, which is required for Kotlin 1.6.0-M1.</p><p>Obviously, if you run those once and they work fine, you don’t need to leave them on. We found a minor issue with Kermit, linked above, and I assume it’ll get fixed, or we can just tweak our implementation. I don’t think we’re going to merge the build script changes above. However, once 1.6.0 is live, I think we’ll probably run both memory models for a while.</p><p>If you find an issue, I’ve created a simple sample project template.</p><p><a href="https://github.com/touchlab-lab/kn-nmm-test">GitHub - touchlab-lab/kn-nmm-test: Kotlin/Native New Memory Model Test</a></p><p>The project is fairly minimal. Put your failing example in a test. To run code in another thread, call “ThreadHelper.doInBackgroundUnfrozen”. Obviously as the new model matures, the focus will shift more to performance issues than hard “bugs”, but at this point I would expect to see actual bugs here and there.</p><p>Ping me in the Kotlin slack or <a href="https://twitter.com/kpgalligan">on twitter</a> if you’re having issues setting up tests!</p><p>When submitting bugs, make sure to select Kotlin as the project. I did it wrong at first. Just FYI.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=d3ccd2c2810f" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Kotlin 1.5.30 and KMM/KMP]]></title>
            <link>https://medium.com/@kpgalligan/kotlin-1-5-30-and-kmm-kmp-2ba19af65fe7?source=rss-c2f810aa7890------2</link>
            <guid isPermaLink="false">https://medium.com/p/2ba19af65fe7</guid>
            <category><![CDATA[kotlin]]></category>
            <category><![CDATA[kotlin-multiplatform]]></category>
            <category><![CDATA[kotlin-native]]></category>
            <dc:creator><![CDATA[Kevin Galligan]]></dc:creator>
            <pubDate>Fri, 27 Aug 2021 16:15:39 GMT</pubDate>
            <atom:updated>2021-08-27T16:28:04.643Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*DFBq1PvJ4lqTzJu2z0VpaQ.jpeg" /></figure><p>Kotlin 1.5.30 officially launched just now. There has been a steady stream of Kotlin releases over the last year or so, each with new features and fixes.</p><p>In other words, business as usual.</p><p>Since we (Touchlab) are plugging away, day in and out, working on client projects using KMM🐶, it can be easy to lose track of the bigger milestones. Kotlin 1.5.30 feels (numerically speaking) like just another point release, but this is a milestone advance for the platform. 1.5.30 presents a few big features, at least in preview, which will ultimately pave the way for “production ready” mainstream adoption of Kotlin shared code technology.</p><blockquote>Kotlin 1.5.30 is a turning point in KMP. Here’s why.</blockquote><h4>Memory Model Preview</h4><p>One of the most controversial aspects of Kotlin/Native is the concurrency and memory model. There are a lot of takes on it. Whether it was a good or bad thing, and why, is beyond the scope of today’s post. However, I talked about it much more than anything else over the last few years because for KMM and KMP to grow, people would need to understand it. Still, it’s been a significant blocker for some. That will be changing soon. I would not run the new memory model in production yet 🤞, but you can start experimenting with it now, and expect production deployments to pop up as we settle into 1.6 (I’m guessing :) 🚀.</p><p>What is this memory model business you ask? Well, in some languages (Java, Swift, etc), multiple threads can read and write shared state. There are a number of ways in which that can be dangerous and error prone. Many languages don’t let you access state from multiple threads (JS), some even have memory restriction rules built into the language and compiler (Rust). Kotlin/Native introduced a <a href="https://dev.to/touchlab/practical-kotlin-native-concurrency-ac7">relatively unique model</a>. In concept, it’s interesting, but in practice, it can be confusing and a barrier to adoption.</p><p>The new memory model will presumably allow unrestricted shared access to state. There are outstanding questions. Will there be equivalents to the JVM concurrency features (synchronized, etc)? If you write a library that needs the new memory model, will you get an error compiling with the freeze model? That kind of thing, but I’m sure these will be resolved in time.</p><blockquote>Check out Russell’s <a href="https://dev.to/touchlab/trying-out-the-experimental-new-kotlin-native-memory-model-235k">quick look at the memory model preview</a></blockquote><p>What will those changes mean to your code, and what should you do <strong><em>today</em></strong>? For the next 6 months at least, you’ll need a working understanding of the current model, and <strong><em>your</em></strong> code probably won’t change at all when you switch on the new model. It’s relaxing the rules more than changing them. <a href="https://dev.to/touchlab/kotlin-native-concurrency-changes-p3e">My thoughts from mid-2020</a>.</p><h4>Compile-time Code Analysis</h4><p>Compiler plugins have been maturing over time, as have the IR compilers for JVM and JS. That maturation isn’t exactly tied to 1.5.30, but KSP support for Kotlin Native and KMP in general is being added, with K/N support <a href="https://github.com/google/ksp/pull/541">added a few weeks ago</a>.</p><p>Kotlin Native is quite static at runtime, so any sort of significant code analysis and manipulation needs to be done at compile time. Because there was no real “annotation processor” equivalent, there are a number of libraries that can’t really be built in the same way that they have been for Android. Things like Dagger are only possible with compiler plugins. Any real mocking will need code transformation. Also, generating Swift code to make integration easier needs stable (and reasonably documented) compile-time code analysis. 1.5.30 doesn’t suddenly turn all of these things on, but the maturity of the plugins, the addition of KSP, and the mutliplatform IR compiler becoming the default will greatly accelerate areas of library development that were significantly more difficult with earlier versions.</p><h4>Hierarchical Modules/Source Sets</h4><p>I would say this falls under the general header of maturing and stabilizing tools, but very specifically, the <a href="https://kotlinlang.org/docs/mpp-share-on-platforms.html#use-target-shortcuts">Hierarchical MPP</a>. Especially in native, there can be many targets with very similar dependency api’s, but configuring the IDE and compiler to recognize them has not been fully functional. It has worked OK for simpler situations like ios(), but for libraries with nested hierarchies and many targets, publishing HMPP-enabled libraries hasn’t really been an option.</p><p>With Kotlin 1.5.30, that has been (mostly?) fixed! With <a href="https://github.com/touchlab/TestHelp/pull/11">gentle nudging</a> from @sellmair, we’ve figured out how to correctly configure relatively complex library modules. Over the next few days we’ll be publishing HMPP library versions. Currently published:</p><ul><li>TestHelp: <a href="https://github.com/touchlab/TestHelp/releases/tag/0.5.5">0.5.5</a></li><li>Sqliter: <a href="https://github.com/touchlab/SQLiter/releases/tag/1.0.9">1.0.9</a></li><li>Stately: <a href="https://github.com/touchlab/Stately/releases/tag/1.1.10">1.1.10</a></li></ul><p><a href="https://github.com/cashapp/sqldelight/pull/2548">SQLDelight HMPP</a> and <a href="https://github.com/cashapp/sqldelight/pull/2549">M1 Mac Arm support</a> is merged and hopefully launching soon. Possibly Koin and others, although I haven’t checked in for a while…</p><p>Our logging library, <a href="https://github.com/touchlab/Kermit">Kermit</a>, is getting HMPP-related changes, but is also going through a fairly significant overhaul focused on performance and features. You can try a preview version <a href="https://github.com/touchlab/Kermit/releases/tag/0.3.0-m1">0.3.0-m1</a>. The api itself has changed somewhat, but should be compatible for most uses.</p><p><strong><em>Also…</em></strong></p><p><a href="https://github.com/touchlab/Kermit/pull/114">M1 architectures are a welcome addition</a>. All of the libraries mentioned above have mac arm architecture targets published.</p><p>There’s <a href="https://kotlinlang.org/docs/whatsnew1530.html#support-for-xcframeworks">direct support for XCFramework</a>. We’ve spent a fair bit of time helping clients integrate KMM into their production build and CI environments, and demand for Swift Package Manager is significant. Streamlining XCFramework is critical for that. We’ve had some productivity issues using various external solutions and have started experimenting internally. Hopefully direct support will improve that situation.</p><h3>Touchlab?</h3><p>The only work we do now that isn’t KMP is for projects we’ve had for years. We are all-in on the tech, and <a href="https://touchlab.co/careers-3/">hiring</a>. If you want to jump into KMP with both feet, think about coming to work with us.</p><p>I am <em>also</em> interested in talking to Dev Rel people. We’re not quite hiring for that yet, but looking into it. Would love to get some feedback on what we’re thinking. Please <a href="https://twitter.com/kpgalligan/status/1428711560516603907?s=20">DM me</a> if you’d like to chat.</p><p>🐶 <em>and KMP. Doing some Kotlin/JS work too!</em></p><p>🤞 <em>We’re going to switch it on for the </em><a href="https://github.com/touchlab/DroidconKotlin/pull/145"><em>refreshed Droidcon app</em></a><em>. In person events or not, we’ll publish the app anyway, just for fun.</em></p><p>🚀 <em>Some. Not everybody. It’ll take some time to work out issues, but somebody has to go first, right?</em></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=2ba19af65fe7" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[SQLCipher and KMM]]></title>
            <link>https://medium.com/@kpgalligan/sqlcipher-and-kmm-58d96ea8095d?source=rss-c2f810aa7890------2</link>
            <guid isPermaLink="false">https://medium.com/p/58d96ea8095d</guid>
            <category><![CDATA[kotlin]]></category>
            <category><![CDATA[kotlin-multiplatform]]></category>
            <category><![CDATA[kotlin-native]]></category>
            <dc:creator><![CDATA[Kevin Galligan]]></dc:creator>
            <pubDate>Wed, 23 Sep 2020 15:17:52 GMT</pubDate>
            <atom:updated>2020-09-23T15:17:52.223Z</atom:updated>
            <content:encoded><![CDATA[<p>Here’s a quick little followup to Sam’s post: <a href="https://dev.to/samhill303/multiplatform-encryption-with-sqldelight-and-sqlcipher-5do4">Multiplatform Encryption with SQLDelight and SQLCipher</a>. Recently for a client we needed to implement this with Kotlin 1.4.0, and ran into a couple issues. I’m only going to describe how to get the iOS side working as Android is pretty straightforward (although Android is in the sample and video).</p><p>Here’s KaMPKit updated to use SQLCipher</p><p><a href="https://github.com/touchlab-lab/KaMPKitSQLCipher">touchlab-lab/KaMPKitSQLCipher</a></p><p>The cipher key is hardcoded in code. Do *not* do that in your app. You need to get your key from a more secure source.</p><p>Here’s a video showing edits on KaMP Kit:</p><iframe src="https://cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fwww.youtube.com%2Fembed%2F6_jgkD1v8j8%3Ffeature%3Doembed&amp;display_name=YouTube&amp;url=https%3A%2F%2Fwww.youtube.com%2Fwatch%3Fv%3D6_jgkD1v8j8&amp;image=https%3A%2F%2Fi.ytimg.com%2Fvi%2F6_jgkD1v8j8%2Fhqdefault.jpg&amp;key=a19fcc184b9711e1b4764040d3dc5c07&amp;type=text%2Fhtml&amp;schema=youtube" width="854" height="480" frameborder="0" scrolling="no"><a href="https://medium.com/media/e66f6e9738b614e0f6e2040ef887c0c1/href">https://medium.com/media/e66f6e9738b614e0f6e2040ef887c0c1/href</a></iframe><p>SQLiter ran into an issue setting the key for SQLCipher. That apparently used to work, but stopped at some point. <a href="https://github.com/touchlab/SQLiter/pull/22">There was a PR to fix that</a>, but that was not merged in before 0.7.0 was released. 0.7.0 is used in the current version of SQLDelight, so you’ll need to force this fixed version.</p><pre>sourceSets[&quot;iosMain&quot;].dependencies <strong>{<br>    </strong>implementation(&quot;co.touchlab:sqliter:0.7.1&quot;) <strong>{<br>        </strong>version <strong>{<br>            </strong>strictly(&quot;0.7.1&quot;)<br>        <strong>}<br>    }<br>    //etc...<br>}</strong></pre><p>We also had an issue with our custom cocoapods fork, so if by chance you’re using that, you’ll need to use the latest, which is version <a href="https://github.com/touchlab/KotlinCocoapods/releases/tag/0.12">0.12</a>.</p><p>To configure your SQLDelight driver for native, you need to supply a custom DatabaseConfiguration for SQLiter.</p><pre>val schema = YourDb.Schema //SQLDelight Schema<br>val configuration = DatabaseConfiguration(<br>    name = &quot;YourDbName&quot;,<br>    version = schema.version,<br>    create = <strong>{ </strong>connection <strong>-&gt;<br>        </strong><em>wrapConnection</em>(connection) <strong>{ </strong>schema.create(<strong>it</strong>) <strong>}<br>    }</strong>,<br>    upgrade = <strong>{ </strong>connection, oldVersion, newVersion <strong>-&gt;<br>        </strong><em>wrapConnection</em>(connection) <strong>{ </strong>schema.migrate(<strong>it</strong>, oldVersion, newVersion ) <strong>}<br>    }<br>    </strong>,key = yourCipherKey<br>)<br>val driver = NativeSqliteDriver(configuration)</pre><p>To get this all to work in iOS, as discussed in Sam’s post, disable sqlite linking:</p><pre><em>sqldelight </em><strong>{<br>    </strong>database(&quot;YourDb&quot;) <strong>{<br>        </strong>packageName = &quot;co.touchlab.yourapp.db&quot;<br>        linkSqlite = false<br>    <strong>}<br>}</strong></pre><p>Then add the SQLCipher dependency (if using cocoapods)</p><pre><em>cocoapods[ext</em>] <strong>{<br>    </strong>summary = &quot;Shared code for YourApp&quot;<br>    homepage = &quot;https://github.com/touchlab&quot;<br>    pod(&quot;SQLCipher&quot;, &quot;~&gt; 4.0&quot;)<br><strong>}</strong></pre><p>Remember, if you add pod to your Gradle config, you need to build from Xcode and not the Gradle command line. I always forget this.</p><p>That *should* be it. If there are other missing details, let me know and I’ll update.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=58d96ea8095d" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Ktor and Kotlin/Native]]></title>
            <link>https://medium.com/@kpgalligan/ktor-and-kotlin-native-fb5c06cb920a?source=rss-c2f810aa7890------2</link>
            <guid isPermaLink="false">https://medium.com/p/fb5c06cb920a</guid>
            <category><![CDATA[kotlin-native]]></category>
            <category><![CDATA[kotlin-multiplatform]]></category>
            <category><![CDATA[kotlin]]></category>
            <dc:creator><![CDATA[Kevin Galligan]]></dc:creator>
            <pubDate>Tue, 01 Sep 2020 20:05:18 GMT</pubDate>
            <atom:updated>2020-09-01T20:05:18.578Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*k6gK_vGTeCP0peOqu97aoA.png" /><figcaption><a href="https://commons.wikimedia.org/wiki/File:Network-cables-1.png">https://commons.wikimedia.org/wiki/File:Network-cables-1.png</a></figcaption></figure><p>The story of coroutines for Kotlin/Native has been complex for a while now, and with the news that <a href="https://blog.jetbrains.com/kotlin/2020/07/kotlin-native-memory-management-roadmap/">the Kotlin/Native memory model will be changing</a>, coroutines for Kotlin/Native will remain a complex story for some time.</p><p>Ktor is built around coroutines. The coroutines situation fundamentally affects how Ktor functions. There have been multiple moving targets in this story, which has created a lot of confusion and a number of bug reports that kind of cross over the same core issues.</p><p>In this post, I will attempt to add some clarity to the situation.</p><h4>The Coroutines Situation</h4><p>To be clear, when we’re talking about “coroutines”, we’re generally talking about <a href="https://github.com/Kotlin/kotlinx.coroutines">kotlinx.coroutines</a>. It’s technically a separate library, but I can’t imagine a realistic situation where you’d actually use coroutines and not include kotlinx.coroutines.</p><p>Initially, kotlinx.coroutines for Kotlin/Native was single-threaded. You could suspend execution, but not schedule work on different threads. This was due to Kotlin/Native’s memory model.</p><p>Ktor was designed to run on this single-threaded model. Also, as far as I know on iOS, you would need to initiate Ktor calls from the main thread.</p><p>In late 2019, a draft PR emerged which allowed kotlinx.coroutines to communicate across threads. We’ll call this the “MT” branch, for “multithreaded”. From this branch, there have been parallel library releases. The current main release is ‘1.3.9’ and the current multithreaded release is ‘1.3.9-native-mt’.</p><p>Unless something changes, the parallel branch and release model will likely stay the same for kotlinx.coroutines until the Kotlin/Native memory model update is complete.</p><h4>Ktor</h4><p>Until 1.4, Ktor was still designed to be run with the single-threaded version of kotlinx.coroutines. You *could* run it with the MT version, but you had to be very careful to keep the scope you were in to the main thread and make sure it was never frozen.</p><p>It’s a little complicated to explain, and not super useful as it’s now history, but here it is. Coroutines run in a scope, which has (among other things) a Dispatcher and a Job. When you change the Dispatcher to run code on another thread, that scope gets frozen. Once frozen, everything the Job holds will also be frozen. So, if you were doing something on a background thread in the same scope as something you were doing with Ktor, even if Ktor was only in the main thread, you’d get an InvalidMutabilityException.</p><p>I think one of the more confusing parts is that Ktor would work until you involved that scope in a background process, after which it would stop working.</p><p>To see this in action, watch the video.</p><iframe src="https://cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fwww.youtube.com%2Fembed%2Fvqyv5q5NqVE%3Ffeature%3Doembed&amp;display_name=YouTube&amp;url=https%3A%2F%2Fwww.youtube.com%2Fwatch%3Fv%3Dvqyv5q5NqVE&amp;image=https%3A%2F%2Fi.ytimg.com%2Fvi%2Fvqyv5q5NqVE%2Fhqdefault.jpg&amp;key=a19fcc184b9711e1b4764040d3dc5c07&amp;type=text%2Fhtml&amp;schema=youtube" width="854" height="480" frameborder="0" scrolling="no"><a href="https://medium.com/media/6a2475686fecac29f85cc4469a52134e/href">https://medium.com/media/6a2475686fecac29f85cc4469a52134e/href</a></iframe><p>To get around this, you either need to maintain a different scope for Ktor, and make sure it never got frozen, or isolate the Job. <a href="https://github.com/touchlab/KaMPKit/blob/45e20c85b42beea9d2a14ad2819ade135f5b56cd/shared/src/iosMain/kotlin/co/touchlab/kampkit/ktor/Platform.kt">We did that with KaMPKit</a>. It was a pretty ugly hack, but it worked.</p><p>Also, since Ktor depended on the non-MT version, you could unintentionally be using the non-MT version of kotlinx.coroutines <em>even though your dependency configuration explicitly asked for it</em>. You would need to specify that you wanted to use that version.</p><pre>implementation(&quot;org.jetbrains.kotlinx:kotlinx-coroutines-core:1.3.9-native-mt&quot;) <strong>{<br>    </strong>version <strong>{<br>        </strong>strictly(&quot;1.3.9-native-mt&quot;)<br>    <strong>}<br>}</strong></pre><h4>Kotlin and Ktor 1.4 release</h4><p>The 1.4 release of Ktor actually fixes this issue. We didn’t hear about it for a bit, but I think that was because the issue was confusing to a lot of folks. Although it’s fixed for the MT branch, the situation has some further confusion, as the current release of Ktor pulls in the MT branch of kotlinx.coroutines. <strong><em>If your project expects the single-threaded version of kotlinx.coroutines, this situation can result in some unexpected behavior.</em></strong></p><p>To experiment with Ktor in the different versions, you can check out our little sample app.</p><p><a href="https://github.com/touchlab-lab/ktorcoroutines">touchlab-lab/ktorcoroutines</a></p><p>The master branch has 1.3.72 and shows the failure that was happening. The <a href="https://github.com/touchlab-lab/ktorcoroutines/tree/kotlin_140">kotlin_140</a> branch has the updated versions and a functional Ktor sample.</p><h4>Issues</h4><p>Ktor needs to be run from the main thread. There are also issues with Ktor and testing, related to the threading restrictions. We’ll be digging into this more at some point. Just be aware of it.</p><p>Also, Russell tells me there’s a <a href="https://youtrack.jetbrains.com/issue/KTOR-924">logging issue</a> which I’m not even going to dig into right now because I want to publish this today…</p><h3>TL;DR</h3><p>Ktor and kotlinx.coroutines were not working well together on native before 1.4. Now they cooperate better. Using Ktor 1.4 will possibly pull in the MT branch of kotlinx.coroutines, so if your project is not designed for that, be aware that it’s possibly an issue.</p><p>We’ve updated KaMP Kit to remove the hack we had put in. Ktor is now just regular Ktor</p><p><a href="https://github.com/touchlab/KaMPKit">GitHub - touchlab/KaMPKit: KaMP Kit by Touchlab. A collection of code &amp; tools designed to get your mobile team started quickly w/Kotlin Multiplatform</a></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=fb5c06cb920a" width="1" height="1" alt="">]]></content:encoded>
        </item>
    </channel>
</rss>