Hi dear community, I've read the documentation (<...
# multiplatform
a
Hi dear community, I've read the documentation (here and here), and wanted to validate an idea, but before I do that, let me share a bit of a context and perhaps my understanding is completely wrong so I would appreciate a gentle kick in a right direction 😅 Context: Imagine a rather complicated project where the majority of the code is written in Swift (iOS) and Kotlin (Android), but the most critical bits of logic are shared between these platforms and are written in.... C++. The interop between Kotlin and C++ and Swift and C++ is implemented through Djinni that generates ObjC wrapper for iOS and JNI for Android. That C++ layer also provides the client-server communication logic via gRPC and Protobuf. Some parts of IDL (Djinni definitions) use proto definitions directly (to describe request/response types, etc) Problem: That C++ doesn't go anywhere any time soon, so we're doomed to keep it in our stack for now. While using Kotlin cinterop is an option to reach ObjC headers in Kotlin/Native and we can make it work with JNI in the Android source set, the proto definitions used directly by Djinni seem to be a problem. It appears that the protobuf compiler does not support Kotlin targets other than JVM. The most viable solution identified was to use Wire to generate Kotlin from proto files. And it works! With this array of technologies, we're now trying to build some sort of infrastructure and integrate it with the existing tech stack. So we're facing some challenges in putting things to places that (we think) are right. Assumed solution: Introduce some logic on CI/CD that uses Wire to generate Kotlin classes from proto files, package those and send the binary to maven to be later consumed by our bridging layer between KMM and C++. Now to how those artifacts are packaged, as far as I understand, we shall be using
*.klib
as such artifact, but I'm also a bit confused by this phrase:
By default, a Kotlin/Native target is compiled down to a
*.klib
library artifact, which can be consumed by Kotlin/Native itself as a dependency but cannot be executed or used as a native library.
Does that mean that
*.klib
would only be compatible with the Kotlin/Native part of the app (e.g. iOS source set) or would it be sufficient to cover all source sets (common, ios, android)? Or would this be the only thing required in my use case? I think I just might be confused by the terms here and need some guidance on the matter. P.S. Also, it was a sneaky attempt to get some validation for the direction we're headed. So I appreciate any comments on that as well 🙏 Thank you
t
You might get better information if you ask this on the #C7L3JB43G channel. For me it seems that your idea is quite OK and AFAIK klib is platform independent. However, it is not a finalized format IIRC, so it might change over time. Asking out of curiosity. You mention a KMM - C++ layer. What goes through that layer actually? Actual protobuf encoded byte arrays?
g
I'm a bit unclear on what your goal is? Is it to gradually replace the C++ code with Kotlin Multiplatform code? Or to replace the Swift (iOS) and Kotlin (Android) code with Kotlin Multiplatform? Or both?
a
Thanks for the responses, folks! @Tóth István Zoltán, to your question about KMM - C++, it is a set of mappers/wrappers to allow us call APIs defined in C++. The proto objects are essentially the byte arrays flowing from one layer to another. @Gary Peck it is a bit of both. We're still in the research phase, but right now we see some opportunities to: • consolidate the majority of business logic that is currently duplicated across Android, iOS (and maybe Web) inside KMM/KMP component(s) • gradually migrate from C++ to give mobile engineers more safety and to provide the opportunity to work with a familiar technology (that doesn't have that many foot-guns 😬)
t
If you generate Kotlin source code, it goes to
commonMain
and you compile and publish it to a Maven repo you will be able to use it on all platforms. There will be different artifacts for different platforms, but the KMP Gradle plugin handles that for you.
1
a
That is awesome! Thank you, @Tóth István Zoltán!
t
I typically just put everything into commonMain and only the really platform specific stuff goes to the platform source sets (as it should be). I've been able to put about 95% of my code into common (web/Android/iOS). I don't use Compose, but I guess it's the same.
a
That's really reassuring. I think I was just a little confused by the documentation and the way how you have to think about 2 things at the same time and whether they would work together or not 😅 In the nutshell, we probably won't really need to do anything apart from this to deploy the artifact, given our kotlin definition of the proto objects are in the common source set. Let me give it a try and I'll share my findings. Thanks again 🙂
r
If I understand correctly, your goal can be easily completed without too many technical obstacles. I will explain: 1. It seems that you are making a glue layer similar to bridge, is it similar to the automated generation of web js bridge? For example, the basic type protocol req & rsp. If this is the case, it is not difficult for Kotlin/KMP. You just need to use KotlinPoet to write kt files, then put them in commonMain, and then enter according to the standard KMP library. Just release it. 2. klib is the standard format of the KMP library, which contains Kotlin's ir files, that is, some intermediate products, which have not been compiled into any platform code. So this lib is universal. These klibs will not participate in the compilation together until you finally compile it into aar/so. reference: https://kotlinlang.org/docs/native-libraries.html#library-format
🙏 1