问题
Trying to create a runnable jar for a kotlin multiplatform project which includes a ktor server component, building with Kotlin Gradle DSL.
I have seen several questions including Create fat jar from kotlin multiplatform project which asks and answers how to create the gradle build file in Groovy, but how do you do it in kotlin dsl?
The groovy code that is reported to work is:
kotlin {
jvm() {
withJava()
jvmJar {
manifest {
attributes 'Main-Class': 'sample.MainKt'
}
from { configurations.runtimeClasspath.collect { it.isDirectory() ? it : zipTree(it) } }
}
}
...
}
How would this translate to Kotlin DSL? I have tried many variations, some of which compile and run, but don't create the desired output... a runnable jar.
回答1:
@andylamax answer is pretty close but leads to the error that @cfnz was seeing
To fix that you need to add doFirst
as in this example:
val jvm = jvm() {
withJava()
val jvmJar by tasks.getting(org.gradle.jvm.tasks.Jar::class) {
doFirst {
manifest {
attributes["Main-Class"] = project.ext["mainClass"]
}
from(configurations.getByName("runtimeClasspath").map { if (it.isDirectory) it else zipTree(it) })
}
}
}
It is working as expected in here with gradle jvmJar && java -jar build/libs/laguna-jvm.jar
回答2:
Your groovy dsl can be written in kotlin as follows
kotlin {
jvm {
withJava()
val jvmJar by tasks.getting(org.gradle.jvm.tasks.Jar::class) {
manifest {
attributes["Main-Class"] = "sample.MainKt"
}
from(configurations.getByName("runtimeClasspath").map { if (it.isDirectory) it else zipTree(it) })
}
}
}
回答3:
I spent 3 days trying to get the fat jar to work, below is the solution and what follows before the solution is clarification:
ERRORS I MADE EARLY
- Shouldn't have rushed into docker, should've made fat jar work local first.
- withJava() was left out, this was the main waste of 36 man hours... WTF is the point of this function?
- dependsOn(build): why the jar task type doesn't know this already I do not understand.
- main.compileDependencyFiles: I was using this for a time in place of the map from argument below.
- main.output.classesDirs: was missing from other solutions and is what seems to include your actual code.
NOTE: No shadow plug in required, which is fantastic (gradle plugins tend not to play well together IMHO, ever).
NOTE: Versioning is important because this stack seems to change roughly 50 times faster than the documentation does in some cases, the following was used for this solution:
- Kotlin 1.3.72
- Gradle 6.5
- Ktor 1.3.2
CODE:
//Import variables from gradle.properties
val environment: String by project
val kotlinVersion: String by project
val ktorVersion: String by project
//Build File Configuration
plugins {
java
kotlin("multiplatform") version "1.3.72"
}
group = "com.app"
version = "1.0-SNAPSHOT"
repositories {
mavenCentral()
jcenter()
jcenter {
url = uri("https://kotlin.bintray.com/kotlin-js-wrappers")
}
maven {
url = uri("https://jitpack.io")
}
}
//Multiplatform Configuration
kotlin {
jvm {
withJava()
compilations {
val main = getByName("main")
tasks {
register<Jar>("buildFatJar2") {
group = "application"
dependsOn(build)
manifest {
attributes["Main-Class"] = "com.app.BackendAppKt"
}
from(configurations.getByName("runtimeClasspath").map { if (it.isDirectory) it else zipTree(it) }, main.output.classesDirs)
archiveBaseName.set("${project.name}-fat2")
}
}
}
}
js {
browser {
}
}
sourceSets { SKIPPED FOR LENGTH }
}
I hope this saves someone 3 days, let me know if you find improvements (I'm still learning too). Kotlin, gradle, multiplatform, docker... all are very tough to deal with, they need to update the docs in parallel IMHO or jetbrains is doomed.
POTENTIAL IMPROVEMENTS:
- The produced jar looks much bigger than it should be with tons of unnecessary stuff, suspect changing to the compile path instead of runtime path will fix that (CONFIRMED 30% size reduction).
- More manifest attributes perhaps.
- Also worth noting, I read an article aptly suggesting fatJars shouldn't be deployed to docker, that the java dependencies should be built as part of the image.
来源:https://stackoverflow.com/questions/61245847/create-fat-jar-from-ktor-kotlin-multiplatform-project-with-kotlin-gradle-dsl