#Kotlin/Native

Kotlin/Native attempts to compile Kotlin source code directly to native binaries specific to the supported target platform. Kotlin/Native is primarily designed to allow compilation for platforms on which virtual machines are not desirable or possible, such as embedded devices or iOS.

Kotlin/Native provides an LLVM based backend for the Kotlin/Native compiler and native implementations of the Kotlin standard library. The Kotlin/Native compiler itself is known as Konan. LLVM is basically a compiler infrastructure that we can use to develop a front end for any programming language and a back end for any instruction set architecture.

It provides a portable, high-level assembly language optimized for various transformations that serve as a language-independent intermediate representation. Originally implemented for C and C++, today there are several languages with a compiler that supports LLVM, including Kotlin:

img
img

Kotlin/Native supports a number of platforms that we can conveniently select through the Gradle configuration:

  • Linux (x86_64, arm32, arm64, MIPS, MIPS little-endian)
  • Windows (mingw x86_64, x86)
  • Android (arm32, arm64, x86, x86_64)
  • iOS (arm32, arm64, simulator x86_64)
  • macOS (x86_64)
  • tvOS (arm64, x86_64)
  • watchOS (arm32, arm64, x86)
  • WebAssembly (wasm32)

Now, we should notice that in our Gradle configuration, there is a check for the host operating system. This is used to determine what native platform to target i.e. you need to be on macOS to build for that platform and so on.

kotlin { val hostOs = System.getProperty("os.name") val isMingwX64 = hostOs.startsWith("Windows") val nativeTarget = when { hostOs == "Mac OS X" -> macosX64("native") hostOs == "Linux" -> linuxX64("native") isMingwX64 -> mingwX64("native") else -> throw GradleException("Host OS is not supported in Kotlin/Native.") } }

#Interoperability

Kotlin/Native also supports two-way interoperability with native programming languages for different operating systems. The compiler creates:

Kotlin/Native supports interoperability to use existing libraries directly from Kotlin/Native:

It is easy to include compiled Kotlin code in existing projects written in C, C++, Swift, Objective-C, and other languages. It is also easy to use existing native code, static or dynamic C libraries, Swift/Objective-C frameworks, graphical engines, and anything else directly from Kotlin/Native.

Finally, Multiplatform projects allow sharing common Kotlin code between multiple platforms, including Android, iOS, JVM, JavaScript, and native. Multiplatform libraries provide required APIs for common Kotlin code and help develop shared parts of a project in Kotlin in one place and share it with some or all target platforms.

#Getting Started

https://kotlinlang.org/docs/native-get-started.html

Create a native application
Create a native application

Open the build.gradle.kts file, the build script that contains the project settings. To create Kotlin/Native applications, you need the Kotlin Multiplatform Gradle plugin installed. Ensure that you use the latest version of the plugin:

plugins { kotlin("multiplatform") version "1.6.10" }

Build your project. It will produce a native executable under

build/bin/native/debugExecutable/<your_app_name>.kexe

#Example: Native Interop

This tutorial demonstrates how to use IntelliJ IDEA to create a command-line application. You'll learn how to create a simple HTTP client that can run natively on specified platforms using Kotlin/Native and the libcurl library.

https://kotlinlang.org/docs/native-app-with-c-and-libcurl.html

The full code for this sample is here: https://github.com/Kotlin/kotlin-hands-on-intro-kotlin-native

  1. Create the project.

New project. Native application in IntelliJ IDEA
New project. Native application in IntelliJ IDEA

  1. Update the build.gradle file.

    kotlin { def hostOs = System.getProperty("os.name") def isMingwX64 = hostOs.startsWith("Windows") def nativeTarget if (hostOs == "Mac OS X") nativeTarget = macosX64('native') else if (hostOs == "Linux") nativeTarget = linuxX64("native") else if (isMingwX64) nativeTarget = mingwX64("native") else throw new FileNotFoundException("Host OS is not supported in Kotlin/Native.") nativeTarget.with { binaries { executable { entryPoint = 'main' } } } }
  2. Create a definition file.

    When writing native applications, you often need access to certain functionalities that are not included in the Kotlin standard library, such as making HTTP requests, reading and writing from disk, and so on.

    Kotlin/Native helps consume standard C libraries, opening up an entire ecosystem of functionality that exists for pretty much anything you may need. Kotlin/Native is already shipped with a set of prebuilt platform libraries, which provide some additional common functionality to the standard library. We'll link in a standard C library.

    Create a directory named src/nativeInterop/cinterop.

    Create a file libcurl.def with the following contents.

headers = curl/curl.h headerFilter = curl/* compilerOpts.linux = -I/usr/include -I/usr/include/x86_64-linux-gnu linkerOpts.osx = -L/opt/local/lib -L/usr/local/opt/curl/lib -lcurl linkerOpts.linux = -L/usr/lib/x86_64-linux-gnu -lcurl

This defined kotlin header files to be created from the C headers on our system.

  1. Add interoperrability to your builds.

Add this to your build.gradle file.

nativeTarget.with { compilations.main { // NL cinterops { // NL libcurl // NL } // NL } // NL binaries { executable { entryPoint = 'main' } }
  1. Write the application code.

Update the source file Main.kt with the following source.

import kotlinx.cinterop.* import libcurl.* fun main(args: Array<String>) { val curl = curl_easy_init() if (curl != null) { curl_easy_setopt(curl, CURLOPT_URL, "https://example.com") curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L) val res = curl_easy_perform(curl) if (res != CURLE_OK) { println("curl_easy_perform() failed ${curl_easy_strerror(res)?.toKString()}") } curl_easy_cleanup(curl) } }

If you build it, you should get a native executable, linked to the curl libraries.

You should be able to run it to see output!

$ ./httpclient.kexe www.example.com <!doctype html> <html> <head> <title>Example Domain</title> <meta charset="utf-8" /> <meta http-equiv="Content-type" content="text/html; charset=utf-8" /> <meta name="viewport" content="width=device-width, initial-scale=1" /> <style type="text/css"> body { background-color: #f0f0f2; margin: 0; padding: 0; ....