Hello! I have a KMP module called analytics-interf...
# multiplatform
n
Hello! I have a KMP module called analytics-interface with targets
ios
and
jvm
that contains class A:
Copy code
class A {
    fun foo() { ... }
}
and another KMP module called analytics with targets
ios
and
android
that contains class B:
Copy code
actual class B : A() {
    fun bar() { ... }
}
When I run
./gradlew :analytics:assembleRelease
, the analytics-release.aar artifact is generated, and when I plug it in Android library, I can do
B().bar()
but not
B().foo()
. What am I doing wrong? EDIT Added a project to reproduce the issue https://gitlab.com/NikitaKhlebushkin/kmp-multi-module
k
That’s odd. Code example?
n
@kpgalligan, sure, which part exactly do you want?
a
Perhaps
analytics-interfase
dependency should be configured as
api
(not as
implementation
) for the
analytics
module.
n
@Arkadii Ivanov thanks, I tried that too, no success. I set it up like this:
Copy code
sourceSets {
        val commonMain by getting {
            dependencies {
                api(project(":analytics-interface"))
                implementation(kotlin("stdlib-common"))
                implementation(kotlin("reflect"))
            }
        }
}
r
Does it fail to build from Gradle or is it just red in the IDE? Sometimes the IDE gets confused when mixing jvm and android modules.
n
@russhwolf Build of analytics neither fails in Gradle nor is red in JVM. I did not try building Android project that uses output artifact of analytics, but what I did is I followed (Ctrl + click) into decompiling of B and it shows correctly that it is inherited from A but fails to find A
I changed
android
target in analytics project to
jvm
, but it didn't help
Seems like the problem is that
B
class is expect/actual kind of classes
And expected class cannot be inherited from anything
I don't really know how to cope with this problem
Added a project to reproduce the issue https://gitlab.com/NikitaKhlebushkin/kmp-multi-module
r
Oh yeah. I actually have seen that before. It’s not that
expect
class can’t inherit, it’s that you need to have the exact same class hierarchy between
expect
and
actual
. There’s a youtrack ticket for it at https://youtrack.jetbrains.com/issue/KT-23703
n
@russhwolf it seems that the hierarchy matches as much as possible (platform doesn't allow doing
expect class B: A()
, which is the only difference. Anything I could do about it?
g
I thinks I have the same issue: I have two multiplatform modules with the same targets: A and B. B depends on A as:
commonMainApi(project(":a"))
Then the final binary for iOS or JS does not contains any class from A
n
@gmazzo did you solve it somehow?
g
In a very very very hacky way: Instead of declaring a dependency on
A
, I’ve just added all
src/x
of
A
as a
srcDir
of
B
(and
C
).
A
was my
common
module.
Not ideal at all, but at least it works 🙃
So, if anyone has a working solution for this dependency problem, I’ll glad to know it
a
Well if the class B is expect/actual then to me such a behaviour is expected. I need to check but I believe I'm using this as a feature in one of my projects.
g
In my case, it has nothing to do with `expect`/`actual`. I have some final classes on
A
, that
B
and
C
should consume. Everything compiles just fine, but then when running those classes are missing.
a
I mean from my point of view,
actual class B : A
should not expose you A.
Let me check
g
Well, I’m not an expect on this, but I think if
class A
is defined in a dependency module
a
: If
a
is declared as
implementation
, then
actual class B : A
should fail to compile for exposing an internal class. If
a
is declared as
api
then it should work ok. But at least on my experience,
class A
doesn’t exist at all on native or js targets in module
b
artifact 😞
a
Perhaps you are right, it works as you expect if you extend e.g. a JDK class. Looks like a bug.
g
At this point I’m not sure if it’s a bug, something we have misted or an edge case. The generated
commonJs
code for
js
receives an injection dependency for the common module, as it’d expecting to have another native pacakge published for the
common
module. For JVM targets, you’ll see a dependency on the
common
module JAR. So I think this is an edge case not covered, because it doesn’t make sense to my that behaves differently depending on the platform: for JVM: it uses the transitively model from the POM, with a common jar artifact for Native and JS: it’s basically the same, expect that there is no dependency mechanism in place. A fat artifact is required then. I think the “fast” workaround w’d be to produce fat artifacts for all the platforms. The “right” solution ’d be to support native artifact for each platforms: NPM modules and CocoaPods
n
Thanks, I'll give it a try!
Would be nice to receive any feedback from JetBrains folk on whether it is expected behavior