Kotlin-native: New plugin DSL doesn't support generating interop bindings

Created on 28 Jul 2018  路  17Comments  路  Source: JetBrains/kotlin-native

The new experimental kotlin-platform-native plugin DSL introduced in v0.8 does not currently support generating interop bindings, like the konan plugin does, according to this.

When will interop support be added?

In the meantime, is there a way to add a klib file as a dependency? I.e. use the konan plugin to generate the interop klib, then add that klib to the kotlin-platform-native build task?

gradle-plugin

Most helpful comment

Please consider possibility in new DSL that cinterop can be combined with custom Kotlin code - sometimes it is convenient to add additional wrappers.

For now I have to create two .klibs, and assign two names - for example libui.klib for cinterop, and libui-ktx.klib for my wrappers.

All 17 comments

Currently the main priority is native support in the new multiplatform plugin (see https://youtrack.jetbrains.com/issue/KT-23930. Samples and some documentation: https://github.com/h0tk3y/k-new-mpp-samples) and the cinterop DSL will be introduced there first soon.

Yes, you can add an interop klib as a file dependency:

dependencies {
    implementation files('path/to/the/klib')
}

Please consider possibility in new DSL that cinterop can be combined with custom Kotlin code - sometimes it is convenient to add additional wrappers.

For now I have to create two .klibs, and assign two names - for example libui.klib for cinterop, and libui-ktx.klib for my wrappers.

Yes, you can add an interop klib as a file dependency:

dependencies {
    implementation files('path/to/the/klib')
}

Hi @ilmat192, thank you for the info. In my case I'm creating interop for Firebase libraries using konan interop(...). I successfully generate the interop klib, called Firebase.klib, which of course has multiple variants (ios_x64, ios_arm32, ios_arm64).

The .def file is as below:

depends = Foundation SystemConfiguration Security MobileCoreServices
headers = FirebaseCore/FirebaseCore.h FirebaseAuth/FirebaseAuth.h FirebaseFirestore/FirebaseFirestore.h FirebaseRemoteConfig/FirebaseRemoteConfig.h FirebaseMessaging/FirebaseMessaging.h
headerFilter = FirebaseCore/** FirebaseAuth/** FirebaseFirestore/** FirebaseRemoteConfig/** FirebaseMessaging/**
language = Objective-C
linkerOpts = -framework FirebaseCore -framework FirebaseAuth -framework FirebaseInstanceID -framework FirebaseAnalytics -framework FirebaseNanoPB -framework FirebaseCoreDiagnostics -framework FirebaseABTesting -framework ProtoRPC -framework grpc -framework openssl -framework leveldb -framework Protobuf -framework GoogleToolboxForMac -framework nanopb -framework GRPCClient -framework GTMSessionFetcher -framework UIKit
compilerOpts = -framework FirebaseCore -framework FirebaseAuth -framework FirebaseFirestore -framework FirebaseRemoteConfig -framework FirebaseMessaging

Specifying the implementation files('path/to/Firebase.klib') dependency results in a build error like exception: java.lang.IllegalStateException: Could not find "Firebase" in <search paths...>.

  1. Its seems that I can't get your suggestion to work, do you have any ideas?
  2. What is the correct way to specify different Firebase.klib variants for different kotlin-platform-native build variants (ios_x64, ios_arm32, ios_arm64)?
  1. Could you please run the build with the -i flag and provide a link to the build log? It contains info about a compiler command line along with all libraries passed to it.
  2. You can specify dependencies per-binary:
import org.jetbrains.kotlin.gradle.plugin.experimental.*

components.withType(KotlinNativeBinary) {
    dependencies {
        def target = konanTarget.name
        implementation files("path/to/${target}.klib")
    }
}

Here konanTarget.name returns a string containing a platform name (e.g. macos_x64 or linux_x64).

My apologies, the Could not find "Firebase" error was because the path/to/klib was wrong. I thought I double checked, but nevertheless I missed it!!

That is extremely helpful, that part seems to work well, thank you.

Now I get an error ld: framework not found FirebaseCore. This is obviously because the Firebase frameworks that were linked into Firebase.klib are not on the search path of the kotlin-platform-native build. I've had a few attempts at providing a search path using the extraOpts property on the main component, but I can't get it right. Do you know how to provide framework search paths to konanc using the kotlin-platform-native plugin?

Use linkerOpts, as specified in https://github.com/JetBrains/kotlin-native/blob/master/GRADLE_PLUGIN.md#properties-available-for-a-compiler-task-executable-library-or-bitcode-building-task.

linkerOpts from konan is not available on a kotlin-platform-native component as far as I can tell?

Neither of below work

  1. extraOpts "-F/path/to/frrameworks" - Error: invalid argument
  2. extraOpts "-linkerOpts -F/path/to/frameworks" - Error: invalid argument

linkerOpts from konan is not available on a kotlin-platform-native component as far as I can tell?

Yes, it's right.

Try to separate the args: extraOpts "-linkerOpts", "-F/path/to/frameworks". The extraOpts option accepts a sequence of strings and passes each of them to the compiler as a separate command line option.

Hi @ilmat192 sorry for the delay, that worked, but now I have another error. I ended up needing to link all sorts of dependencies as below before the linker could progress. Gosh! I hope there will be a better way in the future!

def frameworksDir = new File("interop/Frameworks").absolutePath
sourceSets {
    main {
        component {
            target 'ios_arm32', 'ios_arm64', 'ios_x64'
            outputKinds = [FRAMEWORK]
            extraOpts "-linkerOpts", "-F${frameworksDir}"

            extraOpts "-linkerOpts", "-framework FirebaseFirestore"
            extraOpts "-linkerOpts", "-framework FirebaseRemoteConfig"
            extraOpts "-linkerOpts", "-framework FirebaseMessaging"
            extraOpts "-linkerOpts", "-framework FirebaseInstanceID"
            extraOpts "-linkerOpts", "-framework FirebaseAuth"
            extraOpts "-linkerOpts", "-framework FirebaseAnalytics"
            extraOpts "-linkerOpts", "-framework FirebaseNanoPB"
            extraOpts "-linkerOpts", "-framework FirebaseCoreDiagnostics"
            extraOpts "-linkerOpts", "-framework FirebaseABTesting"
            extraOpts "-linkerOpts", "-framework FirebaseCore"

            extraOpts "-linkerOpts", "-framework CoreGraphics"
            extraOpts "-linkerOpts", "-framework Security"
            extraOpts "-linkerOpts", "-framework SystemConfiguration"
            extraOpts "-linkerOpts", "-framework MobileCoreServices"
            extraOpts "-linkerOpts", "-framework SafariServices"
            extraOpts "-linkerOpts", "-framework StoreKit"
            extraOpts "-linkerOpts", "-framework grpc"
            extraOpts "-linkerOpts", "-framework GRPCClient"
            extraOpts "-linkerOpts", "-framework GTMSessionFetcher"
            extraOpts "-linkerOpts", "-framework nanopb"
            extraOpts "-linkerOpts", "-framework GoogleToolboxForMac"
            extraOpts "-linkerOpts", "-framework Protobuf"
            extraOpts "-linkerOpts", "-framework leveldb"
            extraOpts "-linkerOpts", "-framework openssl"
            extraOpts "-linkerOpts", "-framework ProtoRPC"
            extraOpts "-linkerOpts", "-framework RxLibrary"
            extraOpts "-linkerOpts", "-lsqlite3"
        }
    }
}

dependencies {
    expectedBy project(':common:common')
    implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core-native:$coroutines_version"
}

import org.jetbrains.kotlin.gradle.plugin.experimental.*
components.withType(KotlinNativeBinary) {
    def target = konanTarget.name
    dependencies {
        implementation files("interop/build/konan/libs/${target}/Firebase.klib")
    }
}

That's great, HOWEVER, now I get the next error error: compilation failed: /targets/ios_x64/kotlin, with the -info output as below:

> Task :ios:common:checkKonanCompiler
Task ':ios:common:checkKonanCompiler' is not up-to-date because:
Task has not declared any outputs despite executing actions.
Downloading Kotlin/Native compiler from https://download.jetbrains.com/kotlin/native/builds/dev/0.9-dev-2922/macos/kotlin-native-macos-0.9-dev-2922 into /Users/brettwillis/.konan
:ios:common:checkKonanCompiler (Thread[Task worker for ':' Thread 6,5,main]) completed. Took 0.056 secs.
:ios:common:compileDebugIos_x64KotlinNative (Thread[Task worker for ':' Thread 6,5,main]) started.

> Task :ios:common:compileDebugIos_x64KotlinNative
Task ':ios:common:compileDebugIos_x64KotlinNative' is not up-to-date because:
Task has failed previously.
Run tool: konanc with args: -o /Users/brettwillis/code/project-name/ios/common/build/lib/main/debug/ios_x64/common.framework -g -ea -target ios_x64 -p framework -Xmulti-platform -linkerOpts -F/Users/brettwillis/code/project-name/ios/common/interop/Frameworks -linkerOpts -framework CoreGraphics -linkerOpts -framework Security -linkerOpts -framework SystemConfiguration -linkerOpts -framework MobileCoreServices -linkerOpts -framework SafariServices -linkerOpts -framework FirebaseFirestore -linkerOpts -framework grpc -linkerOpts -framework GRPCClient -linkerOpts -framework GTMSessionFetcher -linkerOpts -framework nanopb -linkerOpts -framework GoogleToolboxForMac -linkerOpts -framework Protobuf -linkerOpts -framework leveldb -linkerOpts -framework openssl -linkerOpts -framework ProtoRPC -linkerOpts -framework RxLibrary -linkerOpts -framework FirebaseRemoteConfig -linkerOpts -framework FirebaseMessaging -linkerOpts -framework FirebaseInstanceID -linkerOpts -framework FirebaseAuth -linkerOpts -framework FirebaseAnalytics -linkerOpts -framework FirebaseNanoPB -linkerOpts -framework FirebaseCoreDiagnostics -linkerOpts -framework FirebaseABTesting -linkerOpts -framework FirebaseCore -linkerOpts -lsqlite3 -linkerOpts -framework StoreKit -r /Users/brettwillis/code/project-name/ios/common/interop/build/konan/libs/ios_arm32 -l Firebase -r /Users/brettwillis/code/project-name/ios/common/interop/build/konan/libs/ios_arm64 -l Firebase -r /Users/brettwillis/code/project-name/ios/common/interop/build/konan/libs/ios_x64 -l Firebase -r /Users/brettwillis/code/project-name/ios/common/interop/build/konan/libs/macos_x64 -l Firebase -r /Users/brettwillis/.gradle/caches/modules-2/files-2.1/org.jetbrains.kotlinx/kotlinx-coroutines-core-native_debug_ios_x64/0.24.0/73ce04d13c47dfafa6857a1f523073d2d6bbc3ce -l kotlinx-coroutines-core-native -r /Users/brettwillis/.gradle/caches/modules-2/files-2.1/org.jetbrains.kotlinx/atomicfu-native_debug_ios_x64/0.11.0/f3e521a0ec75e6a2035c639b763177dfcbf15652 -l atomicfu-native ...
Starting process 'command '/Applications/Android Studio.app/Contents/jre/jdk/Contents/Home/bin/java''. Working directory: /Users/brettwillis/code/project-name/ios/common Command: /Applications/Android Studio.app/Contents/jre/jdk/Contents/Home/bin/java -DCVS_PASSFILE=~/.cvspass -D__idea.mac.env.lock=unlocked -Dapple.laf.useScreenMenuBar=true -Dawt.toolkit=sun.lwawt.macosx.LWCToolkit -Dcom.apple.mrj.application.live-resize=false -Dfile.encoding.pkg=sun.io -Dfile.separator=/ -Dftp.nonProxyHosts=local|*.local|169.254/16|*.169.254/16 -DgopherProxySet=false -Dhttp.nonProxyHosts=local|*.local|169.254/16|*.169.254/16 -Dide.new.welcome.screen.force=true -Didea.cycle.buffer.size=1024 -Didea.dynamic.classpath=false -Didea.executable=studio -Didea.fatal.error.notification=disabled -Didea.home.path=/Applications/Android Studio.app/Contents -Didea.java.redist=Bundled -Didea.jre.check=true -Didea.max.content.load.filesize=20000 -Didea.max.intellisense.filesize=2500 -Didea.no.launcher=false -Didea.paths.selector=AndroidStudio3.1 -Didea.platform.prefix=AndroidStudio -Didea.popup.weight=heavy -Didea.smooth.progress=false -Didea.xdebug.key=-Xdebug -Dio.netty.machineId=28:f0:76:ff:fe:16:65:0e -Dio.netty.processId=47830 -Dio.netty.serviceThreadPrefix=Netty  -Djava.awt.graphicsenv=sun.awt.CGraphicsEnvironment -Djava.awt.headless=true -Djava.awt.printerjob=sun.lwawt.macosx.CPrinterJob -Djava.class.path=/Users/brettwillis/.gradle/wrapper/dists/gradle-4.7-all/4cret0dgl5o3b21weaoncl7ys/gradle-4.7/lib/gradle-launcher-4.7.jar -Djava.class.version=52.0 -Djava.endorsed.dirs=/Applications/Android Studio.app/Contents/jre/jdk/Contents/Home/jre/lib/endorsed -Djava.ext.dirs=/Users/brettwillis/Library/Java/Extensions:/Applications/Android Studio.app/Contents/jre/jdk/Contents/Home/jre/lib/ext:/Library/Java/Extensions:/Network/Library/Java/Extensions:/System/Library/Java/Extensions:/usr/lib/java -Djava.home=/Applications/Android Studio.app/Contents/jre/jdk/Contents/Home/jre -Djava.library.path=/Users/brettwillis/.konan/kotlin-native-macos-0.9-dev-2922/konan/nativelib -Djava.net.preferIPv4Stack=true -Djava.rmi.server.disableHttp=true -Djava.rmi.server.hostname=localhost -Djava.runtime.name=OpenJDK Runtime Environment -Djava.runtime.version=1.8.0_152-release-1024-b01 -Djava.specification.name=Java Platform API Specification -Djava.specification.vendor=Oracle Corporation -Djava.specification.version=1.8 -Djava.util.concurrent.ForkJoinPool.common.threadFactory=com.intellij.concurrency.IdeaForkJoinWorkerThreadFactory -Djava.vendor=JetBrains s.r.o -Djava.vendor.url=https://www.jetbrains.com/ -Djava.vendor.url.bug=https://youtrack.jetbrains.com -Djava.version=1.8.0_152-release -Djava.vm.info=mixed mode -Djava.vm.name=OpenJDK 64-Bit Server VM -Djava.vm.specification.name=Java Virtual Machine Specification -Djava.vm.specification.vendor=Oracle Corporation -Djava.vm.specification.version=1.8 -Djava.vm.vendor=JetBrains s.r.o -Djava.vm.version=25.152-b01 -Djavax.swing.rebaseCssSizeMap=true -Djb.vmOptionsFile=/Applications/Android Studio.app/Contents/bin/studio.vmoptions -Djna.boot.library.path -Djna.encoding=UTF8 -Djna.loaded=true -Djna.nosys=true -Djna.platform.library.path=/usr/lib:/usr/lib -Djna.tmpdir=/Users/brettwillis/Library/Caches/AndroidStudio3.1/tmp -Djnidispatch.path=/Users/brettwillis/Library/Caches/AndroidStudio3.1/tmp/jna8612810209034690672.tmp -Dkonan.home=/Users/brettwillis/.konan/kotlin-native-macos-0.9-dev-2922 -Dkotlin.environment.keepalive=true -Dlibrary.jansi.path=/Users/brettwillis/.gradle/native/jansi/1.14/osx -Dline.separator=
-Dlog4j.defaultInitOverride=true -Dos.arch=x86_64 -Dos.name=Mac OS X -Dos.version=10.13.6 -Dpath.separator=: -DsocksNonProxyHosts=local|*.local|169.254/16|*.169.254/16 -Dstudio.record.file=/Users/brettwillis/Library/Caches/AndroidStudio3.1/tmp/AndroidStudio.865c1433-99fa-43ba-833d-c417064228dd -Dsun.arch.data.model=64 -Dsun.boot.class.path=/Applications/Android Studio.app/Contents/jre/jdk/Contents/Home/jre/lib/resources.jar:/Applications/Android Studio.app/Contents/jre/jdk/Contents/Home/jre/lib/rt.jar:/Applications/Android Studio.app/Contents/jre/jdk/Contents/Home/jre/lib/sunrsasign.jar:/Applications/Android Studio.app/Contents/jre/jdk/Contents/Home/jre/lib/jsse.jar:/Applications/Android Studio.app/Contents/jre/jdk/Contents/Home/jre/lib/jce.jar:/Applications/Android Studio.app/Contents/jre/jdk/Contents/Home/jre/lib/charsets.jar:/Applications/Android Studio.app/Contents/jre/jdk/Contents/Home/jre/lib/jfr.jar:/Applications/Android Studio.app/Contents/jre/jdk/Contents/Home/jre/classes -Dsun.boot.library.path=/Applications/Android Studio.app/Contents/jre/jdk/Contents/Home/jre/lib -Dsun.cpu.endian=little -Dsun.cpu.isalist -Dsun.io.unicode.encoding=UnicodeBig -Dsun.java.command=org.gradle.launcher.daemon.bootstrap.GradleDaemon 4.7 -Dsun.java.launcher=SUN_STANDARD -Dsun.jnu.encoding=UTF-8 -Dsun.management.compiler=HotSpot 64-Bit Tiered Compilers -Dsun.os.patch.level=unknown -Dswing.bufferPerWindow=true -Duser.dir=/Users/brettwillis/code/project-name/ios/common -Duser.home=/Users/brettwillis -Duser.name=brettwillis -Duser.timezone=Pacific/Auckland -Xmx3G -Dfile.encoding=UTF-8 -Djava.io.tmpdir=/var/folders/lj/jb9r_w_n6hq60g8yjf1h62b40000gn/T/ -Duser.country=NZ -Duser.language=en -Duser.variant -ea -cp /Users/brettwillis/.konan/kotlin-native-macos-0.9-dev-2922/konan/lib/kotlin-stdlib.jar:/Users/brettwillis/.konan/kotlin-native-macos-0.9-dev-2922/konan/lib/klib.jar:/Users/brettwillis/.konan/kotlin-native-macos-0.9-dev-2922/konan/lib/Runtime.jar:/Users/brettwillis/.konan/kotlin-native-macos-0.9-dev-2922/konan/lib/protobuf-java-2.6.1.jar:/Users/brettwillis/.konan/kotlin-native-macos-0.9-dev-2922/konan/lib/shared.jar:/Users/brettwillis/.konan/kotlin-native-macos-0.9-dev-2922/konan/lib/kotlin-script-runtime.jar:/Users/brettwillis/.konan/kotlin-native-macos-0.9-dev-2922/konan/lib/kotlin-compiler.jar:/Users/brettwillis/.konan/kotlin-native-macos-0.9-dev-2922/konan/lib/kotlin-reflect.jar:/Users/brettwillis/.konan/kotlin-native-macos-0.9-dev-2922/konan/lib/utilities.jar:/Users/brettwillis/.konan/kotlin-native-macos-0.9-dev-2922/konan/lib/backend.native.jar:/Users/brettwillis/.konan/kotlin-native-macos-0.9-dev-2922/konan/lib/StubGenerator.jar:/Users/brettwillis/.konan/kotlin-native-macos-0.9-dev-2922/konan/lib/Indexer.jar org.jetbrains.kotlin.cli.utilities.MainKt konanc -o /Users/brettwillis/code/project-name/ios/common/build/lib/main/debug/ios_x64/common.framework -g -ea -target ios_x64 -p framework -Xmulti-platform -linkerOpts -F/Users/brettwillis/code/project-name/ios/common/interop/Frameworks -linkerOpts -framework CoreGraphics -linkerOpts -framework Security -linkerOpts -framework SystemConfiguration -linkerOpts -framework MobileCoreServices -linkerOpts -framework SafariServices -linkerOpts -framework FirebaseFirestore -linkerOpts -framework grpc -linkerOpts -framework GRPCClient -linkerOpts -framework GTMSessionFetcher -linkerOpts -framework nanopb -linkerOpts -framework GoogleToolboxForMac -linkerOpts -framework Protobuf -linkerOpts -framework leveldb -linkerOpts -framework openssl -linkerOpts -framework ProtoRPC -linkerOpts -framework RxLibrary -linkerOpts -framework FirebaseRemoteConfig -linkerOpts -framework FirebaseMessaging -linkerOpts -framework FirebaseInstanceID -linkerOpts -framework FirebaseAuth -linkerOpts -framework FirebaseAnalytics -linkerOpts -framework FirebaseNanoPB -linkerOpts -framework FirebaseCoreDiagnostics -linkerOpts -framework FirebaseABTesting -linkerOpts -framework FirebaseCore -linkerOpts -lsqlite3 -linkerOpts -framework StoreKit -r /Users/brettwillis/code/project-name/ios/common/interop/build/konan/libs/ios_arm32 -l Firebase -r /Users/brettwillis/code/project-name/ios/common/interop/build/konan/libs/ios_arm64 -l Firebase -r /Users/brettwillis/code/project-name/ios/common/interop/build/konan/libs/ios_x64 -l Firebase -r /Users/brettwillis/code/project-name/ios/common/interop/build/konan/libs/macos_x64 -l Firebase -r /Users/brettwillis/.gradle/caches/modules-2/files-2.1/org.jetbrains.kotlinx/kotlinx-coroutines-core-native_debug_ios_x64/0.24.0/73ce04d13c47dfafa6857a1f523073d2d6bbc3ce -l kotlinx-coroutines-core-native -r /Users/brettwillis/.gradle/caches/modules-2/files-2.1/org.jetbrains.kotlinx/atomicfu-native_debug_ios_x64/0.11.0/f3e521a0ec75e6a2035c639b763177dfcbf15652 -l atomicfu-native ...
Successfully started process 'command '/Applications/Android Studio.app/Contents/jre/jdk/Contents/Home/bin/java''
warning: library included more than once: /Users/brettwillis/code/project-name/ios/common/interop/build/konan/libs/ios_arm32/Firebase.klib
error: compilation failed: /targets/ios_x64/kotlin

* Source files: ...
* Compiler version info: Konan: 0.9-dev-2922 / Kotlin: 1.2.70
* Output kind: FRAMEWORK

exception: java.nio.file.NoSuchFileException: /targets/ios_x64/kotlin
    at com.sun.nio.zipfs.ZipPath.getAttributes(ZipPath.java:666)
    at com.sun.nio.zipfs.ZipFileSystemProvider.readAttributes(ZipFileSystemProvider.java:294)
    at java.nio.file.Files.readAttributes(Files.java:1737)
    at java.nio.file.FileTreeWalker.getAttributes(FileTreeWalker.java:219)
    at java.nio.file.FileTreeWalker.visit(FileTreeWalker.java:276)
    at java.nio.file.FileTreeWalker.walk(FileTreeWalker.java:322)
    at java.nio.file.FileTreeIterator.<init>(FileTreeIterator.java:72)
    at java.nio.file.Files.walk(Files.java:3574)
    at java.nio.file.Files.walk(Files.java:3625)
    at org.jetbrains.kotlin.konan.file.FileKt.recursiveCopyTo(File.kt:210)
    at org.jetbrains.kotlin.konan.file.File.recursiveCopyTo(File.kt:67)
    at org.jetbrains.kotlin.backend.konan.library.impl.FileExtractor.extractDir(KonanLibrary.kt:91)
    at org.jetbrains.kotlin.backend.konan.library.impl.FileExtractor$kotlinDir$2.invoke(KonanLibrary.kt:71)
    at org.jetbrains.kotlin.backend.konan.library.impl.FileExtractor$kotlinDir$2.invoke(KonanLibrary.kt:56)
    at kotlin.SynchronizedLazyImpl.getValue(LazyJVM.kt:74)
    at org.jetbrains.kotlin.backend.konan.library.impl.FileExtractor.getKotlinDir(KonanLibrary.kt)
    at org.jetbrains.kotlin.backend.konan.library.impl.LibraryReaderImpl.getBitcodePaths(KonanLibraryReaderImpl.kt:67)
    at org.jetbrains.kotlin.backend.konan.LinkStage.linkStage(LinkStage.kt:221)
    at org.jetbrains.kotlin.backend.konan.KonanDriverKt$runTopLevelPhases$5.invoke(KonanDriver.kt:109)
    at org.jetbrains.kotlin.backend.konan.KonanDriverKt$runTopLevelPhases$5.invoke(KonanDriver.kt)
    at org.jetbrains.kotlin.backend.konan.PhaseManager$phase$$inlined$with$lambda$1.invoke(KonanPhases.kt:139)
    at org.jetbrains.kotlin.backend.konan.PhaseManager$phase$$inlined$with$lambda$1.invoke(KonanPhases.kt:118)
    at org.jetbrains.kotlin.konan.util.UtilKt.profileIf(Util.kt:34)
    at org.jetbrains.kotlin.backend.konan.PhaseManager.phase$backend_native_compiler(KonanPhases.kt:138)
    at org.jetbrains.kotlin.backend.konan.KonanDriverKt.runTopLevelPhases(KonanDriver.kt:108)
    at org.jetbrains.kotlin.cli.bc.K2Native.doExecute(K2Native.kt:73)
    at org.jetbrains.kotlin.cli.bc.K2Native.doExecute(K2Native.kt:40)
    at org.jetbrains.kotlin.cli.common.CLICompiler.execImpl(CLICompiler.java:94)
    at org.jetbrains.kotlin.cli.common.CLICompiler.execImpl(CLICompiler.java:50)
    at org.jetbrains.kotlin.cli.common.CLITool.exec(CLITool.kt:88)
    at org.jetbrains.kotlin.cli.common.CLITool.exec(CLITool.kt:66)
    at org.jetbrains.kotlin.cli.common.CLITool.exec(CLITool.kt:34)
    at org.jetbrains.kotlin.cli.common.CLITool$Companion.doMainNoExit(CLITool.kt:180)
    at org.jetbrains.kotlin.cli.common.CLITool$Companion.doMain(CLITool.kt:171)
    at org.jetbrains.kotlin.cli.bc.K2Native$Companion$main$1.invoke(K2Native.kt:197)
    at org.jetbrains.kotlin.cli.bc.K2Native$Companion$main$1.invoke(K2Native.kt:188)
    at org.jetbrains.kotlin.konan.util.UtilKt.profileIf(Util.kt:34)
    at org.jetbrains.kotlin.konan.util.UtilKt.profile(Util.kt:29)
    at org.jetbrains.kotlin.cli.bc.K2Native$Companion.main(K2Native.kt:190)
    at org.jetbrains.kotlin.cli.bc.K2NativeKt.main(K2Native.kt:202)
    at org.jetbrains.kotlin.cli.utilities.MainKt.main(main.kt:27)


> Task :ios:common:compileDebugIos_x64KotlinNative FAILED
:ios:common:compileDebugIos_x64KotlinNative (Thread[Task worker for ':' Thread 6,5,main]) completed. Took 29.401 secs.

FAILURE: Build failed with an exception.

I feel like we're nearly there, do you know how to solve this one?

It's worth mentioning that this did build successfully without errors, then the next day this new error started, and I can't figure out what changed.

Sorry, It looks like I provided a wrong code for adding dependency on an interop klib. In my snippet the top-level dependencies block was called so we added dependencies on all interop klibs to each binary. The compiler tried to link a library with a wrong target and failed to do this.

The correct adding a dependency will look like this:

import org.jetbrains.kotlin.gradle.plugin.experimental.*
components.withType(KotlinNativeBinary) {
    def target = konanTarget.name
    // Here, the binary's dependencies are accessed instead of the top-level block.
    dependencies.implementation files("interop/build/konan/libs/${target}/Firebase.klib")
}

Thank you I'll give that a try shortly.

Another side-effect of moving from konan to the kotlin-platform-native plugin, is that it seems the plugin doesn't respect the konan plugin properties passed in from Xcode on the command line.

The konan build phase script in Xcode is something like this:

"$SRCROOT/../gradlew" -p "$SRCROOT" "$KONAN_TASK"
    -Pkonan.configuration.build.dir="$CONFIGURATION_BUILD_DIR"
    -Pkonan.debugging.symbols="$DEBUGGING_SYMBOLS"
    -Pkonan.optimizations.enable="$KONAN_ENABLE_OPTIMIZATIONS"

The kotlin-platform-native build doesn't respect the build output directory, and therefore probably not the other properties either. Is there a new way of providing these gradle properties to the kotlin-platform-native plugin?

No, these properties are not used by the new plugin but you can copy the framework built in the right location as shown here.

Ok that worked great, thank you.

Now that the project can build and run, it seems like the Firebase iOS libraries just fall apart when linked into Kotlin/Native:

  • Firstly, the debugger understandably produces warnings about duplicate Firebase symbols defined in both the Kotlin/Native framework, and also the iOS app. All sorts of runtime errors ensue like the ones below. I stop the Firebase symbols being duplicately linked into app (because they are already linked in to the Kotlin/Native Framework how I showed a posts ago), so now those warnings stop.
  • Nevertheless Firebase seems to fall apart, with runtime errors like:

    • [FIRInstanceIDCheckinPreferences preferencesFromKeychainContents:]: unrecognized selector sent to class inside FIRApp.configure() or inside FIRMessaging.messaging() depending whether the duplicate symbols are linked or not

    • FIRFirebase.firebase() factory returns nil (this should always return an instance or throw an exception)

I realise this is very specific to Firebase, but I confirmed the framework versions I'm linking work fine outside of Kotlin/Native. Once I use it from Kotlin/Native using interop, it all just falls apart.

Is this a loosing battle? Or do you have some ideas?

I can't share the project code, but if it will be helpful, I can put together a stripped down project to reproduce the problems.

I can put together a stripped down project to reproduce the problems.

Yes, it would be very helpful :)

Hi @ilmat192, now that C Interop is implemented in the multi platform plugin, the above experiment may be a moot point. So I'm trying this again, but having a few issues:

Def files in src/nativeInterop/cinterop, for example FirebaseCore.def:

headers = FirebaseCore/FirebaseCore.h
compilerOpts = -framework FirebaseCore
excludeDependentModules = true
package = com.google.firebase.core

And build.gradle (I've excluded the Android parts for brevity):

apply plugin: 'kotlin-multiplatform' // 1.3.0
apply plugin: 'kotlinx-atomicfu'

kotlin {
    sourceSets {
        commonMain {
            dependencies {
                implementation 'org.jetbrains.kotlin:kotlin-stdlib'
                implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core-common:$coroutines_version"
                implementation "org.jetbrains.kotlinx:kotlinx-serialization-runtime-common:$serialization_version"
                implementation "org.jetbrains.kotlinx:atomicfu-common:$atomicfu_version"
            }
        }
        iosMain {
            dependencies {
                implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core-native:$coroutines_version"
                implementation "org.jetbrains.kotlinx:kotlinx-serialization-runtime-native:$serialization_version"
                implementation "org.jetbrains.kotlinx:atomicfu-native:$atomicfu_version"
            }
        }
    }

    targets {
        fromPreset(presets.android, 'android')

        def buildForDevice = project.findProperty("device")?.toBoolean() ?: false
        def iosPreset = (buildForDevice) ? presets.iosArm64 : presets.iosX64
        println("iOS preset: ${iosPreset.getName()}")

        fromPreset(iosPreset, 'ios') {
            compilations.main {
                outputKinds('FRAMEWORK')
                cinterops {
                    FirebaseCore
                    FirebaseAuth
                    FirebaseFirestore
                    FirebaseMessaging
                }
            }
        }
    }
}

I'm stuck at the first step because it's trying to include the Kotlin dependencies in the cinterop task (?):

* What went wrong:
Could not resolve all files for configuration ':common:iosFirebaseCoreCInterop'.
> Could not resolve org.jetbrains.kotlinx:kotlinx-coroutines-core-native:1.0.0.
Required by:
    project :common
> Unable to find a matching configuration of org.jetbrains.kotlinx:kotlinx-coroutines-core-native:1.0.0:
    ...
    - Configuration 'debugIos_x64Link':
        - Found org.gradle.native.debuggable 'true' but wasn't required.
        - Found org.gradle.native.optimized 'false' but wasn't required.
        - Found org.gradle.status 'release' but wasn't required.
        - Required org.gradle.usage 'java-api' and found incompatible value 'kotlin-api'.
        - Required org.jetbrains.kotlin.native.target 'ios_x64' and found compatible value 'ios_x64'.
        - Required org.jetbrains.kotlin.platform.type 'native' and found compatible value 'native'.

etc...

What am I doing wrong here?

Hi! It's a known problem with dependencies. The fix is ready and will be included in 1.3.10. As a workaround you can modify the wrong attribute manually by adding the following code in your build script:

kotlin.targets.matching { it.platformType.name == 'native' }.all {
    compilations.all { 
        cinterops.all {
            configurations[dependencyConfigurationName].attributes.attribute(
                Usage.USAGE_ATTRIBUTE, 
                objects.named(Usage, 'kotlin-api')
            )
        }
    }
}  

Thanks @ilmat192, that works well for now.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

SBNTT picture SBNTT  路  4Comments

jonnyzzz picture jonnyzzz  路  4Comments

talanov picture talanov  路  3Comments

Marcopohlo picture Marcopohlo  路  4Comments

tarek360 picture tarek360  路  4Comments