如何在Kotlin/Native项目中使用新版链接器与glibc?
问题:Arch Linux下Kotlin/Native集成GLFW时的GLIBC版本冲突
背景
在Arch Linux x86_64系统的Kotlin/Native项目中集成GLFW,已完成以下配置:
- 创建
src/nativeInterop/cinterop/glfw3.def文件 - 更新
build.gradle.kts配置
但运行时出现GLIBC版本冲突的链接错误,原因是Konan默认工具链依赖glibc 2.19,而系统GLFW依赖更高版本的GLIBC符号。
已配置文件
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 } }
错误日志
链接错误输出
> 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'
需求与疑问
需求
- 希望通过更新/更换工具链、升级glibc解决问题,不接受
-l:/usr/lib/libc.so.6这类强制链接系统库的方式 - 也接受兼容GLFW的musl静态链接方案
疑问
Kotlin/Native宣称基于LLVM,为何Konan默认使用GCC而非Clang?
解决方案
1. 使用系统Clang工具链替代Konan默认工具链
直接让Konan使用Arch系统自带的Clang工具链(匹配系统GLIBC版本),修改build.gradle.kts:
plugins { kotlin("multiplatform") version "1.9.23" } kotlin { linuxX64("native").apply { // 配置使用系统Clang和LLD链接器 toolchain { useClang() linker = org.jetbrains.kotlin.gradle.native.toolchain.Linker.create("/usr/bin/ld.lld") } 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 } }
此方案无需修改glfw3.def,直接复用系统库即可。
2. 切换到musl静态链接方案
musl是轻量级C标准库,静态链接后无需依赖系统GLIBC。步骤如下:
步骤1:编译musl版本的GLFW静态库
Arch官方仓库没有musl版本的GLFW,需自行编译:
git clone https://github.com/glfw/glfw.git cd glfw mkdir build && cd build # 使用musl-gcc编译静态库 CC=musl-gcc cmake .. -DGLFW_BUILD_SHARED_LIBS=OFF -DCMAKE_INSTALL_PREFIX=/usr/local/musl make && sudo make install
步骤2:修改项目配置
更新build.gradle.kts,切换到linuxX64Musl目标:
plugins { kotlin("multiplatform") version "1.9.23" } kotlin { linuxX64Musl("native").apply { compilations.getByName("main") { cinterops { val glfw3 by creating { defFile(project.file("src/nativeInterop/cinterop/glfw3.def")) packageName("glfw3") // 指定musl版本GLFW的头文件路径 compilerOpts("-I/usr/local/musl/include") // 链接musl静态库 linkerOpts("-L/usr/local/musl/lib", "-lglfw", "-lm", "-ldl", "-pthread") } } } binaries { executable { // 添加GLFW静态库 staticLibs.add(file("/usr/local/musl/lib/libglfw.a")) } } } sourceSets { val nativeMain by getting val nativeTest by getting } }
修改glfw3.def:
headers = glfw3.h glfw3native.h headerFilter = /usr/local/musl/include/GLFW/* compilerOpts.linux = -I/usr/local/musl/include -I/usr/local/musl/include/GLFW linkerOpts.linux = -L/usr/local/musl/lib -lglfw -lm -ldl -pthread
3. 升级Konan工具链
检查Kotlin版本更新,新版本的Konan可能使用更高版本的GLIBC工具链。比如升级到Kotlin 1.9.20+,若官方已更新工具链,问题可能直接解决。
疑问解答
Kotlin/Native基于LLVM编译,但Konan默认使用GCC工具链是出于兼容性考虑:
- 早期LLVM的ld链接器在部分Linux发行版上兼容性不如GCC的ld.gold
- GCC工具链提供了更完善的C标准库支持,确保编译出的程序能在多种旧版Linux系统上运行
不过Konan早已支持Clang工具链,用户可通过方案1手动切换,享受LLVM生态的优势。
内容的提问来源于stack exchange,提问作者xdevs23
相关产品推荐
相关产品推荐

