You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

能否从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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.31 23:39:08