A technology for compiling Kotlin code into native binaries is Kotlin/Native. In cases where a virtual machine is not accessible or desirable, applications and libraries written in Kotlin Native run without a virtual machine and this is useful.
Creating Native Instructions:
Kotlin Native makes use of LLVM. A set of modular compiler tools is LLVM (not an acronym….anymore 1). A language-independent Intermediate Representation (IR) is compiled into different platform-specific native binaries by backend compilers. To compile any high-level language into this IR, front-end compilers can be written. This enables the compilation of several high-level languages into native instructions unique to the platform.
- Kotlin Native is only beta but supports it already
- iOS (arm32, arm64, emulator x86_64)
- MacOS (x86_64)
- Android (arm32, arm64)
- Windows (mingw x86_64)
- Linux (x86_64, arm32, MIPS, MIPS little endian, Raspberry Pi)
- WebAssembly (wasm32)
Tools are available for translating C and Objective C (and thus, indirectly, Swift) libraries into Kotlin libraries and then using them directly from Kotlin. There is a simple integration into Gradle for this construction phase.
Unique bindings for popular libraries have already been created on each platform. For example:
Designing an Application
In the tool chain, there are many moving pieces:
- Kotlinc – Compiler Kotlin
- Cinterop – A Kotlin Libraries (klib) generation tool from C/ObjC headers/libraries
- Org.jetbrains.kotlin.multiplatform – Gradle multi-platform plugin for projects with Kotlin
- The best way to get started is to build a new Kotlin Native project using IDE (CLion or IntelliJ)
This configures tasks for creating a native Mac OS framework and checking it. Depending on the platform, the macosX64 call can be substituted,
- Importing C / Objective C
Many frameworks and libraries are supported out of the box, as mentioned above.
As you would in any other Kotlin project, you can also draw in other dependencies via Gradle,
You can build .def files that define the headers, compiler options, and linker options if you need to import additional C / ObjC headers. The cinterop tool processes these to generate klibs or Kotlin bindings that can easily be used to call the C code from Kotlin. Marshalling and translation are primarily done by the Klib.
To have a single .def file that supports multiple native platforms, you can use platform specific compiler and linker options,
Although the Cinterop tool can do the job in the context, Gradle is the best way to invoke it.
When the project is setup, most of the code you compose will be standard Kotlin. Because it’s not running on the JVM, there won’t be a wide swath of libraries you know and love – because they’re just Java libraries.
But the standard platform libraries, any native or multi-platform libraries that you import and any C/ObjC klibs that you import/generate will be open to you.
If you are using your Kotlin code, memory management is still managed for you, but the implementation is very different. It uses comparison counting during runtime (with a garbage collector for cycles). So the nice thing is, not much changes when writing Kotlin for Native.
There are more considerations when crossing the border between Kotlin and other languages/ platforms. Unique issues for natives include,
- Native Memory Management – allocating and freeing bytes!
- Marshaling Data – moving data back and forth between Kotlin and native code – e.g reference counting implementation is compatible with Swift / ObjC but not C
- Threading – Kotlin Native has tight constraints on what can be shared between threads
- Passing Functions – calling Kotlin from native and calling native from Kotlin
- Supported Language Features – e.g. Suspend functions are not supported between Kotlin and C / ObjC
Within this article, there’s so much here to get into and some of this is a moving target as it’s all beta. For example:
- To support common patterns, the threading model can evolve to
- At the time of writing, Coroutines are mainly confined to the main thread so that a solution needs to be developed
- Kotlin libraries can have some common cross-platform concerns
- All the time, Kotlin Native or multi-platform libraries and frameworks pop up
With all of Kotlin’s numerous flavours, planning how to handle the code can be overwhelming. On all platforms (JVM, Android, JS and different native platforms), some code will be compatible and some will be exclusive to a single platform. This is where projects of multi-platforms come in.
We can provide a single project with a multi-platform project that includes the normal and unique code. It can be used for the creation of various objects, such as JVM .jar file, native .dll or .dylib file etc.
Within the popular field, with the expected keyword, we can define placeholders for entities (classes, functions, globals, etc.).
This can then be applied using the actual keyword explicitly for each platform,
The reuse of Kotlin across multiple platforms is maximized by these ventures.
Advantages of Kotlin/Native
- Kotlin allows writing less code, specified to each device builtin native language & runs without restrictions
- Fully compatible with Java
- It imposes no runtime overhead
- Suits for the multi-platform development
- Kotlin development offers more safety
Kotlin Native, while beta, is a very interesting project and has a lot of features and potential already. Using Kotlin to write common code for a mobile application in a multi-platform project is one of the most convincing tales. A native iOS framework or an Android library can be developed. It is then possible to add a thin native iOS (Swift) and Android (more Kotlin :-)) layer on top, thus reducing overhead and expense in the development of mobile Cross-platform applications.