能否从CMake构建的原生库生成Kotlin .def文件?
生成Kotlin Native互用所需.def文件的规范CMake实现
针对跨平台(Linux多版本+Windows)的CMake原生库项目,要生成符合Kotlin Native互用要求的.def文件,以下是基于CMake规范机制的实现方案,避免手动维护或简单FILE命令拼接的不严谨问题:
核心思路
利用CMake的目标依赖管理+跨平台符号提取工具,自动收集库的公开导出符号并生成.def文件,确保符号列表与库的实际导出内容同步。
1. 配置库目标与自定义生成任务
在主CMakeLists.txt中定义原生库目标,并添加自定义任务触发.def文件生成:
# 定义你的原生库目标 add_library(MyNativeLib SHARED src/core.c src/utils.cpp ) # 声明公开头文件目录(确保符号被正确导出) target_include_directories(MyNativeLib PUBLIC include) # 添加自定义目标:生成.def文件,依赖库构建完成 add_custom_target(GenerateKotlinDef ALL COMMAND ${CMAKE_COMMAND} -D TARGET_NAME=MyNativeLib -D OUTPUT_DEF=${CMAKE_CURRENT_BINARY_DIR}/MyNativeLib.def -P ${CMAKE_CURRENT_SOURCE_DIR}/GenerateDef.cmake DEPENDS MyNativeLib COMMENT "Generating .def file for Kotlin Native interop" )
2. 编写跨平台符号提取脚本(GenerateDef.cmake)
创建独立的CMake脚本,适配Windows和Linux的符号提取工具,过滤有效导出符号:
# 获取库文件的实际路径 get_target_property(LIB_FILE_PATH ${TARGET_NAME} LOCATION) # 跨平台提取导出符号 if(WIN32) # Windows使用dumpbin工具提取导出表 execute_process( COMMAND dumpbin /EXPORTS ${LIB_FILE_PATH} OUTPUT_VARIABLE RAW_SYMBOLS ) # 过滤出有效符号(跳过序号、类型标记,仅保留符号名) string(REGEX MATCHALL "[0-9]+ +[A-Z0-9]+ +[0-9]+ +([_a-zA-Z0-9]+)" FILTERED_MATCHES ${RAW_SYMBOLS}) else() # Linux使用nm工具提取动态符号 execute_process( COMMAND nm -D ${LIB_FILE_PATH} OUTPUT_VARIABLE RAW_SYMBOLS ) # 过滤出公开的函数(T标记)和全局变量(D标记) string(REGEX MATCHALL "[0-9a-f]+ [TD] +([_a-zA-Z0-9]+)" FILTERED_MATCHES ${RAW_SYMBOLS}) endif() # 生成.def文件内容 file(WRITE ${OUTPUT_DEF} "LIBRARY ${TARGET_NAME}\nEXPORTS\n") foreach(MATCH ${FILTERED_MATCHES}) string(REGEX REPLACE ".* ([_a-zA-Z0-9]+)$" "\\1" SYMBOL_NAME ${MATCH}) # 跳过编译器自动生成的特殊符号(如__init、__fini系列) if(NOT SYMBOL_NAME MATCHES "^__") file(APPEND ${OUTPUT_DEF} " ${SYMBOL_NAME}\n") endif() endforeach()
3. 集成到Kotlin Native构建
生成的.def文件可直接在Kotlin项目的cinterop配置中引用,以build.gradle.kts为例:
kotlin { // 适配你的目标平台 linuxX64("linux") windowsX64("windows") targets.all { compilations["main"].cinterops.create("MyNativeLib") { defFile.set(file("${rootProject.projectDir}/cmake-build/${target.name}/MyNativeLib.def")) includeDirs.allHeaders("${rootProject.projectDir}/include") } } }
方案优势
- 自动同步:库的导出符号更新时,.def文件会自动重新生成,无需手动修改
- 跨平台兼容:自动适配Windows和Linux的符号提取工具,无需单独维护两套逻辑
- 规范集成:完全基于CMake的目标依赖和脚本机制,与现有构建流程无缝衔接
内容的提问来源于stack exchange,提问作者ijustlovemath
相关产品推荐
相关产品推荐

