Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to create a Fat JAR with the Kotlin DSL?

I'm using Gradle 5.5. I have a Groovy-based build script that I'm trying to migrate to the Kotlin DSL. The jar task contains the typical line for copying all dependencies to the JAR file:

from { configurations.compile.collect { it.isDirectory() ? it : zipTree(it) } }

I can't find a way to translate this line to the Kotlin DSL.

Let me give you some context. This is my original Groovy-based build script:

plugins {
    id "org.jetbrains.kotlin.jvm" version "1.3.41"
}

group = "com.rhubarb_lip_sync"
version = "1.0.0"

repositories {
    mavenCentral()
    jcenter()
}

dependencies {
    compile "com.beust:klaxon:5.0.1"
    compile "org.apache.commons:commons-lang3:3.9"
    compile "no.tornado:tornadofx:1.7.19"
}

compileKotlin {
    kotlinOptions.jvmTarget = "1.8"
}
compileTestKotlin {
    kotlinOptions.jvmTarget = "1.8"
}

jar {
    manifest {
        attributes "Main-Class": "com.rhubarb_lip_sync.rhubarb_for_spine.MainKt"
    }

    // This line of code recursively collects and copies all of a project"s files
    // and adds them to the JAR itself. One can extend this task, to skip certain 
    // files or particular types at will
    from { configurations.compile.collect { it.isDirectory() ? it : zipTree(it) } }
}

And this is my Kotlin-based build script. It's working fine, except for that one line:

import org.jetbrains.kotlin.gradle.tasks.KotlinCompile

plugins {
    kotlin("jvm") version "1.3.41"
}

group = "com.rhubarb_lip_sync"
version = "1.0.0"

repositories {
    mavenCentral()
    jcenter()
}

dependencies {
    implementation(kotlin("stdlib-jdk8"))
    implementation("com.beust:klaxon:5.0.1")
    implementation("org.apache.commons:commons-lang3:3.9")
    implementation("no.tornado:tornadofx:1.7.19")
}

tasks.withType<KotlinCompile> {
    kotlinOptions.jvmTarget = "1.8"
}

tasks.withType<Jar> {
    manifest {
        attributes("Main-Class" to "com.rhubarb_lip_sync.rhubarb_for_spine.MainKt")
    }

    // ?
}

like image 544
Daniel Wolf Avatar asked Jul 19 '19 17:07

Daniel Wolf


People also ask

What is a fat jar file?

An uber-JAR—also known as a fat JAR or JAR with dependencies—is a JAR file that contains not only a Java program, but embeds its dependencies as well. This means that the JAR functions as an “all-in-one” distribution of the software, without needing any other Java code.

How do I enable kotlin DSL?

To activate the Kotlin DSL, simply use the . gradle. kts extension for your build scripts in place of . gradle .

Where can I find examples of Kotlin DSLs?

Many other Kotlin DSL examples are available and you can find them on GitHub. As a starter, have a look at Kotlintest or kotlinx.html for instance. If you like to have a look at my examples or even want to contribute, the code is available here: SeKurity.

What is the use of apply in Kotlin?

This small piece of source code contains four usages of apply, a method that makes use of Function Literals with Receiver. It's one of Kotlin's famous scope functions, which creates a scope on an arbitrary context object, in which we access members of that context object without additional qualifiers.

Is there a Kotlin DSL for Gradle?

There’s also a Kotlin DSL for Gradle available: Gradle-Script-Kotlin Simon is a software engineer with 9+ years of experience developing software on multiple platforms including the JVM and Serverless environments. He currently builds scalable distributed services for a decision automation SaaS platform. Simon is a self-appointed Kotlin enthusiast.

How do I build a “fat” jar of dependencies in Gradle?

To build a “fat” Jar of your Java or Kotlin project that contains all the dependencies within a single file, you can use the shadow Gradle plugin. I found it hard to find clear documentation on how it works using the Gradle Kotlin DSL (with a build.gradle.kts instead of build.gradle) so here is how I did it:


2 Answers

collect() in groovy is map() in Kotlin.

The ternary operator of groovy can be transformed into an if in Kotlin.

The main difference is that configurations.compile in Kotlin is not a Configuration but a Provider<Configuration>. So either you get the configuration out of the Provider, or you stay lazy by mapping the Provider to another Provider. So I think it should work

from(configurations.compileClasspath.get().map { if (it.isDirectory()) it else zipTree(it) })

or

from(configurations.compileClasspath.map { config -> config.map { if (it.isDirectory) it else zipTree(it) } })

Note that compile is deprecated for a long time now. Since use implementation now to declare your dependencies, there's nothing anymore in the compile configuration, and you must get the dependencies out of the compileClasspath one to build your uber jar.

like image 134
JB Nizet Avatar answered Oct 04 '22 04:10

JB Nizet


Here is a great sample by Maksim Kostromin

val mainClass = "com.myproject" // Replace this, your project main name

tasks {
  register("fatJar", Jar::class.java) {
    archiveClassifier.set("all")
    duplicatesStrategy = DuplicatesStrategy.EXCLUDE
    manifest {
      attributes("Main-Class" to mainClass)
    }
    from(configurations.runtimeClasspath.get()
        .onEach { println("add from dependencies: ${it.name}") }
        .map { if (it.isDirectory) it else zipTree(it) })
    val sourcesMain = sourceSets.main.get()
    sourcesMain.allSource.forEach { println("add from sources: ${it.name}") }
    from(sourcesMain.output)
  }
}
like image 44
Thiago Avatar answered Oct 04 '22 02:10

Thiago