Kotlin 代码是如何编译成原生代码的?

Posted

技术标签:

【中文标题】Kotlin 代码是如何编译成原生代码的?【英文标题】:How is Kotlin code compiled into native code? 【发布时间】:2020-01-12 07:01:00 【问题描述】:

官方的 Kotlin/Native documentation 声明 Kotlin/Native

.. 是基于 LLVM 的 Kotlin 编译器后端。

据我所知:

Kotlin 编译器 (kotlinc) 从您的 Kotlin 源文件生成 .class 文件(带有 Java 字节码)。 通用 LLVM 后端(与 Kotlin 无关)采用 LLVM IR 并将其转换为二进制代码。

因此,Kotlin/Native 是否将 Java 字节码转换为 LLVM IR? 如果是这样,说明 Kotlin/Native 是 LLVM 后端是否正确? Kotlin 代码是否被编译到 LLVM IR 中? 如果不是,每个编译步骤的输入和输出是什么? (例如:Kotlin -(kotlinc)-> Java 字节码 -(LLVM 后端-> 本机二进制文件)

This 博客文章指出 Kotlin 前端编译器(我认为它指的是 kotlinc)产生 Kotlin IR,我从未读过。

Kotlin 编译器有一个前端,但有多个后端,具体取决于您用于构建代码的插件。 Kotlin/Native 插件将 Kotlin 中间表示 (IR) 转换为本机代码(即机器可执行的代码)。

这句话对吗?

它告诉你,Java 字节码、本机代码和 javascript 的编译过程是相同的。你编译你的 Kotlin 代码,然后你有 3 个后端编译器来提供预期的输出格式(Java 字节码、JavaScript、二进制代码)。

最终的平台特定二进制文件是否包含原生 Kotlin 标准库,还是动态链接?

【问题讨论】:

【参考方案1】:

Kotlin 编译器有一个前端,但有多个后端,具体取决于您用于构建代码的插件。 Kotlin/Native 插件将 Kotlin 中间表示 (IR) 转换为本机代码(即机器可执行的代码)。

这句话对吗?

是的,非常正确。中间表示 (IR) 是一种通用表示 Kotlin 程序的形式,与平台无关。然后,特定于平台的后端将 IR 转换为最终的二进制形式——Kotlin/JVM 的 JVM 类文件、LLVM 位码和其他元数据打包到 Kotlin/Native 的 *.klib 中。

因此,Kotlin/Native 不会以任何方式处理 JVM 字节码。

中间表示是 Kotlin 编译器的一个实现细节,除了 Kotlin 编译器本身之外,其他任何消费者都不会使用它,因此它不是开发人员应该关心的事情。对于 JVM,它甚至保存在内存中,从不写入二进制文件。对于 Kotlin/Native,它实际上是序列化并写入 *.klib 以供重复使用。

它告诉你,Java 字节码、本机代码和 JavaScript 的编译过程是相同的。你编译你的 Kotlin 代码,然后你有 3 个后端编译器来提供预期的输出格式(Java 字节码、JavaScript、二进制代码)。

其实编译过程的一部分是一样的,即前端语言分析,包括解析、调用解析、类型推断、诊断等不需要的步骤任何特定于平台的代码转换。尽管如此,前端部分还是针对每个平台进行了调整,因为它们允许不同的语言功能集并提供不同的诊断集。

最后一个问题,最终平台特定的二进制文件是否包含原生 Kotlin 标准库?还是动态链接?

目前,标准库静态链接到生成的 Kotlin/Native 二进制文件中。

【讨论】:

所以基本上如果我理解正确的话,即使前端编译器在 3 个编译目标(JVM、JS 和本机)中非常相似,也不只有一种工具可以将 Kotlin 转换为 IR,对吧?每个编译目标都有自己的前端编译器,但如果代码相同,它们特定前端进程的输出会产生相同的 IR?那么位于 klib 中的 IR 是 LLVM IR 还是 Kotlin-specific IR? 对于 JVM,编译过程非常清楚:kotlinc 可以做所有事情,我想 Kotlin/JS 也一样,kotlin2js 可以做任何事情。但是 kotlinc 在里面做了什么?它的步骤是什么? Kotlin /Native 的前端和后端编译器是哪一个?

以上是关于Kotlin 代码是如何编译成原生代码的?的主要内容,如果未能解决你的问题,请参考以下文章

kotlin可以编译成c代码吗

react native 如何将其代码编译成原生应用程序?

如何在 Kotlin 中实现 switch-case 语句

一次搞懂Java如何调用Kotlin的高级特性

一次搞懂Java如何调用Kotlin的高级特性

不会用kotlin?这篇看完不懂,我跪搓衣板