Create fat jar from ktor Kotlin multiplatform project with Kotlin Gradle DSL

对着背影说爱祢 提交于 2020-07-23 07:37:16

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!