Kotlin Native and Raspberry Pi: multiplatform projects
This article concludes the short series about using Kotlin Native for writing Raspberry Pi applications. So far, we have successfully created a sample IoT project in Gradle, and bound a C library into our codebase. Then, we used them to show some content on an SSD1306 monochrome display. Now it’s time to add a HTTP client and show some dynamic content… if it only worked! However, the failure is an opportunity to take a closer look of how Kotlin multiplatform projects work.
tl;dr;
Ktor is not available for Raspberry Pi due to the lack of coroutine support on this platform. Unfortunately.
Ktor Client for Raspberry Pi? No!
My original plan for concluding the series was using Ktor Client library. It’s a HTTP client, so that we could fetch some content from the Internet and then show it on the display. The idea is reasonable. HTTP powers the Internet. Therefore, the ability to communicate over it is a must-have for almost every IoT project. Unfortunately, at this moment this is not possible without a lot of hacking. To understand the reason, let’s see how Kotlin ecosystem is shaped.
Kotlin in JVM
In every programming language, we can find a standard library. It provides the basic functionality, general-purpose algorithms and data structures, so that we don’t have to reinvent wheel. Kotlin originated in JVM ecosystem, therefore it shares the standard library with Java. In addition to this, JetBrains added some extra utilities that make better use of Kotlin syntax. They include modifications to the collection API, some standard functions and sequences. However, for most of the advanced tasks we basically use JDK tools in our Kotlin projects.
Going further with Kotlin multiplatform projects
Kotlin has an ambitious goal of supporting multiplatform projects. One part is compilation, where JetBrains provides compilers for JVM, JavaScript and native executables. However, the support is also present in the language itself. It helps organizing the codebase. Let’s notice that most of the logic will be common to all platforms. We also need a place to put the code that differs between the platforms. This is how Kotlin multiplatform projects are organized. Kotlin has also a special syntax to help us here:
In the “common” codebase we can use the “expect” keyword on classes. It means that the we know the class, but the implementation is platform-specific. The common code contains just a stub:
interface FileReader {
fun readFile(): String
}
expect class FileReaderFactory {
fun createFileReader(path: String): FileReader
}
Now, in every target we provide the “actual” implementation. For JVM, it would use JDK standard library:
// for JVM target
actual class FileReaderFactory {
fun createFileReader(path: String): FileReader {
val file = File(path)
// ...
return JvmFileReader(file)
}
}
Obviously, in Kotlin JS and Native we cannot use File
from JDK. Instead, we must find other ways. And here’s the catch – sometimes there’s no alternative.
Kotlin standard library
Kotlin relies so much on JDK standard library that if we take it out, there’s very little left. JetBrains tries to bury the hole by creating several Kotlin multiplatform projects:
The maturity of each library varies. For example, coroutines and serialization have already achieved the production stability, whereas date/time support – not. In addition, not every target is equally supported. When it comes to linuxarm32hfp
target (binaries used by Raspberry Pi), I found the official packages only for kotlinx-serialization. With minimal effort, it is also possible to create a custom build of kotlinx-datetime for this target. However, coroutines pose a much bigger challenge. And unfortunately, Ktor Framework needs coroutines, therefore it is restricted only for those targets that support them. Raspberry Pi is not among them.
Hint
Don’t release a new multiplatform programming language without a good standard library.
Statement by JetBrains
The targets with the best support are Linux-x86_64, Android and iOS. All the official libraries have releases for those platforms. Third-party multiplatform libraries also support at least one of them. When it comes to Raspberry Pi, I found some discussions between the developers and JetBrains (the company behind Kotlin). It seems that currently the main reason behind the poor support for Raspberry Pi is the lack of CI/CD pipeline.
At this moment, we can use some unofficial builds of the libraries mentioned above and Ktor. However, they required forking the actual projects. Therefore, we should not expect regular updates for them (e.g. Ktor is only available in 1.6.8 version, but not 2.x).
Why IoT is such a big thing?
Younger generations may not remember that Java was originally a language used for all sorts of applications. Desktop apps, games, mobile apps, backends. Currently, JVM is very strong only in the last use case and here’s most of the current development focused. In all other use cases, JVM is a rather niche ecosystem. JetBrains with their IntelliJ family of code editors is a notable exception. However, they use a forked JVM to fix bugs and improve the interoperability between Java code and Windows/Linux/macOS platforms.
Language specialization
Specialization is not a bad thing, although it is not good, either. For us, developers, it means that we are locked to only a certain type of projects. If we want to try out something else, we have to change the entire technology stack. Web companies can face issues if they want to go beyond web. Suppose that they want to develop a product that is not a typical client/server application with Java backend. It means that they either have to outsource it or hire new specialists that know another technology. It’s also harder to keep those specialists in the company if there’s just one single project available to them. Inability to switch projects and find new challenges can be a reason to leave the company. And the precious know-how also goes away.
IoT market
In the last 10-15 years we could observe a massive change in how Internet works. When I was a student, the vast majority of devices connected to the Internet were desktop computers and laptops. Browsing the web from the mobile phone was available to a small group of business people and enthusiasts. Then, smartphones arrived and everything changed. In addition, people started connecting more and more ordinary devices to the network. Java never targeted IoT market, because back in the 1990-ies there was no such thing as “IoT”. Of course, there were embedded microcontrollers but we used them differently and nobody seriously considered porting resource-heavy JVM into them.
Today, it is quite normal that a business application works together with plenty of devices. Barcode scanners, sensors, automation. Even my company, Allegro (the biggest on-line marketplace in Central Europe) develops its own parcel lockers. In fact, this is the second company that I work for which has its own hardware:
Gues what all those projects have in common. They are not client-server applications; they may run on devices with limited resources; they may use exotic peripherals. And they are a great addition to the client-server approach. It’s great that Kotlin attempts to take this road with the multiplatform project support. GraalVM and Java’s Project Panama are other examples. However, there’s still a couple of challenges on the way.
Conclusion
So, can we use Kotlin Native to write Raspberry Pi applications? The answer is “yes, but… “. Below, I provide a summary of things that impressed me:
- Gradle support in general
- Binding C libraries to Kotlin with cinterop tool
- Multiplatform projects in Kotlin
The documentation could be slightly better, but it’s not bad. It was quite easy to find all I needed in the official docs. On the other hand, I notice two issues:
- small community: the number of articles about Kotlin Native and third-party libraries is small,
- poor standard library – and this is currently a blocker.
At this moment, I do not recommend using Kotlin Native for serious Raspberry Pi projects. It was a great fun, but for serious work we need stable foundations and more tools. Hopefully things will change in the future, it would be quite sad if another language from the JVM world missed another opportunity…
Take also a look at previous articles, if you haven’t seen them: