shadow icon indicating copy to clipboard operation
shadow copied to clipboard

Shadow is not working with Kotlin Multiplatform plugin

Open Danilo-Araujo-Silva opened this issue 5 years ago • 6 comments

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 avatar Apr 25 '19 16:04 Danilo-Araujo-Silva

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.

Danilo-Araujo-Silva avatar Apr 25 '19 18:04 Danilo-Araujo-Silva

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)
    }
}

Ingwersaft avatar Nov 03 '19 13:11 Ingwersaft

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
}

avan1235 avatar Feb 24 '22 10:02 avan1235

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).

NorbertSandor avatar Jul 12 '23 06:07 NorbertSandor

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.

alexstyl avatar Mar 27 '24 09:03 alexstyl

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

Ynnck123 avatar Jul 11 '24 06:07 Ynnck123