Search code examples
kotlin-multiplatformkotlin-native

How to generate a .framework depending from another with Kotlin/native?


I have some dependencies issues with KMP and iOS Framework.

Here is some context: I have 2 KMP modules:

  • An API module: define only interfaces
  • A classic lib use the API module as injection

I also have 2 android projects and 2 iOS projects:

  • an Android and iOS application (that use the KMP ClassicLib)
  • an Android and iOS lib that implement the API module

On Android, I have the following :

// KMP API project
public interface Foo

// KMP libA project
public class Bar {
    fun doSomething(foo: Foo)
}

// ANDROID: libB project
import API
public class FooImpl: Foo { }

// ANDROID app
import libA
import libB
var foo = FooImpl()
var bar = Bar()
bar.doSomething(foo) // <----- Everything is fine here

but on iOS, I have this:

// iOS app
import libA
import libB
var foo = FooImpl()
var bar = Bar()
bar.doSomething(foo) // <----- Error here : FooImpl is of type APIFoo but here LibAAPIFoo is excpected 

Indeed when I take a look into the generated headers, I have the following:

// KMP API.h
@protocol APIFoo
@end;

// KMP libA.h
@protocol LibAKAFoo // <----- here we have a redefinition of the protocol.
@end;

@interface Bar
- (void)doSomething:(KMPKAFoo)foo;  
@ends;

I was expecting to have something more like :

// KMP API.h
@protocol APIFoo
@end;

// KMP libA.h
#include <API/API.h> // <----- import the API

@interface Bar
- (void)doSomething:(APIFoo)foo; // <----- use it
@ends;

Is there a special configuration that I'm missing into my build.gradle ? I've tried to use compileOnly into the dependencies definition, but it had no effect and have the same behavior as implementation

val commonMain by getting {
dependencies {
    compileOnly("com.poc.sample:KMPAPI:0.0.1")
}

Solution

  • You cannot create multiple Kotlin iOS frameworks and use them in the same project interchangeably. When the Kotlin compiler creates an iOS framework, it is its "own world", as in it includes everything you need (dependencies, etc). It's one big binary.

    The summary is, the config you want is not possible. You can use multiple Kotlin iOS frameworks in the same project, but they need to be fully independent. They won't be able to communicate with each other.