Kotlin Multiplatform Mobile 找不到 klib 包 [英] Kotlin Multiplatform Mobile can't find klib package

查看:43
本文介绍了Kotlin Multiplatform Mobile 找不到 klib 包的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已阅读这些 SO 帖子

Platform下的红线是错误:

<块引用>

预期的类平台"在模块 MyApplication.shared.androidNativeArm64Main 中没有实际声明用于 Native

但显然这可能只是系统故障(不确定-用于创建实际类..."的 Alt+Enter 解决方案似乎没有做任何事情).假设这不是问题,我继续...

我检查了 .klib 详细信息

运行 .konan/.../bin/klib info mylib.klib 我没有得到 c.mylib 作为包名,而是 com.example.myapplication:shared-cinterop-mylib 代替(见下文).我可以接受(虽然不知道为什么它不是我在 Gradle 中指定的)

解析为:/home/me/AndroidStudioProjects/MyApplication/shared/build/classes/kotlin/androidNativeArm64/main/shared-cinterop-mylib模块名称:ABI 版本:1.4.1编译器版本:1.4.10库版本:空元数据版本:1.4.0红外版本:1.0.0可用目标:android_arm64

我尝试将包包含在我的 androidApp Gradle

我想访问我的 androidApp 项目中的 .klib.我尝试了 c.mylibcom.example.myapplication:shared-cinterop-mylib 两个包.

我尝试将 implementation("com.example.myapplication:shared-cinterop-mylib") 添加到我的 androidApp Gradle 文件中,但出现错误:<块引用>

无法确定任务:androidApp:lintVitalRelease"的依赖关系.无法解析配置:androidApp:debugCompileClasspath"的所有工件.找不到 com.example.myapplication:shared-cinterop-mylib:.要求:项目:androidApp可能的解决方案:

我不确定提示是否能解决问题,但我尝试使用例如将文件添加到 androidApp Gradle repositories { ... }

 maven {url = uri("/home/me/AndroidStudioProjects/MyApplication/shared/build/classes/kotlin/androidNativeArm64/main/shared-cinterop-mylib.klib")}

但我不确定这是将文件添加到存储库的正确方法.

问题

谁能帮我在 androidApp 中识别包?我会继续努力的.

解决方案

您可能对针对不同平台的不同 Kotlin 版本感到困惑.请查看文档了解详细信息,同时我将在这里尝试解释基本概念.

Kotlin Multiplatform 通常由三种不同的编译器组成:一种为 JVM 构建,一种用于转译为 JS,另一种用于编译特定于平台的本机二进制文件(可执行文件、静态或共享库).KMM 技术是关于在两个不同的平台(iOS 和 Android)之间共享您的代码.

这里的重要细节是 KMM 旨在让开发人员更容易地将这些共享代码包含到他们现有的代码库中——通常是 Swift 或 Objective-C(用于 iOS 和 Java)或 Kotlin/JVM(用于 Android).这很重要,因为这个项目是用 Kotlin/Native 和 Kotlin/JVM 构建的.

在您的代码中,我看到了一个额外的平台声明.androidNativeArm64,这是一个 Kotlin/Native 目标,而不是经典的 Android 目标.它使用另一个编译器,并因此生成一个共享库.这就是为什么

  1. 您可以定义 cinterop 块,为标题创建绑定,但是
  2. 这些绑定仅作为 Kotlin/Native 编译的一部分适用.

KLIB,您在此处创建的,不是库本身,而是本机库 (mylib) 的一组绑定.它使您能够从 Kotlin 代码中使用 mylib 的 API,该代码是在 androidNativeArm64Main 源集中编写的.由于您目前没有这样的源代码集,您的项目无法正确构建,并显示关于缺少实际声明的警告.

总结上述所有内容.以下是在项目的当前状态下您可以做和不能做的事情:

可以

  • 使用 Kotlin/Native 代码中的绑定(将文件添加到 shared/src/androidNativeArm64Main/kotlin/)
  • 使用这些绑定编译代码到共享库(.so 文件)
  • 按照 Android NDK 文档中的说明使用此共享库(此处)

  • 删除 Kotlin/Native Android 目标,以及 shared/src/androidMain/kotlin/
  • 中没有使用 C API 的代码

不能

  • 依赖于 Kotlin/JVM 模块中的 KLIB(例如,一般的 androidApp 项目或 shared 中的 androidMain 源集)
  • 发布绑定并且不关心将生成的工件与 C 库链接
  • 使用从 Kotlin/Native 编译的共享或静态库比使用 C/C++ 原生库更容易(抱歉,这将是您可能在这里尽量避免使用的 JNI 内容)

对不起,答案冗长而复杂,如有任何问题,请在下面的评论部分与我联系.我很乐意纠正我的任何错误或不准确之处.

I've read these SO posts 1, 2, 3 which faced a similar problem. I'm trying to use a .klib in my KMM Android project. The Klib is built from library.h C header. Here's what I did:

I built the Kotlin Library

Using the following Gradle block in the KMM shared project:

kotlin {
    ...
    androidNativeArm64 { // target
        compilations.getByName("main") {
            val mylib by cinterops.creating {
                defFile(project.file("mylib.def"))

                packageName("c.mylib")
                // Options to be passed to compiler by cinterop tool.
                compilerOpts("-I/home/me/CLionProjects/mylib/")

                // Directories for header search (an analogue of the -I<path> compiler option).
                includeDirs.allHeaders("/home/me/CLionProjects/mylib/")

                // A shortcut for includeDirs.allHeaders.
                includeDirs("/home/me/CLionProjects/mylib/")
            }
        }
        binaries {
            sharedLib() // https://kotlinlang.org/docs/mpp-build-native-binaries.html#declare-binaries
        }
    }
}

with mylib.def file

headers = /home/me/CLionProjects/mylib/library.h
headerFilter = /home/me/CLionProjects/mylib/*
package = c.mylib

On building, the .klib and build folder appears in the classes directory of the shared project as shown below:

The red line under Platform is for the error:

Expected class 'Platform' has no actual declaration in module MyApplication.shared.androidNativeArm64Main for Native

but apparently that may just be a system glitch (not sure - the Alt+Enter solution to "create actual class..." doesn't seem to do anything). Assuming this is not a problem I continue...

I check the .klib details

Running .konan/.../bin/klib info mylib.klib I don't get c.mylib as the package name but com.example.myapplication:shared-cinterop-mylib instead (see below). I can live with that (although not sure why it isn't what I specified in Gradle)

Resolved to: /home/me/AndroidStudioProjects/MyApplication/shared/build/classes/kotlin/androidNativeArm64/main/shared-cinterop-mylib
Module name: <com.example.myapplication:shared-cinterop-mylib>
ABI version: 1.4.1
Compiler version: 1.4.10
Library version: null
Metadata version: 1.4.0
IR version: 1.0.0
Available targets: android_arm64

I tried including the package in my androidApp Gradle

I want to access the .klib inside my androidApp project. I tried both packages c.mylib and com.example.myapplication:shared-cinterop-mylib.

I tried adding implementation("com.example.myapplication:shared-cinterop-mylib") to my androidApp Gradle file, but got the error:

Could not determine the dependencies of task ':androidApp:lintVitalRelease'. Could not resolve all artifacts for configuration ':androidApp:debugCompileClasspath'. Could not find com.example.myapplication:shared-cinterop-mylib:. Required by: project :androidApp Possible solution:

I'm not sure if the hint would solve the problem, but I tried adding the file to the androidApp Gradle repositories { ... } block anyway using e.g.

    maven {
        url = uri("/home/me/AndroidStudioProjects/MyApplication/shared/build/classes/kotlin/androidNativeArm64/main/shared-cinterop-mylib.klib")
    }

but I'm not sure that's the right way to add a file to a repository.

Question

Can anyone help me to get the package recognised in androidApp ? I'll keep trying.

解决方案

You are probably confused about different Kotlin versions aiming for a different platform. Please check out the documentation for details, while I'll try to explain the basic concept here.

Kotlin Multiplatform in general consists of three different compilers: one to build for the JVM, one to transpile to the JS, and one to compile platform-specific native binaries(executables, static or shared libraries). KMM technology is about sharing your code between two different platforms, iOS and Android.

The important detail here is that KMM aims to make it easier for developers to include this shared code into their existing codebase - usually Swift or Objective-C for iOS and Java or Kotlin/JVM for Android. This is important because this project is built with Kotlin/Native and Kotlin/JVM.

In your code, I see an additional platform declaration. The androidNativeArm64, this is a Kotlin/Native target, not a classic Android one. It uses the other compiler, and produces a shared library as a result. This is the reason why

  1. You're able to define a cinterop block, creating bindings for the header, but
  2. Those bindings are applicable only as a part of the Kotlin/Native compilation.

KLIB, which you created here, is not a library itself, but a set of bindings for the native library(mylib). It provides you an ability to use mylibs API from Kotlin code, written in the androidNativeArm64Main source set. As you don't have such a source set at this moment, your project cannot build correctly, and shows warning about missing actual declaration.

Concluding everything described above. Here are the things you can do, and cannot do in the current state of the project:

Can

  • Use bindings from your Kotlin/Native code(add files to shared/src/androidNativeArm64Main/kotlin/)
  • Compile the code using those bindings to a shared library(.so file)
  • Use this shared library as described in the Android NDK documentation(here)

or

  • Delete the Kotlin/Native Android target, and code without C API usage at the shared/src/androidMain/kotlin/

Cannot

  • Depend on a KLIB from the Kotlin/JVM modules(e.g. androidApp project in general or androidMain source set in shared)
  • Publish bindings and do not care about linking the resulting artifact with the C library
  • Use shared or static library compiled from Kotlin/Native easier than using C/C++ native library(sorry, but it will be the same JNI thing you probably try to avoid here)

Sorry for a long and complicated answer, please contact me with any questions in the comment section below. I would be glad to correct any fo my mistakes or inaccuracies.

这篇关于Kotlin Multiplatform Mobile 找不到 klib 包的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆