如何将Mapbox iOS框架集成到Kotlin本机

时间:2020-06-08 13:39:14

标签: mapbox kotlin-native

我正在尝试将Mapbox的框架集成到我的Kotlin多平台库中。但是我在cinterop部分遇到了编译错误。

第一个问题是MapboxMobileEvents框架的编译步骤。 MapboxMobileEvents.h的导入语句引用了不存在的MapboxMobileEvents目录。我创建了一个符号链接来解决这个问题。

那之后,我从clang收到一个错误。

Exception in thread "main" java.lang.IllegalStateException: clang_parseTranslationUnit2 failed with CXError_ASTReadError;
sourceFile = /var/folders/vj/mvxq9qtn1r9_8x2c7zyx04_m0000gn/T/tmp6661284981682757951tmp8536987580934998728.m
arguments = -fmodules -isystem /Users/mkrussel/.konan/dependencies/clang-llvm-apple-8.0.0-darwin-macos/lib/clang/8.0.0/include -B/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin -fno-stack-protector -stdlib=libc++ -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator13.5.sdk -miphoneos-version-min=9.0 -O2 -I/Users/mkrussel/pangea/mapbox-native/pangea-mapbox/frameworks/MapboxMobileEvents.framework/Headers -fobjc-arc -include-pch /var/folders/vj/mvxq9qtn1r9_8x2c7zyx04_m0000gn/T/tmp1085765932502683439.pch -Werror=implicit-function-declaration -ferror-limit=0

tmp6661284981682757951tmp8536987580934998728.m名称在每次构建时都会更改,但是文件始终为空,这是我认为引起问题的原因。

我不知道是什么导致文件为空。

我是否将cinterop配置错误?

Kotlin插件是否损坏?

Mapbox框架与Kotlin本机不兼容吗?

我的gradle文件看起来像

iOSTarget("ios") {
   compilations {
         @Suppress("UNUSED_VARIABLE")
         val main by getting {
             kotlinOptions.freeCompilerArgs = listOf("-Xobjc-generics")

             val frameworksDir = "$projectDir/frameworks"
             cinterops(Action {
               val mapboxEvents by creating {
                   defFile("$frameworksDir/mapbox-events.def")

                   includeDirs.allHeaders("$frameworksDir/MapboxMobileEvents.framework/Headers")
               }
             })

             cinterops(Action {
                val mapbox by creating {
                    defFile("$frameworksDir/mapbox.def")
                    includeDirs.allHeaders("$frameworksDir/Mapbox.framework/Headers")
                }
             })
        }
    }
}

mapbox-events.def

package = framework.mapbox.events
language = Objective-C
headers = MapboxMobileEvents.h
headersFilter = **

compilerOpts = -F/Users/mkrussel/pangea/mapbox-native/pangea-mapbox/frameworks -framework MapboxMobileEvents -fmodules
linkerOpts = -F/Users/mkrussel/pangea/mapbox-native/pangea-mapbox/frameworks -framework MapboxMobileEvents

mapbox.def

package = framework.mapbox
language = Objective-C
headers = Mapbox.h
headersFilter = **

compilerOpts = -F/Users/mkrussel/pangea/mapbox-native/pangea-mapbox/frameworks -framework Mapbox -fmodules
linkerOpts = -F/Users/mkrussel/pangea/mapbox-native/pangea-mapbox/frameworks -framework Mapbox

.def文件中使用完整路径名,以确保没有相对路径问题。 尝试仅使用mapbox.defmapbox-events.def文件之一仍然会产生相同的错误。

使用:

  • 科特林1.3.72版
  • Xcode 11.5版(11E608c)

也尝试过此方法,但同样失败。

    iOSTarget("ios") {
        val frameworksDir = "$projectDir/frameworks"
        compilations {
            @Suppress("UNUSED_VARIABLE")
            val main by getting {
                kotlinOptions.freeCompilerArgs = listOf("-Xobjc-generics")

                cinterops(Action {
                    val mapboxEvents by creating {
                        defFile("$frameworksDir/mapbox-events.def")
                        packageName("com.mapbox.events")
                        header("$frameworksDir/MapboxMobileEvents.framework/Headers/MapboxMobileEvents.h")

                        compilerOpts("-fmodules")
                        includeDirs.allHeaders("$frameworksDir/MapboxMobileEvents.framework/Headers")
                    }
                })

                cinterops(Action {
                    val mapbox by creating {
                        defFile("$frameworksDir/mapbox.def")
                        packageName("com.mapbox")
                        header("$frameworksDir/Mapbox.framework/Headers/Mapbox.h")
                        compilerOpts("-fmodules")
                        includeDirs.allHeaders("$frameworksDir/Mapbox.framework/Headers")
                    }
                })
            }
        }
        binaries {
            executable {
                linkerOpts = mutableListOf("-F$frameworksDir", "-framework", "Mapbox", "-framework", "MapboxMobileEvents")
            }

        }
    }

mapbox-event.def

language = Objective-C

mapbox.def

language = Objective-C

2 个答案:

答案 0 :(得分:1)

我最终使它起作用。

mapbox.def

language = Objective-C
modules = Mapbox
linkerOpts = -framework Mapbox

在build.gradle.kts中

kotlin {
    ios {
        val frameworkLocation = File(rootDir, "native/TestApp/Pods/Mapbox-iOS-SDK/dynamic/").absolutePath
        val frameworks = "-F$frameworkLocation"
        compilations {
            @Suppress("UNUSED_VARIABLE")
            val main by getting {
                cinterops {
                    val mapbox by creating {
                        defFile = File("$projectDir/libs/mapbox.def")
                        packageName("com.mapbox")
                        compilerOpts(frameworks)
                    }
                }
            }
        }
        binaries.matching { it is org.jetbrains.kotlin.gradle.plugin.mpp.Framework }
            .configureEach {
                val framework = this as org.jetbrains.kotlin.gradle.plugin.mpp.Framework
                framework.linkerOpts(frameworks)
            }
    }
}

好像我缺少的一大块东西是模块行

答案 1 :(得分:0)

我已经在那些框架上玩了一些,这里就是我所发现的。 您不需要compilerOpts文件中的那些.def。此选项用于cinterop工具,而不是最终的二进制编译。您在此处设置的选项可能应该转到Gradle脚本的kotlin.binaries.framework块。可以在documentation中找到更多信息。


UPD:此建议并不完全正确,因为它仅解决了Mapbox框架的绑定生成问题。问题是cinterop工具的-fmodules编译器标志存在问题。该标志对于MapboxMobileEvents框架非常重要,因为它在使用Foundation和CoreFoundation框架时依赖于@import语法。
请订阅YouTrack问题here。修复后,我将在这里进行更新。