Kotlin/Native 库编译与管理指南
Kotlin/Native 提供了强大的工具来创建和管理库,本文将详细介绍相关编译器和实用程序的使用。
Kotlin 编译器细节
使用 Kotlin/Native 编译器生成库时,需使用 -produce library 或 -p library 标志。例如,命令 kotlinc-native foo.kt -p library -o bar 会生成包含 foo.kt 编译内容的库文件 bar.klib。
要链接到现有库,请使用 -library <库名> 或 -l <库名> 标志。例如,kotlinc-native qux.kt -l bar 将结合 qux.kt 和 bar.klib 生成可执行文件 program.kexe。
cinterop 工具细节
cinterop 工具主要用于为原生库生成 .klib 包装。例如,使用 Kotlin/Native 发行版中的 libgit2.def 定义文件,运行命令 cinterop -def samples/gitchurn/src/nativeInterop/cinterop/libgit2.def -compiler-option -I/usr/local/include -o libgit2 即可得到 libgit2.klib。更多关于 C 交互操作的详细信息,请参考 C Interop。
klib 实用程序
klib 是一个库管理实用程序,支持探查、安装和删除库。常用命令包括:
content:列出库内容,如klib contents <库名>。info:查看库的详细信息,如klib info <库名>。install:将库安装到默认位置,如klib install <库名>。remove:从默认存储库中删除库,如klib remove <库名>。
所有命令都支持 -repository <目录> 参数来指定非默认存储库,例如 klib <命令> <库名> -repository <目录>。
示例:创建和使用库
以下是一个完整示例,演示如何创建库并用于程序编译。
首先,创建库源代码文件 kotlinizer.kt:
package kotlinizer
val String.kotlinized
get() = "Kotlin $this"
使用编译器生成库:
$ kotlinc-native kotlinizer.kt -p library -o kotlinizer
生成 kotlinizer.klib 文件后,可以查看其内容:
$ klib contents kotlinizer
将库安装到默认存储库:
$ klib install kotlinizer
删除本地库文件:
$ rm kotlinizer.klib
创建一个使用该库的程序 use.kt:
import kotlinizer.*
fun main(args: Array<String>) {
println("Hello, ${"world".kotlinized}!")
}
编译程序并链接库:
$ kotlinc-native use.kt -l kotlinizer -o kohello
运行程序:
$ ./kohello.kexe
Hello, Kotlin world!
通过这个示例,可以体验 Kotlin/Native 库的完整工作流程。
高级主题
库搜索顺序
当使用 -library foo 标志时,编译器按以下顺序搜索库:
- 当前编译目录或绝对路径。
- 通过
-repo标志指定的所有存储库。 - 安装在默认存储库中的库(默认为
~/.konan,可通过设置kotlin.data.dirGradle 属性或使用-Xkonan-data-dir编译器选项自定义)。 - 安装在
$installation/klib目录中的库。
库格式
Kotlin/Native 库文件(.klib)是包含预定义目录结构的 ZIP 文件。解压后,典型布局如下:
foo/
$component_name/
ir/
# 序列化的 Kotlin IR
targets/
$platform/
kotlin/
# Kotlin 编译为 LLVM 位码
native/
# 附加原生对象的位码文件
$another_platform/
# 其他平台相关文件
linkdata/
# 序列化链接元数据的 ProtoBuf 文件
resources/
# 普通资源(目前未使用)
manifest
# 描述库的 Java 属性文件
可以在安装的 klib/stdlib 目录中查看示例布局。
在 klib 中使用相对路径
从 Kotlin 1.6.20 开始,支持在 klib 中使用相对路径。序列化的 IR 表示包含文件路径用于生成调试信息,默认使用绝对路径。通过 -Xklib-relative-path-base 编译器选项,可以改为使用相对路径。需要将一个或多个源文件基路径作为参数传递。
例如,在 Kotlin Gradle 任务中配置:
import org.jetbrains.kotlin.gradle.tasks.KotlinCompilationTask
// ...
tasks.named<KotlinCompilationTask<*>>("compileKotlin").configure {
compilerOptions.freeCompilerArgs.add("-Xklib-relative-path-base=$base")
}
或在 Groovy 中:
import org.jetbrains.kotlin.gradle.tasks.KotlinCompilationTask
// ...
tasks.named('compileKotlin', KotlinCompilationTask) {
compilerOptions {
freeCompilerArgs.add("-Xklib-relative-path-base=$base")
}
}
这样,库中的路径将基于指定基路径以相对形式存储。