GradleUp / shadow

Gradle plugin to create fat/uber JARs, apply file transforms, and relocate packages for applications and libraries. Gradle version of Maven's Shade plugin.
https://www.gradleup.com/shadow/
Apache License 2.0
3.69k stars 389 forks source link

Shadow is not working with Kotlin Multiplatform plugin #484

Open Danilo-Araujo-Silva opened 5 years ago

Danilo-Araujo-Silva commented 5 years ago

Please check the User Guide before submitting "how do I do 'x'?" questions!

Shadow Version

5.0.0

Gradle Version

5.3.1

Expected Behavior

The shadowJar task should appear and work.

Actual Behavior

Only the knows task appears and the shadow task don't appear and don't work.

Gradle Build Script(s)

import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar
...
plugins {
    kotlin("multiplatform")

    id("com.github.johnrengelman.shadow") version "5.0.0"
}
...
tasks.withType<ShadowJar> {
    baseName = "app"
    classifier = ""
    version = ""
}

//// This works but do not really creat the fatJar, java -jar myFatJar.jar doesn't run and inside of this jar we have just a MANIFEST.MF with a single line of information.
//tasks.create("shadowJar", ShadowJar::class.java) {
//  baseName = "my_project"
//  classifier = ""
//  version = ""
//}

Content of Shadow JAR (jar tf <jar file> - post link to GIST if too long)

None.

Danilo-Araujo-Silva commented 5 years ago

I was able to have something working with:

import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar
...
plugins {
    kotlin("multiplatform")

    id("com.github.johnrengelman.shadow") version "5.0.0"
    id("java")
}
...
tasks.withType<ShadowJar> {
    manifest {
        attributes.put("Main-Class", "com.example.ExampleKt")
    }

    val target = kotlin.targets.jvm("myTarget")
    from(target.compilations["main"].output)
    val runtimeClasspath = target.compilations["main"].compileDependencyFiles as Configuration
    configurations = mutableListOf(runtimeClasspath)
}

But I need to be checking the other options available.

Ingwersaft commented 4 years ago

Your workaround didn't work for me, I had to modify it a little bit, maybe it helps someone :)

import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar

plugins {
    kotlin("multiplatform") version "1.3.50"
    id("com.github.johnrengelman.shadow") version "5.1.0"
}
val ktor_version: String by project
val kotlin_version: String by project
val logback_version: String by project

repositories {
    mavenCentral()
    mavenLocal()
    jcenter()
    maven { url = uri("https://kotlin.bintray.com/ktor") }
}

group = "<group>"

kotlin {
    jvm {
        compilations["main"].defaultSourceSet {
            dependencies {
                implementation(kotlin("stdlib-jdk8"))
                implementation("io.ktor:ktor-server-netty:$ktor_version")
                implementation("ch.qos.logback:logback-classic:$logback_version")
                implementation("io.ktor:ktor-server-core:$ktor_version")
                implementation("io.ktor:ktor-server-host-common:$ktor_version")
                implementation("io.ktor:ktor-metrics:$ktor_version")
                implementation("io.ktor:ktor-auth:$ktor_version")
                implementation("com.pi4j:pi4j-core:1.2")
            }
        }
        compilations["test"].defaultSourceSet {
            dependencies {
                implementation("io.ktor:ktor-server-tests:$ktor_version")
            }
        }
    }
    js().compilations["main"].defaultSourceSet {
        dependencies {
            implementation(kotlin("stdlib-js"))
        }
    }
}
tasks {
    val shadowCreate by creating(ShadowJar::class) {
        manifest {
            attributes["Main-Class"] = "<mainfullyqualified>"
        }
        archiveClassifier.set("all")
        from(kotlin.jvm().compilations.getByName("main").output)
        configurations =
            mutableListOf(kotlin.jvm().compilations.getByName("main").compileDependencyFiles as Configuration)
    }
    val build by existing {
        dependsOn(shadowCreate)
    }
}
avan1235 commented 2 years ago

You actually need also runtime dependencies imo, so the valid full configuration (with Kotlin idiomatic syntax) would contain

tasks.withType<ShadowJar> {
  manifest {
    attributes("Main-Class" to "main.fully.qualified.Class")
  }
  archiveClassifier.set("all")
  val main by kotlin.jvm().compilations
  from(main.output)
  configurations += main.compileDependencyFiles as Configuration
  configurations += main.runtimeDependencyFiles as Configuration
}
NorbertSandor commented 1 year ago

Is there a plan to support this feature? As I see, Kotlin is moving towards "multiplatform with single target" instead of the platform-specific Kotlin plugins (e.g. js will be deprecated, or it is already).

alexstyl commented 5 months ago

The previous mentioned tasks wouldn't compile on my end. Fixed it by doing:

tasks.withType<ShadowJar> {
    manifest {
        attributes.put("Main-Class", "MainKt") // "MainKt" or w/e your main class is
    }

    val target = kotlin.targets.named("desktop").get() //"desktop" or w/e name your jvm target is
    from(target.compilations["main"].output)
    val runtimeClasspath = target.compilations["main"].compileDependencyFiles
    configurations = mutableListOf(runtimeClasspath)
}

EDIT: The above works on a sample project but doesnt work on my main project. The shadowJar task is not in the tasks. Trying to figure this out.

EDIT 2: Figured it out. Needed to add id("java") in the plugins. Without it, the shadowJar task doesnt appear in tasks. Not sure how this will work as my multiplatform project is targeting Android too, and Android complains that you can't use java with libs.plugins.androidApplication but I'll figure it out.

Ynnck123 commented 2 months ago

@alexstyl did you manage to come up with a solution for the Android target?