I believe there are some problems with Android configuration which aren’t actually related to MPP. To find out the root issue, try some additional logging, described here — stack traces will help you to get the idea what’s actually wrong with that. So far, it’s hard to diagnose what is the problem, not enough information for that.
As to shadow
plugin (com.github.johnrengelman.shadow
), the situation is as follows.
-
in case of using
jvmWithJava
target, it should work as is, just apply it from the top level of thebuild.gradle
script. Note, hovewer, that the target is going to be deprecated as it’s already said above. -
when using with
jvm
target, an additional task definition is needed, like the following:task shadowJar(type: com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar) { def target = kotlin.targets.jvm6 from target.compilations.main.output def runtimeClasspath = target.compilations.main.runtimeDependencyFiles configurations = [runtimeClasspath] }
— where
jvm6
is the JVM target’s name.So overall
build.gradle
will look like:group 'com.example' version '1.0' buildscript { repositories { jcenter() } dependencies { classpath 'org.jetbrains.kotlin:kotlin-gradle-plugin:1.3.10' classpath 'com.github.jengelman.gradle.plugins:shadow:4.0.2' } } apply plugin: 'kotlin-multiplatform' apply plugin: 'com.github.johnrengelman.shadow' repositories { jcenter() } kotlin { targets { fromPreset(presets.jvm, 'jvm6') } sourceSets { commonMain { dependencies { api 'org.jetbrains.kotlin:kotlin-stdlib-common' } } jvm6Main { dependencies { api 'org.jetbrains.kotlin:kotlin-stdlib' } } } } task shadowJar(type: com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar) { from kotlin.targets.jvm6.compilations.main.output def runtimeClasspath = kotlin.targets.jvm6.compilations.main.runtimeDependencyFiles configurations = [runtimeClasspath]
The support of kotlin-frontend plugin for JS is in progress right now, you may track the progress via this issue.
Generated a stack trace, saved to
https://scans.gradle.com/s/kckuuohn2u23q/console-log
For now, got it working by hooking my task onto compileDebugSources
That specific task did not work, but with your idea of using a specific task found compileDebugSources which does work
thank you for reply, i’m tried shadow plugin in this way:
buildscript {
repositories {
jcenter()
}
dependencies {
classpath 'com.github.jengelman.gradle.plugins:shadow:2.0.1'
}
}
plugins {
id 'kotlin-multiplatform' version '1.3.10'
id 'kotlinx-serialization' version '1.3.10'
}
apply plugin: 'com.github.johnrengelman.shadow'
repositories {
jcenter()
mavenCentral()
maven { url "https://dl.bintray.com/kotlin/ktor" }
maven { url "https://kotlin.bintray.com/kotlinx" }
maven { url "http://dl.bintray.com/kotlin/kotlin-eap" }
maven { url "http://dl.bintray.com/kotlin/kotlin-js-wrappers" }
}
kotlin {
ext.ktor_version = '1.0.0-beta-4'
ext.serialization_version = '0.9.0'
targets {
fromPreset(presets.jvm, 'jvm')
fromPreset(presets.js, 'js')
}
sourceSets {
commonMain {
dependencies {
implementation 'org.jetbrains.kotlin:kotlin-stdlib-common'
implementation "org.jetbrains.kotlinx:kotlinx-serialization-runtime-common:$serialization_version"
}
}
commonTest {
dependencies {
implementation 'org.jetbrains.kotlin:kotlin-test-common'
implementation 'org.jetbrains.kotlin:kotlin-test-annotations-common'
}
}
jvmMain {
dependencies {
implementation 'org.jetbrains.kotlin:kotlin-stdlib-jdk8'
implementation 'org.jetbrains.exposed:exposed:0.9.1'
implementation "io.ktor:ktor-server-netty:$ktor_version"
implementation "io.ktor:ktor-gson:$ktor_version"
implementation "io.ktor:ktor-client-core:$ktor_version"
implementation "io.ktor:ktor-client-cio:$ktor_version"
implementation "io.ktor:ktor-locations:$ktor_version"
implementation "io.ktor:ktor-html-builder:$ktor_version"
implementation "org.jetbrains.kotlinx:kotlinx-serialization-runtime:$serialization_version"
implementation "mysql:mysql-connector-java:8.0.7-dmr"
}
}
jvmTest {
dependencies {
implementation 'org.jetbrains.kotlin:kotlin-test'
implementation 'org.jetbrains.kotlin:kotlin-test-junit'
}
}
jsMain {
dependencies {
implementation 'org.jetbrains.kotlin:kotlin-stdlib-js'
implementation "org.jetbrains.kotlinx:kotlinx-serialization-runtime-js:$serialization_version"
implementation 'org.jetbrains:kotlin-react:16.6.0-pre.59-kotlin-1.3.0'
implementation 'org.jetbrains:kotlin-react-dom:16.6.0-pre.59-kotlin-1.3.0'
}
}
jsTest {
dependencies {
implementation 'org.jetbrains.kotlin:kotlin-test-js'
}
}
}
}
task shadowJar(type: com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar) {
def target = kotlin.targets.jvm
from target.compilations.main.output
def runtimeClasspath = target.compilations.main.runtimeDependencyFiles
configurations = [runtimeClasspath]
println "task shadow jar"
}
it builds but jar is not fat…
@leonid
I tried your build script, and by running ./gradlew shadowJar
I got a fat JAR under build/libs/test-project.jar
which contains the dependencies:
$ unzip build/libs/test-project.jar
$ tree build/libs/test-project -L 2 -d
.
├── com
│ ├── google
│ ├── mysql
│ └── typesafe
├── io
│ ├── ktor
│ └── netty
├── junit
│ ├── extensions
│ ├── framework
│ ├── runner
│ └── textui
├── kotlin
│ ├── annotation
│ ├── collections
│ ├── comparisons
│ ├── concurrent
│ ├── contracts
│ ├── coroutines
│ ├── experimental
│ ├── internal
│ ├── io
│ ├── jdk7
│ ├── js
│ ├── jvm
│ ├── math
│ ├── properties
│ ├── random
│ ├── ranges
│ ├── reflect
│ ├── sequences
│ ├── streams
│ ├── system
│ └── text
├── kotlinx
│ ├── atomicfu
│ ├── coroutines
│ ├── html
│ ├── io
│ └── serialization
├── META-INF
│ ├── maven
│ ├── proguard
│ └── services
└── org
├── eclipse
├── hamcrest
├── intellij
├── jetbrains
├── joda
├── json
├── junit
└── slf4j
Is your result different? What do you mean by ‘jar is not fat’?
@leonid Note that the shadow JAR is created alongside with the normal JAR for the JVM target. The normal JAR is suffixed with -jvm
. It is up to you to replace the normal JVM JAR with the fat one whenever it is used or published.
yes, it works, thank you
You guys should really add this to documentation.
@wild_lynx Hi, I’ve tried creating a project from template (Kotlin - Mobile Android and iOS) in Idea 2018.3.1, kotlin plugin 1.3.11-release-IJ2018.3-1, gradle 4.7. I’ve tried adding jvm target for ktor server I planned and building that target throws this error Error:Kotlin: Unsupported plugin option: org.jetbrains.kotlin.android:enabled=true
.
Looking at module setting, it appears that all targets/submodules/sourcesets have android plugin enabled in “Compiler Plugins” tab. I’ve tried removing that in .idea project files but it just reappears after IDE restart. Any suggestions? build.gradle.xml (3.1 KB)
It would be good to have, or may it already exist, an example for new mpp model, like kotlin-fullstack-example ktor 0.9.0 · Issue #27 · Kotlin/kotlin-fullstack-sample · GitHub
Please make sure in IDE that Preferences | Build, Execution, Deployment | Build Tools | Gradle | Runner > Delegate IDE build/run actions to gradle is checked. For the IDEA’s built-in builder (JPS), there is an issue. Does it help?
Also please note that in general, Gradle is a preferred way to build the multiplatform projects; JPS has certain limitations (in particular, it wouldn’t build any of Native targets, such as iOS in your project).
A small comment on the build.gradle
you’ve shared: for the source sets generated from the presets (jvm
, js
, etc.), it isn’t necessary to specify explicitly the dependencies of the corresponding *Main
and *Test
compilations on commonMain
and commonTest
explicitly, those are specified already by default, as it said at the documentation. So the following line of your configuration for serverMain
may be simply removed: dependsOn commonMain
Indeed, there are some already. You may try various samples generated by IDEA via New Project Wizard: open Kotlin section, there are four of them (Multiplatform).
Also, please have a look:
• GitHub - orangy/multiplatform-lib: Sample multiplatform library in Kotlin with tests and publishing
• GitHub - h0tk3y/better-parse: A nice parser combinator library for Kotlin
• GitHub - Kotlin/kotlinx.atomicfu: The idiomatic way to use atomic operations in Kotlin
• GitHub - Kotlin/kmm-basic-sample: Example of Kotlin multiplatform project
• GitHub - JetBrains/kotlinconf-app: KotlinConf Schedule Application
• GitHub - jonnyzzz/kotlin-fractals
• GitHub - jonnyzzz/kotlin-mpp-mobile
• GitHub - RubyLichtenstein/Kotlin-Multiplatform-Firebase: Kotlin Multiplatform - Android/iOS/Web/Node.Js(FIrebase)
Thanks, offloading build to gradle fixed the build issues. Btw, should jvm server be runnable from IDEA now? Cause I’m having troubles just running hello world server, I get this error: Error: Could not find or load main class rs.mmitic.MainKt
It’s possible that I’m just a dummy, I haven’t coded in Kotlin that much but I’ve tried lots of stuff:
package rs.mmitic
import sample.hello
object Main {
@JvmStatic
fun main(args: Array<String>) {
print(hello())
}
}
class Main2 {
companion object {
@JvmStatic
fun main(vararg args: String) {}
}
}
fun main(args: Array<String>) {
print(hello())
}
There is an issue with main
run in IDEA for the multiplatform projects having Android
target among others.
As a workaround, a Gradle task for the main
run may be specified:
task run(type: JavaExec) {
main = 'sample.SampleJKt'
def target = kotlin.targets.jvm
def compilation = target.compilations.main
def classes = files(
compilation.runtimeDependencyFiles,
compilation.output.allOutputs
)
classpath = classes
}
— where main
is a path to the class with main()
function defined as follows:
- if
main
is declared as a top-level function, then packageName + “.” + fileName.capitalized().removeSuffix(“.kt”) + “Kt” - if
main
is declared inside of anobject
, then packageName + “.” + objectName
For a file without package, for example, ActualB.kt
: main = 'ActualBKt'
Thanks a lot.
Is it going to be the only way to work around the absence of jvmWithJava
? In Okio, we’ve got unit tests written in Java living in the JVM module: their main value is that they test the API from the perspective of a Java user of the library and help us keep the API Java-friendly. Some unit tests rely on internal
members, hence moving them into a separate module is not an option. Inability to compile and run Java code in the JVM module is pretty inconvenient and will require a lot of redesign on our part.
@Egorand Yes, for now. But we are going to introduce Java support in the future releases, in some form. From what I can say now, it will likely be something quite similar to jvmWithJava
, because applying the java
Gradle plugin seems to be the only way to reach compatibility with existing 3rd-party plugins that work with Java. So if you try to use jvmWithJava
, then your feedback is welcome. The issue for Java support that you can follow is: KT-26256.
Thanks! Here’s an issue I filed a couple days ago: https://youtrack.jetbrains.com/issue/KT-28985
Doesn’t look like the plugin plays well with Dokka, and it’s not mentioned on the official docs page. Is Dokka gonna be supported eventually?