I'm using Kotlin multi-platform (JVM & JS), which in IDEA creates three projects: demo
, demo-js
and demo-jvm
.
I would like to split the common code into more subprojects/submodules. Let's say I add commonmod
; how do I make it compile?
The error right now, for gradle run -p demo-jvm
, is:
demo/demo-js/src/main/kotlin/demo/commonmod/example.kt: (3, 12): Actual function 'getPlatform' has no corresponding expected declaration
but I think I'm doing this fundamentally wrong, as I don't know what should depend on what (although I tried quite some iterations). If I solve this error I get other ones, and then other ones again, until I'm back to this one.
As a minimal-but-still-large example, I have:
demo/settings.gradle:
rootProject.name = 'demo'
include 'demo-jvm', 'demo-js', 'commonmod'
demo/build.gradle:
buildscript { ... }
apply plugin: 'kotlin-platform-common'
repositories {
mavenCentral()
}
dependencies {
compile "org.jetbrains.kotlin:kotlin-stdlib-common:$kotlin_version"
testCompile "org.jetbrains.kotlin:kotlin-test-annotations-common:$kotlin_version"
testCompile "org.jetbrains.kotlin:kotlin-test-common:$kotlin_version"
compile project(':commonmod')
}
demo/demo-jvm/settings.gradle:
rootProject.name = 'demo'
demo/demo-jvm/build.gradle:
buildscript { ... }
apply plugin: 'kotlin-platform-jvm'
apply plugin: 'application'
repositories {
mavenCentral()
}
mainClassName = "demo.MainKt"
dependencies {
compile "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
expectedBy project(":")
testCompile "junit:junit:4.12"
testCompile "org.jetbrains.kotlin:kotlin-test-junit:$kotlin_version"
testCompile "org.jetbrains.kotlin:kotlin-test:$kotlin_version"
}
demo/demo-js/settings.gradle:
rootProject.name = 'demo'
demo/demo-js/build.gradle:
buildscript { ... }
apply plugin: 'kotlin-platform-js'
repositories {
mavenCentral()
}
dependencies {
compile "org.jetbrains.kotlin:kotlin-stdlib-js:$kotlin_version"
expectedBy project(":")
testCompile "org.jetbrains.kotlin:kotlin-test-js:$kotlin_version"
}
demo/commonmod/settings.gradle:
rootProject.name = 'demo'
include 'demo-jvm', 'demo-js'
demo/commonmod/build.gradle:
buildscript { ... }
apply plugin: 'kotlin-platform-common'
repositories {
mavenCentral()
}
dependencies {
compile "org.jetbrains.kotlin:kotlin-stdlib-common:$kotlin_version"
testCompile "org.jetbrains.kotlin:kotlin-test-annotations-common:$kotlin_version"
testCompile "org.jetbrains.kotlin:kotlin-test-common:$kotlin_version"
compile project(':demo-js')
compile project(':demo-jvm')
}
This took a crazy amount of time, so I hope this is useful for someone!
There is a functional example on Github: kotlin_multiplatform_gradle_demo
Several sources helped, but a lot of it was trial and error, so if something is bad practise, please let me know!
For the minimal example, the structure is like this:
├── alpha
│ ├── alpha-js
│ │ └── build.gradle
│ ├── alpha-jvm
│ │ └── build.gradle
│ ├── build.gradle
│ └── src
│ └── main
│ ├── kotlin
│ │ └── demo
│ │ └── alpha
│ │ └── main.kt
├── beta
│ ├── beta-js
│ │ ├── build.gradle
│ │ └── src
│ │ └── main
│ │ └── kotlin
│ │ └── demo
│ │ └── beta
│ │ └── platform.kt
│ ├── beta-jvm
│ │ ├── build.gradle
│ │ └── src
│ │ └── main
│ │ └── kotlin
│ │ └── demo
│ │ └── beta
│ │ └── platform.kt
│ ├── build.gradle
│ └── src
│ └── main
│ └── kotlin
│ └── demo
│ └── beta
│ └── platform.kt
├── build.gradle
└── settings.gradle
The common modules (alpha
and beta
) need platform modules for each platform with at least a `build.gradle``.
The settings.gradle
file imports all modules, including platform ones.
Dependencies, e.g. from alpha on beta, is declared in the common alpha module and all alpha platform modules.
Some patterns I learned:
alpha
, the javascript platform module must be called alpha-js
(similar for -jvm
).alpha:alpha-js
).expectedBy project(":the_common_module")
.If module alpha
depends on beta
, then
alpha
must have dependencies { compile project(":beta") }
alpha-js
must have dependencies { compile project(":beta:beta-js") }
(in addition to expectedBy
)alpha-jvm
must have dependencies { compile project(":beta:beta-jvm") }
(in addition to expectedBy
) etcOnly the top module has settings.gradle
, which includes ALL submodules (including platform ones).
I used to have the full config files here, but it's better to just check the code on Github because it's really long.