Kotlin Android in Bazel
The past week I took some of my spare time to make building Kotlin Android in Bazel work. The result is merged into pubref/rules_kotlin, which is kind of the "official" Kotlin rules for Bazel at the moment, and in its 0.4 release. Here I'm going to talk about some backgrounds and explain some technical details of this work.
Kotlin actually added Android support long before Android's announcement of official Kotlin support, and I did some attempts to make it work in Bazel, but to no avail. That's why I turned to Scala and sbt-android for my NotifBot project.
Recently I did some googling and found aaronj1335/bazel-kotlin-android, which is actually very nice, and the main inspiration of my work. I learnt a few interesting points from this project:
- The android_library rule on top of resource files will make the R class in Kotlin code work.
- The java_import rule with neverlink = 1 will make the Android SDK classes in Kotlin code work.
So I tried to rewrite NotifBot using Kotlin (from Scala), and followed the example of that project, but hit a problem: AAR libraries imported.
AAR libraries are kind of like JAR libraries, but with additional Android things in it. (e.g. resource files, AndroidManifest.xml, etc.) Since they are different from JAR files, when we generating the JAR file out of the Kotlin sources, they'll pose a problem.
To resolve this problem, I created the kotlin_android_library rule/macro to do the following things:
- Auto generate implicated "_res" and "_sdk" rules, which are the android_library and java_import rules from the aaronj1335/bazel-kotlin-android example.
- Auto generate an implicated "_aar" rule, which is an android_library rule of all the AAR dependencies, but with neverlink = 1, so that we won't try to include them into the generated JAR file.
- After generated the JAR file out of the Kotlin sources, auto generate an android_library rule, which includes the JAR file, all the AAR dependencies and the resource dependency so that this rule can be used alone in the android_binary rule.
With these changes, the rewriting of NotifBot in Kotlin worked. As a next step, I tried to rewrite OneKey in Kotlin (this time from Java directly). This rewriting discovered a bug in depended kotlin_library rules, and I fixed that.
After that the rewriting of OneKey was also a success, so I think the work of getting Kotlin Android support in Bazel is done. Yes it's still possible (and trivial) to add a kotlin_android_binary kind of rule to include everything in a single rule, but I think that's not very useful or needed. If you really think that will be useful in some cases, or if you find any bugs in the implementation, please do let me know.
If you are looking for an example of building Kotlin Android in Bazel, please take a look at my BUILD files for NotifBot and OneKey.