KMP - General understanding

I’ve just spent some time on a second attempt of using KMP and Compose.

Naturally, I went through the documentation mentioned here:

Here are the things that confused me in this process:

  1. I planned and expected to use IDEA Ultimate as the IDE - for one thing, it mentions KMP in the “new project” modal. However, I had some trouble with it and the documentation seems to always recommend using Android Studio.
  2. Switching to Android Studio solved many problems and after some fidgeting, I got the app to build and run on a simulator (on Windows). However, browsing the project, a lot of things come up about multiplatform and android, but not much about ios (for example the root build.gradle.kts as well as composeApp/build.gradle.kts contains an entire “android” section). This is very confusing because it gives the impression that something is wrong/missing.
  3. I wrote some platform-specific code. The android part compiles fine, the iOS part doesn’t (“Unresolved reference: platform”).
  4. After some digging, I find that in order to make it work on ios, you actually need to have XCode running (which in turn requires osx).

This seems to be a silly limitation to a certain point. In the end, I’d use some sort of CI process to actually build platform-specific apps.

In conclusion:

  1. would be nice to mention limitations and requirements somewhere
  2. it’s still not clear to me how the project should be managed - is it correct that I would need to switch between Android Studio and XCode (and possibly IDEA Ultimate), or is there a way to use just one IDE?
  3. still don’t know where to start with ios, or if I can somehow skip the current problem (I can’t compile the rest of the project)
  4. the interface to the build system could be greatly improved if gradle was dropped - I’ve said it in the past, it’s one of the worst piece of software I’ve ever seen, and wrapping it in kotlin only seems to make kotlin dirtier.
  5. at this point, it feels that “multiplatform” isn’t very true - considering that you need 3rd-party and platform-specific tools (and code?).
1 Like

I think there was a small mention on the KMM release blog that iOS is still in beta or alpha. I can’t remember. But based on my past digging before, you really need Xcode tools for iOS to work. This has been the case for every cross-platform framework.

2 Likes

That’s correct, it’s still in alpha - but since it is released one way or another, one expects the basics to be in place.

1 Like

As I know (although I don’t develop iOS apps) it is apple’s fault. Apple allows developing native iOS apps only on mac. Jetbrains does not have much things can do to help with that.

2 Likes

I don’t believe that’s entirely true. Apple (AFAIK) doesn’t publish interfaces or an sdk in Kotlin.

This is particularly confusing to me… KMP somehow has bindings to something on ios (otherwise you wouldn’t be able to write Kotlin code for ios at all).

And secondly, my understanding of “multiplatform” is that some sort of abstraction layer is provided which you can code against in a platform agnostic way. I guess this is a bit how Jetpack Compose is working.

At this point I’m still very fuzzy on a lot of concepts

Well, you answer yourself in the very next sentence, don’t you?

I never used Kotlin with iOS, but my understanding is it provides an abstraction layer to code for multiple targets, including iOS, but to compile it fully we need macos. Apple doesn’t allow or at least doesn’t make it easy to compile anything for their devices without using macos.

2 Likes

Well, you answer yourself in the very next sentences, don’t you?

It was more of a guess. It’s confusing because I’m guessing that since Apple isn’t actively supporting Kotlin, then somehow jetbrains is providing some sort of SDK or bridge to ios/osx.
In my current project this bridge does not seem to exist. The code in the documentation here results in bad/missing references. Again, I’m guessing this is because I haven’t somehow initialised the project in XCode.

The documentation should be more explicit about that and about the flow in general. E.g. explain why I should open the project in XCode. (in particular, I can’t imagine why opening XCode would suddenly make the references work)

but my understanding is it provides an abstraction layer to code for multiple targets, including iOS

That’s the thing - I haven’t see this abstraction layer (or a hint to it). I’ve only seen missing references in the ios-side of the app.

Apple doesn’t allow or at least doesn’t make it easy to compile anything for their devices without using macos.

Yes, that’s clear. As mentioned above, I would be building for ios/osx using CI pipelines running on macs. That should theoretically work. Problem is, it seems I will be coding blindly until then (because of the aforementioned missing references).

1 Like

Hi there, I ran into the same problem when developing Kotlin multiplatform OSS libraries on Windows.

Indeed you will need xcode to actually compile, run or test your code for Apple targets. However, as you pointed out, there are indeed Kotlin bindings for Apple APIs, and those can technically be used by the IDE even on non-Apple computers. In order to do so, @LouisCAD developed a Gradle plugin that downloads the Kotlin bindings on non-Apple platforms so the IDE can pick them up and stop showing red code, it’s called CompleteKotlin:

With this plugin I could at least write the code with IDE autocompletion and highlighting on IntelliJ IDEA Ultimate. I still needed a macOS agent on the CI to run the tests, though. I hope this helps.

4 Likes

Thanks!

That’s very useful to know - at least now I can stop worrying that I did something wrong and spending time trying to fix a problem that doesn’t really exist.

In my opinion, that plugin is absolutely essential (or at least should strongly recommend). Would be nice if JetbBrains acknowledged that and mentioned it in the documentation. :thinking:

1 Like

@zhengkeli. Isn’t true (AFAIK). For example, you can code app for iOS (and Android) with “Visual Studio” without Xcode.

@uuf6429 Agree with you. For instance VS/Xamarin looks to be the abstraction layer you mention.

I think first you need to decide if you want a native compiled or JVM app. I’m developing a JVM desktop app on Linux and use Conveyor to package for Win/Mac. People gave me feedback that the app works on Mac, so maybe you want to concentrate on JVM and stay away from native for now?

I was planning to have a mobile app, hence the targets of interest would be android and ios.

Hey, @uuf6429, I’ve been using KMP for developing an multiplatform app that targets Android, iOS and web for the better part of an year now, so maybe I can give you a more hands-on view on this.

Firstly, I kinda agree with your critique about the documentation, I’ve never developed for iOS before and sometimes I ended up in a weird state because it assumes you have some experience with iOS development and limitations. Part of it was just my ignorance, though, so keep in mind that things improve with time.

Second thing that comes to mind from your posts is that you seem to be conflating two things in regards to the “muitiplatform” idea here. KMP is mainly about writing common Kotlin code and run the same code on multiple platforms, not necessarily about writing code on one platform and running it on another (there is a slight difference here). KMP works beautifully for the former, I have a few modules in my project that compile for all client and server platforms involved (Android, iOS, web, Linux and macOS). For the latter, though, mainly due to limitations imposed by Apple, you’ll need a macos if you want to test the iOS output as you write code (common or ios-specific).

That being said, it doesn’t mean you need to use macOS all the time. You definitely need a macOS for the initial setup and for CI, but the process my team adopted is: If you are just creating new UI code that does not change any dependency and does not touch src/iosMain/kotlin, or also any server code, you can do that from any Mac, window or Linux machine and you don’t need to run the iOS version to verify your changes. If you are changing iOS related code, upgrading any libraries, thought, you should be on Mac and verify your changes on the iOS app. Of course, we run a set of tests on all platforms before releasing, but that’s not being done by the developers.

Overall, the platform has evolved a lot, even the Gradle side of things, which I agree is the worse part of the Kotlin experience. The app is evolving quite rapidly considering we have 3 platforms, especially considering the level of quality for the UI we’re achieving.

Let me know if you need any more info, I’m glad to help.

Thanks for the comprehensive reply @brunojcm!

sometimes I ended up in a weird state because it assumes you have some experience with iOS development and limitations

Agreed! While that is totally expected when you need to dig deeper in the code, it shouldn’t by something that comes up right after opening a new project, in my opinion.

Part of it was just my ignorance, though, so keep in mind that things improve with time.

Yes, sure - same thing here. This is definitely a great product and it does have a bit of a learning curve - but documentation should be able to make it easier.

While there’s already a considerable amount of documentation, it doesn’t seem to explain the architecture (from what I’ve seen, or I looked in the wrong place).

Some remaining questions/thoughts I have:

  1. Which IDE should one use and is that mandatory?
    Context: IDEA Ultimate seemed to have some trouble with the project, in the end I followed the documentation and switched to Android Studio - which I’m now also using for the iOS side (at the moment). I could imagine that some things, such as gradle(plugins) might actually require a specific IDE. But also, it’s obvious that Android Studio is better suited for developing and testing android apps.
    Reading the documentation, it seems mandatory to use xcode, at least once, on mac (we have macs at work, but I’ve never had to use xcode - an explanation would be welcome).

  2. How does the compilation process work?
    Context: other multiplatform languages, such as C, work differently. Code is effectively switched out depending on pre-processor directives. Some smart IDEs can be preconfigured with the right pre-processor settings so that such switched-out code is ignored.
    In KMP, this works differently. Errors still show up and when you look at the code of a different target, it gives the impression that the project won’t compile. The plugin mentioned above solves the errors, which in the end provides a better dev experience than C.

  3. Why platform X requires plugin/settingsX, but platform Y doesn’t have plugin/settingsY?
    Context: This is more of a product decision question on JetBrains’ side. What I mean is, when I look at src/build.gradle.kts, it looks like so more or less:

    kotlin {
    ...
        androidTarget {
            compilations.all {
                kotlinOptions {
                    jvmTarget = "1.8"
                }
            }
        }
    
        listOf(          // why doesn't this look like `iosTarget { ...`?
            iosX64(),
            iosArm64(),
            iosSimulatorArm64()
        ).forEach { iosTarget ->
            iosTarget.binaries.framework {
                baseName = "ComposeApp"
                isStatic = true
            }
        }
    
        sourceSets {
            val androidMain by getting {
    ...
            }
            val commonMain by getting {
    ...
            }
            // why isn't there an `val iosMain ...`?
        }
    }
    
    android {
    ...
    }
    
    // why isn't there an ios section?
    
  4. Are existing platform-agnostic/pure-kotlin libraries automatically usable as common dependencies?
    Context: When I saw that GitHub - g0dkar/qrcode-kotlin: QRCode Generator implemented in pure Kotlin, I assumed it could be used as a common dependency. I tried it so and ended up with some vague gradle errors. Looked a bit deeper and saw the the author had an androind version and was in the process of releasing an ios one too. Naturally, I’m wondering where are the limitations - is gradle/maven even aware of platform-specific libraries? Is a pure-kotlin library not automatically portable? Why?

  5. Where does KMP end and platform-specific layer start?
    Context: This is effectively what you wrote already and I guess relates to the compilation flow. Kotlin for javascript generates javascript, kotlin for wasm generates assembler. For android, presumably same as java. For ios I’m guessing it’s the same principle as native so I assume it’s automatically adding a platform-specific layer for things like memory management.

Anyway, at this point I think I’ve got the hang of it, so I feel more comfortable looking around.