Kotlin Native 实战开发
17/100
发布文章
xiangzhihong8
注:本部分内容来源于《Kotlin 入门与实战》,预计 9 月上市。
16.1 Kotlin Native
16.1.1 Kotlin Native 简介
Kotlin Native 是一种将 Kotlin 源码编译成不需要任何 VM 支持的目标平台二进制数据的技术,编译后的二进制数据可以直接运行在目标平台上,它主要包含一个基于 LLVM 的后端编译器的和一个 Kotlin 本地运行时库。设计 Kotlin Native 的目的是为了支持在非 JVM 环境下进行编程,如在嵌入式平台和 iOS 环境下,如此一来,Kotlin 就可以运行在非 JVM 平台环境下。
LLVM 是 Low Level Virtual Machine 的缩写,是一种比较底层的虚拟机技术,LLVM 由 C ++ 编写而成,主要用来优化应用程序的编译时间 (compile-time)、链接时间(link-time)、运行时间(run-time) 以及空闲时间(idle-time)。LLVM 可以有效的解决编译器重复编译代码的问题,并且 LLVM 制定了 LLVM IR 这种中间代码表示语言,LLVM IR 充分考虑了各种应用场景,有效的提高了代码的编译效率。
在讲解 Kotlin Native 具体的知识之前,先来看一下计算机高级语言常见两种流派:编译型语言和解释型语言。
所谓编译型语言,是指使用专门的编译器、针对特定平台 / 操作系统将某种高级语言源代码一次性编译成该平台硬件能够执行的机器码,编译生成的可执行程序可以脱离开发环境,在特定的平台上独立运行。因为编译型语言是一次性编译成机器码的,所以可以脱离开发环境独立运行,而且通常运行效率较高。不过,正因为编译型语言只能被编译成特定平台上的机器码,所以生成的可执行程序通常无法移植到其他平台上运行。例如,现在比较流行的 C、C++ 等高级编程语言都属于编译型语言。
而所谓解释型语言,是指使用专门的解释器对源程序进行逐行解释,并生成特定平台的机器码并立即执行的编程语言。解释型语言通常不需要进行整体的编译和链接处理,解释型语言会把编译型语言中的编译和解释过程混合在一起执行。虽然解释型语言运行效率较低且不能脱离释器独立运行,但解释型语言可以很方便的实现源程序的移植和运行。
16.1.2 Kotlin Native 编译器
目前,Kotlin Native 主要提供了 Mac、Linux 和 Windows 三个主流平台的编译器,使用该编译器可以很轻松的编译出运行在树莓派、iOS、OS X、Windows 以及 Linux 系统上的程序。Kotlin Native 支持平台和版本如下表所示。
支持的系统平台 支持的版本
Windows x86_64
Linux x86_64、arm32、MIPS、MIPS 小端
MacOS x86_64
iOS arm64
Android arm32、arm64
WebAssembly wasm32
表 16-1 Kotlin Native 支持平台及其版本
编译 Kotlin Native 项目,首先需要到 Github 上下载 Kotlin Native 的编译器软件包,下载地址为:https://github.com/JetBrains/…,使用前下载对应的平台版本即可,下载后解压下载的 Kotlin Native 编译器软件包,其目录结构如图 16- 1 所示。
图 16-1 Kotlin Native 编译器目录结构图
当然,也可以通过克隆 Kotlin Native 编译器的源码进行编译,编译需要先到 Github 上下载编译器源码,下载地址为:https://github.com/JetBrains/…。下载完成后,使用如下命令下载依赖关系,命令如下:
./gradlew dependencies:update
然后,建立编译器和库的关联。
./gradlew bundle
如果需要构建整个项目可能需要很长的时间。然后,使用以下的命令即可编译项目。
./gradlew dist distPlatformLibs
到此,就可以得到 Kotlin 的 Native 编译器了,它通常位于项目的./dist/bin 目录下,打开 bin 文件可以看到 Native 编译器的相关信息,它有 7 个可执行程序构成,如图 15- 2 所示。通过对比发现,Native 编译器的目录结构和 Kotlin Native 官方提供的编译器的内容是一样的。然后,就可以利用 Native 编译器编译应用程序了。例如:
export PATH=./dist/bin:$PATH
kotlinc hello.kt -o hello
如果需要进行优化编译,可以使用 -opt 参数。
kotlinc hello.kt -o hello -opt
如果需要对应用程序进行测试,可以使用类似于下面的命令。
./gradlew backend.native:tests:run
图 16-2 Kotlin 的 Native 编译器目录结构
在 Kotlin Native 官方提供的示例中,系统自带了针对不同平台的例子,并且这些例子都是可以直接编译运行的。由于 Kotlin Native 本身是一个 gradle 构建的项目,所以可以使用 idea 直接打开 Kotlin Native 目录下的 samples 文件,idea 会自动识别该项目。
16.1.3 编译器 konan
打开 kotlin-native-macos-0.6 文件,其目录结构如图 15- 3 所示。其中,bin 目录包含众多的与 Kotlin Native 相关的执行命令,klib 目录则主要包含 Kotlin 的标准库的关联元数据文件以及针对各个目标平台的 bc 文件,konan 主要包含编译器依赖的一些 jar 包和一些已经编译好的项目实例,可以使用 IntelliJ IDEA 直接导入。
图 16-3 编译器 konan 目录结构
打开 Kotlin Native 编译器的 bin 目录可以发现,bin 文件主要由 cinterop、jsinterop、klib、konanc、kotlinc、kotlinc-native、run_konan 等 7 个可执行文件组成。其中,run_konan 是编译器真正的入口,源码如下。
TOOL_NAME="$1"
shift
if [-z "$JAVACMD" -a -n "$JAVA_HOME" -a -x "$JAVA_HOME/bin/java"]; then
JAVACMD="$JAVA_HOME/bin/java"
else
JAVACMD=java
fi
[-n "$JAVACMD"] || JAVACMD=java
// 省略部分代码
LIBCLANG_DISABLE_CRASH_RECOVERY=1 \
$TIMECMD "$JAVACMD" "${java_opts[@]}" "${java_args[@]}" -cp "$KONAN_CLASSPATH" "$TOOL_CLASS" "$TOOL_NAME" "${konan_args[@]}"
可以发现,Kotlin Native 编译器 konan 的运行环境还是需要 JVM 环境支持的,但是它生成的机器码的可执行程序是不需要 JVM 环境支持的,可以直接运行在对应的平台系统上。
16.2 Kotlin Native 实例
16.2.1 构建 Kotlin Native 项目
首先,在 IDEA 中依次选择【File】→【New】→【Project】创建一个普通的 Gradle 工程。
图 16-4 创建 Gradle 工程
16.2.2 添加 konan 插件配置
创建完成之后,需要修改 build.gradle 文件配置。打开 build.gradle 文件并添加如下配置。
buildscript {
repositories {mavenCentral()
maven {url "https://dl.bintray.com/jetbrains/kotlin-native-dependencies"}
}
dependencies {classpath "org.jetbrains.kotlin:kotlin-native-gradle-plugin:0.5"}
}
apply plugin: 'konan'
其中,kotlin-native-gradle-plugin:0.5 是 Gradle 构建 Kotlin Native 工程所使用的 DSL 插件,这个插件发布在 https://dl.bintray.com/jetbra…。除此之外,还需要应用 konan 插件,konan 插件是用来将 Kotlin 代码编译为 native 代码的插件,可以通过如下地址来获取更多 konan 相关的信息。
https://github.com/JetBrains/kotlin-native/blob/master/GRADLE_PLUGIN.md
此时,还需要创建一个 kotliner.def 文件,该文件主要用来配置 C 源码到 Kotlin 的映射关系。
headers=cn_kotliner.h
16.2.3 编写源代码
接下来,在工程的 src 目录下新建一个 c 目录,此目录专门用来存放 C 代码。首先,创建两个 c 文件:cn_kotliner.h 和 cn_kotliner.c。其中,C 头文件声明的代码如下。
#ifndef CN_KOTLINER_H
#define CN_KOTLINER_H
void printHello();
int factorial(int n);
#endif
在上面的代码中,主要声明了两个函数,打印 HelloWorld 的 printHello 函数和用来计算阶乘的 factorial 函数。cn_kotlinor.c 的源代码如下:
#include "cn_kotliner.h"
#include <stdio.h>
void printHello(){printf("[C]HelloWorld\n");
}
int factorial(int n){printf("[C]calc factorial: %d\n", n);
if(n == 0) return 1;
return n * factorial(n - 1);
}
接下来,还需要创建一个 kotlin 文件,该文件主要是调用 C 层的代码,实现跨平台调用。该文件的源码如下:
import kotliner.*
fun main(args: Array<String>) {printHello()
(1..5).map(::factorial).forEach(::println)
}
其中,导入的 kotlinor.* 包是 C 语言代码经过 clang 编译后对应的 C 接口的包路径,可以在项目的 build.gradle 配置文件中的 konanInterop 中配置这个路径。
图 16-5 Kotlin Native 项目目录结构图
16.2.4 添加 konanInterop 与 konanArtifacts 配置
接下来,还需要添加 konanInterop 和 konanArtifacts 相关的配置信息。其中,konanInterop 主要用来配置 Kotlin 调用 C 的接口。相关的源码如下:
konanInterop {
ckotlinor {
defFile 'kotlinor.def' // interop 配置文件
includeDirs "src/c" // C 头文件目录,可以传入多个
}
}
在上面的配置文件中,ckotlinor 是插件中的 KonanInteropConfig 对象,在 konanArtifacts 配置中会引用这个 ckotlinor。而 kotlinor.def 是 Kotlin Native 与 C 语言互操作的配置文件,可以在 kotlinor.def 里面配置 C 源码到 Kotlin 的映射关系,该配置文件的内容如下。
headers=cn_kotlinor.h
compilerOpts=-Isrc/c
除此上面使用的选项之外,konanInterop 还提供了如下常用的选项。
konanInterop {
pkgName {
defFile <def-file>
pkg <package with stubs>
target <target: linux/macbook/iphone/iphone_sim>
compilerOpts <Options for native stubs compilation>
linkerOpts <Options for native stubs >
headers <headers to process>
includeDirs <directories where headers are located>
linkFiles <files which will be linked with native stubs>
dumpParameters <Option to print parameters of task before execution>
}
}
konanInterop 配置参数选项对应的具体含义如下表所示。
配置选项 选项说明
defFile 互操作映射关系配置文件
pkg C 头文件编译后映射为 Kotlin 的包名
target 编译目标平台:linux/macbook/iphone 等
compilerOpts 编译选项
linkerOpts 链接选项
headers 需要处理的头文件
includeDirs 包括头文件的目录
linkFiles 与 native stubs 链接的文件
dumpParameters 打印 Gradle 任务参数的选项配置
表 16-2 konanInterop 配置选项说明表
接下来,需要为项目添加 konanArtifacts 相关的配置,该配置主要用来处理编译任务的执行。
konanArtifacts {
KotlinorClient {inputFiles fileTree("src/kotlin") //kotlin 代码配置,项目入口 main()
useInterop 'ckotlinor' // 前面的 interop 配置
nativeLibrary fileTree('src/c/cn_kotlinor.bc') // 本地库文件配置
target 'macbook' // 编译的目标平台
}
}
konan 编译任务配置的处理类是 KonanCompileTask.kt,可以在 Kotlin Native 的 kotlin-native-gradle-plugin 插件中找到该类。可以通过以下地址来获取更详细的 konan 插件配置信息。
https://github.com/JetBrains/kotlin-native/blob/master/GRADLE_PLUGIN.md
16.2.5 编译与执行
接下来,在项目的 src/ c 目录下面,用命令行编译上面的代码,命令如下。
clang -std=c99 -c cn_kotliner.c -o cn_kotliner.bc -emit-llvm
其中,clang 是一个由 C ++ 编写的基于 LLVM 的 C /C++/Objective-C/Objective-C++ 编译器。如果提示找不到 clang 命令,可以在编译器的 dependencies 目录中找到相关的内容。当然,还可以使用 shell 脚本(名称为 kclang.sh)来简化 clang 编译的命令行输入参数。
#!/usr/bin/env bash clang -std=c99 -c $1 -o $2 -emit-llvm
接着把 kclang.sh 放到 C 代码目录下,然后使用脚本来编译 C 代码。例如:
kclang.sh cn_kotlinor.c cn_kotlinor.bc
通过上面的命令编译之后,将得到一个名为 cn_kotlinor.bc 的库文件。最后,在执行 Gradle 构建之前,还需要指定 konan 编译器主目录。具体的,在工程根目录下面新建一个 gradle.properties 属性配置文件,该文件格式如下。
konan.home=< 编译器路径 >
例如:
konan.home=/Users/xiangzhihong /kotlin native/kotlin-native-macos-0.5
当然,也可以不添加 gradle.properties 配置文件,那样的话,只需要在编译的时候使用本地的编译器即可。
然后,在 IDEA 的 Gradle 工具栏依次点击【Tasks】→【build】执行构建操作,如图 15- 5 所示。等待项目构建完成,会在项目的 build/konan/bin/ 目录下面生成一个 KotlinorClient.kexe 的可执行程序,它可以直接运行在 Mac OS 系统上而不再需要依赖 JVM 环境。
图 16-5 使用 Gradle 工具栏编译项目
然后,在命令行中执行 KotlinorApp.kexe 命令,即可看到输出结果,对应的命令如下。
build/konan/bin/KotlinorApp.kexe
可以看到,作为一款致力于跨平台开发的编程语言,Kotlin Native 非常注重语言平台的互操作性,可以说,使用 Kotlin Native 进行跨平台开发优势是非常明显的。
16.2.6 命令行方式编译 Kotlin Native
对于 Kotlin Native 项目来说,除了允许 Gradle 方式构建编译外,还可以使用命令行的方式来编译项目。具体来说,编写完 Kotlin 源码之后,采用 shell 脚本的方式来构建,或者使用 Makefile 或 build.sh 的方式来构建,官方推荐使用 shell 脚本构建方式,本篇采用与之类似的 Makefile 脚本方式。例如:
build : src/kotlin/main.kt kotliner.kt.bc
konanc src/kotlin/main.kt -library build/kotliner/kotliner.kt.bc -nativelibrary build/kotliner/cn_kotliner.bc -o build/kotliner/kotliner.kexe
kotliner.kt.bc : kotliner.bc kotliner.def
cinterop -def ./kotliner.def -o build/kotliner/kotliner.kt.bc
kotliner.bc : src/c/cn_kotliner.c src/c/cn_kotliner.h
mkdir -p build/kotliner
clang -std=c99 -c src/c/cn_kotliner.c -o build/kotliner/cn_kotliner.bc -emit-llvm
clean:
rm -rf build/kotliner
采用命令行方式编译 Kotlin Native 时,需要先把编译器 <konan.home>/bin
目录加入系统的 path 环境中,然后再执行 make 命令,编译完成之后就可以在项目的 build/kotliner 目录中找到 kotliner.kexe 文件。
图书链接:Kotlin 入门与实战
注:本部分内容来源于《Kotlin 入门与实战》,预计 9 月上市。
16.1 Kotlin Native
16.1.1 Kotlin Native 简介
Kotlin Native 是一种将 Kotlin 源码编译成不需要任何 VM 支持的目标平台二进制数据的技术,编译后的二进制数据可以直接运行在目标平台上,它主要包含一个基于 LLVM 的后端编译器的和一个 Kotlin 本地运行时库。设计 Kotlin Native 的目的是为了支持在非 JVM 环境下进行编程,如在嵌入式平台和 iOS 环境下,如此一来,Kotlin 就可以运行在非 JVM 平台环境下。
LLVM 是 Low Level Virtual Machine 的缩写,是一种比较底层的虚拟机技术,LLVM 由 C ++ 编写而成,主要用来优化应用程序的编译时间 (compile-time)、链接时间(link-time)、运行时间(run-time) 以及空闲时间(idle-time)。LLVM 可以有效的解决编译器重复编译代码的问题,并且 LLVM 制定了 LLVM IR 这种中间代码表示语言,LLVM IR 充分考虑了各种应用场景,有效的提高了代码的编译效率。
在讲解 Kotlin Native 具体的知识之前,先来看一下计算机高级语言常见两种流派:编译型语言和解释型语言。
所谓编译型语言,是指使用专门的编译器、针对特定平台 / 操作系统将某种高级语言源代码一次性编译成该平台硬件能够执行的机器码,编译生成的可执行程序可以脱离开发环境,在特定的平台上独立运行。因为编译型语言是一次性编译成机器码的,所以可以脱离开发环境独立运行,而且通常运行效率较高。不过,正因为编译型语言只能被编译成特定平台上的机器码,所以生成的可执行程序通常无法移植到其他平台上运行。例如,现在比较流行的 C、C++ 等高级编程语言都属于编译型语言。
而所谓解释型语言,是指使用专门的解释器对源程序进行逐行解释,并生成特定平台的机器码并立即执行的编程语言。解释型语言通常不需要进行整体的编译和链接处理,解释型语言会把编译型语言中的编译和解释过程混合在一起执行。虽然解释型语言运行效率较低且不能脱离释器独立运行,但解释型语言可以很方便的实现源程序的移植和运行。
16.1.2 Kotlin Native 编译器
目前,Kotlin Native 主要提供了 Mac、Linux 和 Windows 三个主流平台的编译器,使用该编译器可以很轻松的编译出运行在树莓派、iOS、OS X、Windows 以及 Linux 系统上的程序。Kotlin Native 支持平台和版本如下表所示。
支持的系统平台 支持的版本
Windows x86_64
Linux x86_64、arm32、MIPS、MIPS 小端
MacOS x86_64
iOS arm64
Android arm32、arm64
WebAssembly wasm32
表 16-1 Kotlin Native 支持平台及其版本
编译 Kotlin Native 项目,首先需要到 Github 上下载 Kotlin Native 的编译器软件包,下载地址为:https://github.com/JetBrains/…,使用前下载对应的平台版本即可,下载后解压下载的 Kotlin Native 编译器软件包,其目录结构如图 16- 1 所示。
这里写图片描述
图 16-1 Kotlin Native 编译器目录结构图
当然,也可以通过克隆 Kotlin Native 编译器的源码进行编译,编译需要先到 Github 上下载编译器源码,下载地址为:https://github.com/JetBrains/…。下载完成后,使用如下命令下载依赖关系,命令如下:
./gradlew dependencies:update
然后,建立编译器和库的关联。
./gradlew bundle
如果需要构建整个项目可能需要很长的时间。然后,使用以下的命令即可编译项目。
./gradlew dist distPlatformLibs
到此,就可以得到 Kotlin 的 Native 编译器了,它通常位于项目的./dist/bin 目录下,打开 bin 文件可以看到 Native 编译器的相关信息,它有 7 个可执行程序构成,如图 15- 2 所示。通过对比发现,Native 编译器的目录结构和 Kotlin Native 官方提供的编译器的内容是一样的。然后,就可以利用 Native 编译器编译应用程序了。例如:
export PATH=./dist/bin:$PATH
kotlinc hello.kt -o hello
如果需要进行优化编译,可以使用 -opt 参数。
kotlinc hello.kt -o hello -opt
如果需要对应用程序进行测试,可以使用类似于下面的命令。
./gradlew backend.native:tests:run
这里写图片描述
图 16-2 Kotlin 的 Native 编译器目录结构
在 Kotlin Native 官方提供的示例中,系统自带了针对不同平台的例子,并且这些例子都是可以直接编译运行的。由于 Kotlin Native 本身是一个 gradle 构建的项目,所以可以使用 idea 直接打开 Kotlin Native 目录下的 samples 文件,idea 会自动识别该项目。
16.1.3 编译器 konan
打开 kotlin-native-macos-0.6 文件,其目录结构如图 15- 3 所示。其中,bin 目录包含众多的与 Kotlin Native 相关的执行命令,klib 目录则主要包含 Kotlin 的标准库的关联元数据文件以及针对各个目标平台的 bc 文件,konan 主要包含编译器依赖的一些 jar 包和一些已经编译好的项目实例,可以使用 IntelliJ IDEA 直接导入。
这里写图片描述
图 16-3 编译器 konan 目录结构
打开 Kotlin Native 编译器的 bin 目录可以发现,bin 文件主要由 cinterop、jsinterop、klib、konanc、kotlinc、kotlinc-native、run_konan 等 7 个可执行文件组成。其中,run_konan 是编译器真正的入口,源码如下。
TOOL_NAME=”$1″
shift
if [-z “$JAVACMD” -a -n “$JAVA_HOME” -a -x “$JAVA_HOME/bin/java”]; then
JAVACMD="$JAVA_HOME/bin/java"
else
JAVACMD=java
fi
[-n “$JAVACMD”] || JAVACMD=java
// 省略部分代码
LIBCLANG_DISABLE_CRASH_RECOVERY=1 \
$TIMECMD “$JAVACMD” “${java_opts[@]}” “${java_args[@]}” -cp “$KONAN_CLASSPATH” “$TOOL_CLASS” “$TOOL_NAME” “${konan_args[@]}”
可以发现,Kotlin Native 编译器 konan 的运行环境还是需要 JVM 环境支持的,但是它生成的机器码的可执行程序是不需要 JVM 环境支持的,可以直接运行在对应的平台系统上。
16.2 Kotlin Native 实例
16.2.1 构建 Kotlin Native 项目
首先,在 IDEA 中依次选择【File】→【New】→【Project】创建一个普通的 Gradle 工程。
这里写图片描述
图 16-4 创建 Gradle 工程
16.2.2 添加 konan 插件配置
创建完成之后,需要修改 build.gradle 文件配置。打开 build.gradle 文件并添加如下配置。
buildscript {
repositories {mavenCentral()
maven {url "https://dl.bintray.com/jetbrains/kotlin-native-dependencies"}
}
dependencies {classpath "org.jetbrains.kotlin:kotlin-native-gradle-plugin:0.5"}
}
apply plugin: ‘konan’
其中,kotlin-native-gradle-plugin:0.5 是 Gradle 构建 Kotlin Native 工程所使用的 DSL 插件,这个插件发布在 https://dl.bintray.com/jetbra…。除此之外,还需要应用 konan 插件,konan 插件是用来将 Kotlin 代码编译为 native 代码的插件,可以通过如下地址来获取更多 konan 相关的信息。
https://github.com/JetBrains/…
此时,还需要创建一个 kotliner.def 文件,该文件主要用来配置 C 源码到 Kotlin 的映射关系。
headers=cn_kotliner.h
16.2.3 编写源代码
接下来,在工程的 src 目录下新建一个 c 目录,此目录专门用来存放 C 代码。首先,创建两个 c 文件:cn_kotliner.h 和 cn_kotliner.c。其中,C 头文件声明的代码如下。
ifndef CN_KOTLINER_H
define CN_KOTLINER_H
void printHello();
int factorial(int n);
endif
在上面的代码中,主要声明了两个函数,打印 HelloWorld 的 printHello 函数和用来计算阶乘的 factorial 函数。cn_kotlinor.c 的源代码如下:
include “cn_kotliner.h”
include <stdio.h>
void printHello(){
printf("[C]HelloWorld\n");
}
int factorial(int n){
printf("[C]calc factorial: %d\n", n);
if(n == 0) return 1;
return n * factorial(n - 1);
}
接下来,还需要创建一个 kotlin 文件,该文件主要是调用 C 层的代码,实现跨平台调用。该文件的源码如下:
import kotliner.*
fun main(args: Array<String>) {
printHello()
(1..5).map(::factorial).forEach(::println)
}
其中,导入的 kotlinor.* 包是 C 语言代码经过 clang 编译后对应的 C 接口的包路径,可以在项目的 build.gradle 配置文件中的 konanInterop 中配置这个路径。
这里写图片描述
图 16-5 Kotlin Native 项目目录结构图
16.2.4 添加 konanInterop 与 konanArtifacts 配置
接下来,还需要添加 konanInterop 和 konanArtifacts 相关的配置信息。其中,konanInterop 主要用来配置 Kotlin 调用 C 的接口。相关的源码如下:
konanInterop {
ckotlinor {
defFile 'kotlinor.def' // interop 配置文件
includeDirs "src/c" // C 头文件目录,可以传入多个
}
}
在上面的配置文件中,ckotlinor 是插件中的 KonanInteropConfig 对象,在 konanArtifacts 配置中会引用这个 ckotlinor。而 kotlinor.def 是 Kotlin Native 与 C 语言互操作的配置文件,可以在 kotlinor.def 里面配置 C 源码到 Kotlin 的映射关系,该配置文件的内容如下。
headers=cn_kotlinor.h
compilerOpts=-Isrc/c
除此上面使用的选项之外,konanInterop 还提供了如下常用的选项。
konanInterop {
pkgName {
defFile <def-file>
pkg <package with stubs>
target <target: linux/macbook/iphone/iphone_sim>
compilerOpts <Options for native stubs compilation>
linkerOpts <Options for native stubs >
headers <headers to process>
includeDirs <directories where headers are located>
linkFiles <files which will be linked with native stubs>
dumpParameters <Option to print parameters of task before execution>
}
}
konanInterop 配置参数选项对应的具体含义如下表所示。
配置选项 选项说明
defFile 互操作映射关系配置文件
pkg C 头文件编译后映射为 Kotlin 的包名
target 编译目标平台:linux/macbook/iphone 等
compilerOpts 编译选项
linkerOpts 链接选项
headers 需要处理的头文件
includeDirs 包括头文件的目录
linkFiles 与 native stubs 链接的文件
dumpParameters 打印 Gradle 任务参数的选项配置
表 16-2 konanInterop 配置选项说明表
接下来,需要为项目添加 konanArtifacts 相关的配置,该配置主要用来处理编译任务的执行。
konanArtifacts {
KotlinorClient {inputFiles fileTree("src/kotlin") //kotlin 代码配置,项目入口 main()
useInterop 'ckotlinor' // 前面的 interop 配置
nativeLibrary fileTree('src/c/cn_kotlinor.bc') // 本地库文件配置
target 'macbook' // 编译的目标平台
}
}
konan 编译任务配置的处理类是 KonanCompileTask.kt,可以在 Kotlin Native 的 kotlin-native-gradle-plugin 插件中找到该类。可以通过以下地址来获取更详细的 konan 插件配置信息。
https://github.com/JetBrains/…
16.2.5 编译与执行
接下来,在项目的 src/ c 目录下面,用命令行编译上面的代码,命令如下。
clang -std=c99 -c cn_kotliner.c -o cn_kotliner.bc -emit-llvm
其中,clang 是一个由 C ++ 编写的基于 LLVM 的 C /C++/Objective-C/Objective-C++ 编译器。如果提示找不到 clang 命令,可以在编译器的 dependencies 目录中找到相关的内容。当然,还可以使用 shell 脚本(名称为 kclang.sh)来简化 clang 编译的命令行输入参数。
!/usr/bin/env bash clang -std=c99 -c $1 -o $2 -emit-llvm
接着把 kclang.sh 放到 C 代码目录下,然后使用脚本来编译 C 代码。例如:
kclang.sh cn_kotlinor.c cn_kotlinor.bc
通过上面的命令编译之后,将得到一个名为 cn_kotlinor.bc 的库文件。最后,在执行 Gradle 构建之前,还需要指定 konan 编译器主目录。具体的,在工程根目录下面新建一个 gradle.properties 属性配置文件,该文件格式如下。
konan.home=< 编译器路径 >
例如:
konan.home=/Users/xiangzhihong /kotlin native/kotlin-native-macos-0.5
当然,也可以不添加 gradle.properties 配置文件,那样的话,只需要在编译的时候使用本地的编译器即可。
然后,在 IDEA 的 Gradle 工具栏依次点击【Tasks】→【build】执行构建操作,如图 15- 5 所示。等待项目构建完成,会在项目的 build/konan/bin/ 目录下面生成一个 KotlinorClient.kexe 的可执行程序,它可以直接运行在 Mac OS 系统上而不再需要依赖 JVM 环境。
这里写图片描述
图 16-5 使用 Gradle 工具栏编译项目
然后,在命令行中执行 KotlinorApp.kexe 命令,即可看到输出结果,对应的命令如下。
build/konan/bin/KotlinorApp.kexe
可以看到,作为一款致力于跨平台开发的编程语言,Kotlin Native 非常注重语言平台的互操作性,可以说,使用 Kotlin Native 进行跨平台开发优势是非常明显的。
16.2.6 命令行方式编译 Kotlin Native
对于 Kotlin Native 项目来说,除了允许 Gradle 方式构建编译外,还可以使用命令行的方式来编译项目。具体来说,编写完 Kotlin 源码之后,采用 shell 脚本的方式来构建,或者使用 Makefile 或 build.sh 的方式来构建,官方推荐使用 shell 脚本构建方式,本篇采用与之类似的 Makefile 脚本方式。例如:
build : src/kotlin/main.kt kotliner.kt.bc
konanc src/kotlin/main.kt -library build/kotliner/kotliner.kt.bc -nativelibrary build/kotliner/cn_kotliner.bc -o build/kotliner/kotliner.kexe
kotliner.kt.bc : kotliner.bc kotliner.def
cinterop -def ./kotliner.def -o build/kotliner/kotliner.kt.bc
kotliner.bc : src/c/cn_kotliner.c src/c/cn_kotliner.h
mkdir -p build/kotliner
clang -std=c99 -c src/c/cn_kotliner.c -o build/kotliner/cn_kotliner.bc -emit-llvm
clean:
rm -rf build/kotliner
采用命令行方式编译 Kotlin Native 时,需要先把编译器 <konan.home>/bin 目录加入系统的 path 环境中,然后再执行 make 命令,编译完成之后就可以在项目的 build/kotliner 目录中找到 kotliner.kexe 文件。
在这里插入图片描述
图书链接:Kotlin 入门与实战
Markdown 已选中 8144 字数 306 行数 当前行 306, 当前列 56 HTML 7545 字数 177 段落