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

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

问题描述

我已阅读这些

Platform 下的红线表示错误:

预期的类'Platform'在本地模块MyApplication.shared.androidNativeArm64Main中没有实际的声明

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

我检查了 .klib 详细信息

运行 .konan/.../bin/klib信息mylib.klib ,我没有得到 c.mylib 作为包名,但是却得到了 com.example.myapplication:shared-cinterop-mylib (请参见下文).我可以接受(尽管不确定为什么它不是我在Gradle中指定的)

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

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

我想访问我的 androidApp 项目中的 .klib .我尝试了两个软件包 c.mylib com.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旨在使开发人员更轻松地将此共享代码包括在其现有代码库中-通常是iOS的Swift或Objective-C以及Android的Java或Kotlin/JVM.这很重要,因为此项目是使用Kotlin/Native和Kotlin/JVM构建的.在您的代码中,我看到了另一个平台声明. androidNativeArm64 ,这是Kotlin/Native目标,而不是经典的Android目标.它使用其他编译器,并因此产生一个共享库.这就是为什么

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

您在此处创建的

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

总结上述所有内容.在项目的当前状态下,您可以执行以下操作:

可以

  • 使用Kotlin/本机代码中的绑定(将文件添加到 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天全站免登陆