我想在我的 Kotlin/Native 项目中使用 GLFW,因此我在
.def
:创建了一个
src/nativeInterop/cinterop/glfw3.def
文件
headers = \
glfw3.h \
glfw3native.h
headerFilter = /usr/include/GLFW/*
compilerOpts.linux = \
-I/usr/include \
-I/usr/include/GLFW
linkerOpts.linux = \
-L/usr/lib \
-lc \
-l:libglfw.so.3
并相应地更新了我的
build.gradle.kts
:
plugins {
kotlin("multiplatform") version "1.9.23"
}
// -- snip --
kotlin {
linuxX64("native").apply {
val main by compilations.getting
compilations.getByName("main") {
cinterops {
val glfw3 by creating {
defFile(project.file("src/nativeInterop/cinterop/glfw3.def"))
packageName("glfw3")
}
}
}
binaries {
executable()
}
}
sourceSets {
val nativeMain by getting
val nativeTest by getting
}
}
但是当我尝试在 Arch Linux x86_64 系统上运行此程序时,出现以下错误:
> Task :linkDebugExecutableNative
e: /home/simao/.konan/dependencies/x86_64-unknown-linux-gnu-gcc-8.3.0-glibc-2.19-kernel-4.9-2/x86_64-unknown-linux-gnu/bin/ld.gold invocation reported errors
The /home/simao/.konan/dependencies/x86_64-unknown-linux-gnu-gcc-8.3.0-glibc-2.19-kernel-4.9-2/x86_64-unknown-linux-gnu/bin/ld.gold command returned non-zero exit code: 1.
output:
/usr/lib/libglfw.so.3: error: undefined reference to 'memfd_create', version 'GLIBC_2.27'
/usr/lib/libglfw.so.3: error: undefined reference to 'dlopen', version 'GLIBC_2.34'
/usr/lib/libglfw.so.3: error: undefined reference to 'pthread_key_delete', version 'GLIBC_2.34'
/usr/lib/libglfw.so.3: error: undefined reference to 'dlclose', version 'GLIBC_2.34'
/usr/lib/libglfw.so.3: error: undefined reference to 'powf', version 'GLIBC_2.27'
/usr/lib/libglfw.so.3: error: undefined reference to 'dlsym', version 'GLIBC_2.34'
/usr/lib/libglfw.so.3: error: undefined reference to 'pthread_setspecific', version 'GLIBC_2.34'
/usr/lib/libglfw.so.3: error: undefined reference to 'pthread_getspecific', version 'GLIBC_2.34'
/usr/lib/libglfw.so.3: error: undefined reference to 'pthread_key_create', version 'GLIBC_2.34'
> Task :linkDebugExecutableNative FAILED
4 actionable tasks: 2 executed, 2 up-to-date
FAILURE: Build failed with an exception.
* What went wrong:
Execution failed for task ':linkDebugExecutableNative'.
> Compilation finished with errors
* Try:
> Run with --stacktrace option to get the stack trace.
> Run with --info or --debug option to get more log output.
> Run with --scan to get full insights.
> Get more help at https://help.gradle.org.
BUILD FAILED in 3s
4:47:17 PM: Execution finished 'runDebugExecutableNative'.
更多日志:
/usr/lib/libmvec.so.1: error: undefined reference to 'exp10f', version 'GLIBC_2.32'
/usr/lib/libmvec.so.1: error: undefined reference to 'exp10', version 'GLIBC_2.39'
/usr/lib/libmvec.so.1: error: undefined reference to 'pow', version 'GLIBC_2.29'
/usr/lib/libmvec.so.1: error: undefined reference to 'powf', version 'GLIBC_2.27'
/usr/lib/libmvec.so.1: error: undefined reference to 'log2', version 'GLIBC_2.29'
/usr/lib/libmvec.so.1: error: undefined reference to 'log2f', version 'GLIBC_2.27'
/usr/lib/libmvec.so.1: error: undefined reference to 'logf', version 'GLIBC_2.27'
/usr/lib/libmvec.so.1: error: undefined reference to 'log', version 'GLIBC_2.29'
/usr/lib/libmvec.so.1: error: undefined reference to 'expf', version 'GLIBC_2.27'
/usr/lib/libmvec.so.1: error: undefined reference to 'exp', version 'GLIBC_2.29'
/usr/lib/libmvec.so.1: error: undefined reference to 'exp2f', version 'GLIBC_2.27'
/usr/lib/libmvec.so.1: error: undefined reference to 'exp2', version 'GLIBC_2.29'
/usr/lib/libmvec.so.1: error: undefined reference to 'hypot', version 'GLIBC_2.35'
/usr/lib/libmvec.so.1: error: undefined reference to 'hypotf', version 'GLIBC_2.35'
到目前为止,我的代码仅包含此内容:
fun main() {
}
看到这一点,它让我相信使用的工具链(
/home/simao/.konan/dependencies/x86_64-unknown-linux-gnu-gcc-8.3.0-glibc-2.19-kernel-4.9-2/x86_64-unknown-linux-gnu/
)太旧了,因为它的名称中写着glibc-2.19
,但库 GLFW 使用的是 Glibc 2.27 和 Glibc 3.34 中的符号)。我也很乐意使用涉及静态链接 musl 的解决方案,只要它与 GLFW 配合良好即可。
我也不明白为什么 Kotlin/Native(或 konan)使用 GCC,而据说 Kotlin/Native 使用 LLVM。那么为什么不使用 Clang 来代替呢?
我想在这里做的是更新整个工具链,使用不同的工具链或仅更新 glibc,但不必使用类似
-l:/usr/lib/libc.so.6
之类的东西。
我该怎么做?
尝试使用 freeCompilerArgs += listOf("-linker-option", "--allow-shlib-undefined")
此标志强制链接器允许最终工件中存在未定义的符号。它之所以有效,是因为尽管新符号不存在于 Kotlin/Native sysroot 中,但它们在系统的 glibc 中可用,而后者实际上是在运行时使用的。当然,这会导致在低版本 glibc 的平台上崩溃。