I am confused about how Kotlin is compiled to iOS....
# ios
d
I am confused about how Kotlin is compiled to iOS. Is it first transpiled to ObjectiveC, or is it compiled to LLVM? What is the relationship between ObjectiveC and LLVM w.r.t Kotlin for iOS?
l
LLVM is a bitcode format (think JVM bytecode, but ahead of time compiled, and much lower level). Objective-C can be compiled to LLVM using a compiler called clang (C-Language family compiler). Kotlin also compiles to LLVM using kotlinc-native.
For both compilers, once LLVM bitcode is created, a tool called llc can be used to compile the bitcode to a binary.
d
If Kotlin code is compiled to LLVM using kotlinc-native, how does the ObjectiveC code come into the picture?
l
Objective-C doesn’t come into the picture during the Kotlin source -> LLVM step. It only comes into play when running cinterop (which extracts the symbols from Objective-C code and creates Kotlin code that can call that symbol) and the runtime, which needs to know enough about Objective-C, since all Kotlin objects are Objective-C objects (the class was some odd name, like k2objc{some random characters} last I checked).
C family essentially has two outputs: a binary, and a header that describes the binary (Kotlin/Native is the same). The header tells a consuming library information about what symbols are available, the structure of data, and some ABI information.
d
ah ok, now it’s finally clear! I didn’t think about the two parts of C! many thanks for the explanation
Actually, I am still missing some bits… You say that cinterop extracts the symbols from Objective-C code and creates Kotlin code that can call that symbol. But actually we start from Kotlin code, not from Objective-C code. We actually want to translate Kotlin code into an Objective-C framework.
l
When calling Kotlin code from Obj-C, you use the header that Kotlin creates during the compile process. This header describes the symbols and structures the Kotlin compiler creates in a way Obj-C can understand.
d
OK, I think I get it now 🎉 So, Kotlin code gets compiled to LLVM, and it creates an Obj-C header that allows Objective-C to run such code. Thanks again, very clear!
l
Yes. The binary is created by each compiler. The main difference is how they describe the binary. Kotlin can read serialized Kotlin IR and clang can read headers. To go Kotlin -> Obj-C, Kotlin compiler creates a header to describe the binary. To go Obj-C to Kotlin, cinterop translates the header to serialized Kotlin IR.
Interesting extension of this: the Kotlin compiler currently requires all Kotlin files to be sent to the compiler at once, unlike clang, which can compile an individual file. If you wanted to compile Kotlin one file at a time for some definition of ‘fun’, you could technically compile the least dependent Kotlin file, then use cinterop to convert the generated header to Kotlin serialized IR, which you add as a dependency to another Kotlin file, which you compile, and continue this until the whole project is compiled. Not suggesting this is a good idea, just interesting.
d
I am ok with having just 1 binary 😉