Kotlin Native 项目构建指南:Gradle 与 Makefile 方法详解

Viewed 0

本文通过 Gradle 以及 Makefile 两种方式对 Kotlin Native 项目进行构建,提供了详细的从 C 源码编译、到 Kotlin Native 项目的编译及运行的方法,以及该过程中遇到的问题和解决方案。源码地址可在相关仓库找到。

Kotlin Native 预览版发布后,这里详细介绍它的一些相关内容。Kotlin Native 不是 Jni 的概念,它不仅仅是要与底层代码比如 C、C++ 交互,而且还要绕过 Jvm 直接编译成机器码供系统运行。也就是说,Kotlin 准备丢掉 Java 这根拐杖了。Kotlin Native 的野心不小,它旨在将 Kotlin 编译成除 Java 虚拟机字节码以外的机器码,具有革命性。所以,Kotlin 是一门很牛逼的静态语言,能够覆盖多种平台。

如何编写 Kotlin Native 程序

现在 Kotlin Native 刚刚处在技术预览阶段,离商用目测还需要至少一年的时间,性能优化、标准库、反射等等功能现在尚处于早期的状态。下面介绍怎么编译出一个 HelloWorld 工程。

准备编译器

编译器目前有 Mac、Linux 两个版本,可以编出运行在树莓派、iOS 以及 OS X 和 Linux 系统上的程序。演示运行在 Mac OS X 上,与 Linux 可能稍有差异。

编译器官方有现成可用的版本,不过也建议直接 clone 编译器源码编译,没有复杂的编译步骤。代码拖下来之后,保证网络畅通,运行以下命令下载依赖:

$ ./gradlew dependencies:update

这一步是下载依赖,官方源码使用了 gradle-wrapper,所以如果本地没有 gradle 3.1 的话也会自动下载。运行完成之后,在 dist/dependencies 目录下面看到下载的各种依赖。接着编译:

./gradlew dist

编译时间不长,如果出现错误,可以 clean 多试几次。编译完之后就可以得到编译器。

Gradle 版 HelloWorld

先在 IntelliJ 中创建一个普通的 Gradle 工程,创建好之后,修改 build.gradle 文件,应用 Kotlin Native 插件。配置好之后,创建一个 gradle.properties 文件,加入编译器 home 的配置。当然,这个配置可以不加,那样的话,编译的时候会首先下载一个编译器放到本地。

接着创建一个 kotliner.def 文件,用来配置 c 源码到 kotlin 的映射关系,内容为:

headers=cn_kotliner.h

下面准备源码,在工程目录下面创建 src 目录,在 src/c 目录下面创建 C 头文件和源文件。定义两个函数,一个用来打印 “HelloWorld”,一个用来计算阶乘。接着在 src/c 目录下面,用命令行编译 C 源码:

clang -std=c99 -c cn_kotliner.c -o cn_kotliner.bc -emit-llvm

如果提示找不到 clang 命令,可以去编译器的 dependencies 目录中找。截止到现在,已经编译好 C 源码了。接着创建 kotlin 源码,在 main.kt 中导入并调用 C 函数。

运行 gradle 的 build 任务,编译完成之后,在 build/konan/Kotliner/bin 目录中会生成一个 kexe 文件,命令行运行它即可看到输出。

命令行版 HelloWorld

除了 gradle 构建外,也可以直接使用命令行编译 Kotlin Native。具体步骤类似,首先准备好源码。接着编写 Makefile 或者 build.sh,官方采用了 shell 脚本的方式来构建。一个示例 Makefile 可以指定编译步骤,这样只需要在命令行执行先把编译器 /bin 加入 path,之后执行 make,编译完成之后就可以在输出目录找到可执行文件。

几个重要的坑

Gradle 插件指定包名的问题

gradle konan 插件配置中,可以配置 C 代码映射到 Kotlin 的包名,但如果这样配置,生成的 C 代码标识符中可能含有 “.” 导致无法编译。例如,生成的函数名会包含点号,这不是合法的 C 标识符。这个问题可以通过修改编译器源码解决,已经提交相关修复。

Kotlin 的 main 函数不能有包名

main 函数所在文件不能有 package,如果给这个文件制定一个 package,那么编译器就无法找到入口函数,进而导致编译链接错误。因此,入口文件必须保持无包名。

def 文件的路径

使用 makefile 进行编译时,cinterop 调用时传入的 def 文件的路径必须使用绝对路径或正确相对路径,例如 ./kotliner.def,否则编译器在编译时会出现找不到文件的问题。这个问题也通过修改编译器源码解决。

展望

Kotlin Native 目前处于早期阶段,但开发体验已经非常关注。随着项目的迭代,IntelliJ 对其的支持也会趋于完善,届时开发 Kotlin Native 的程序将更加高效。同时,Kotlin Native 有望支持更多平台,如 Windows 和 Android,从而扩展其应用场景。

Kotlin Native 的出现有希望简化与底层代码的交互,终结 Jni 的痛苦现状,为开发者打开一扇窗户,几乎零成本进入底层代码的编写。此外,Kotlin 从 Jvm 起家,现正在向着各种应用场景用功,各个场景的表现也不错,成为一门擅长多个领域的语言,实现跨平台的大一统愿景。

0 Answers