web-dev-qa-db-de.com

Mit Gradle und Kotlin ein selbstausführbares Glas erstellen

Ich habe eine einfache Kotlin-Quelldatei geschrieben, um zu beginnen, und eine Gradle-Skriptdatei ... __ Aber ich kann nicht herausfinden, wie man die Hauptfunktion zum Manifest hinzufügt, so dass das Glas selbst ausführbar sein kann .

Hier mein build.gradle-Skript:

buildscript {
    repositories {
        mavenCentral()
    }
    dependencies {
        classpath 'org.jetbrains.kotlin:kotlin-gradle-plugin:0.9.66'
    }
}
apply plugin: "kotlin"
repositories {
    mavenCentral()
}
dependencies {
    compile 'org.jetbrains.kotlin:kotlin-stdlib:0.9.66'
}

jar {
    manifest {
        attributes 'Main-Class': 'com.loloof64.kotlin.exps.ExpsPackage'
    }
}

Hier ist mein com.loloof64.kotlin.exps.Multideclarations.kt

package com.loloof64.kotlin.exps

class Person(val firstName: String, val lastName: String) {
    fun component1(): String {
        return firstName
    }
    fun component2(): String {
        return lastName
    }
}

fun main(args: Array < String > ) {
    val(first, last) = Person("Laurent", "Bernabé")
    println("First name : $first - Last name : $last")
}

Wenn ich jar vom Terminal (Java-jar MYJar.jar) starte, erhalte ich den folgenden Stacktrace, der besagt, dass die Klassen der Reflexionsbibliothek von Kotlin fehlen und tatsächlich nicht zum jar hinzugefügt wurden. Es scheint, dass mir die Kotlin-Compiler-Artefaktklassen aus dem letzten Glas und auch die Kotlin-Stdlib-Quellen fehlen, aber ich weiß nicht, wie ich den Gradle-Build anpassen soll.

$> Java -jar build/libs/kotlin_exps.jar 

Exception in thread "main" Java.lang.NoClassDefFoundError: kotlin/reflect/jvm/internal/InternalPackage
    at com.loloof64.kotlin.exps.ExpsPackage.<clinit>(MultiDeclarations.kt)
Caused by: Java.lang.ClassNotFoundException: kotlin.reflect.jvm.internal.InternalPackage
    at Java.net.URLClassLoader$1.run(URLClassLoader.Java:372)
    at Java.net.URLClassLoader$1.run(URLClassLoader.Java:361)
    at Java.security.AccessController.doPrivileged(Native Method)
    at Java.net.URLClassLoader.findClass(URLClassLoader.Java:360)
    at Java.lang.ClassLoader.loadClass(ClassLoader.Java:424)
    at Sun.misc.Launcher$AppClassLoader.loadClass(Launcher.Java:308)
    at Java.lang.ClassLoader.loadClass(ClassLoader.Java:357)
    ... 1 more

Ich benutze Kotlin 0.9.66 und Gradle 2.1

36
loloof64

Ich habe die Problemumgehung gefunden (danke an MkYong Website )

  1. Das Gradle-Skript benötigte das Kotlin-Compiler-Artefakt als Abhängigkeit
  2. Das Gradle-Skript benötigte eine Möglichkeit, alle Kotlin-Dateien zu sammeln und in das Gefäß zu legen.

Also bekomme ich mit dem folgenden Gradle-Skript:

buildscript {
    repositories {
        mavenCentral()
    }
    dependencies {
       classpath 'org.jetbrains.kotlin:kotlin-gradle-plugin:1.0.1-2'
    }
}

apply plugin: "kotlin"

repositories {
    mavenCentral()
}

dependencies {
    compile 'org.jetbrains.kotlin:kotlin-stdlib:1.0.1-2'
}

jar {
    manifest {
        attributes 'Main-Class': 'com.loloof64.kotlin.exps.MultideclarationsKT'
    }

    // NEW LINE HERE !!!
    from { configurations.compile.collect { it.isDirectory() ? it : zipTree(it) } }
}
24
loloof64

Fügen Sie das Plugin application hinzu, und legen Sie die mainClassName als fest

mainClassName = '[your_namespace].[your_arctifact]Kt'

Angenommen, Sie haben den folgenden Code in eine Datei mit dem Namen main.kt eingefügt:

package net.mydomain.kotlinlearn

import kotlin
import Java.util.ArrayList

fun main(args: Array<String>) {

    println("Hello!")

}

ihr build.gradle sollte sein:

apply plugin: 'kotlin'
apply plugin: 'application'

mainClassName = "net.mydomain.kotlinlearn.MainKt"

Tatsächlich erstellt Kotlin eine Klasse, um Ihre Hauptfunktion mit dem gleichen Namen Ihrer Datei zu kapseln - mit Title Case.

28
Guildenstern70

Keine der oben genannten Lösungen hat bei der Erstellung von Artifact funktioniert.

IDE-Version IntelliJ IDEA 2019.1.1.

Führen Sie die folgenden Schritte aus, um das Problem zu beheben

Schritte

Schritt 1 - Artefakt erstellen

  1. Gehen Sie zu Datei -> Projektstruktur -> Artefakte

  2. Klicken Sie auf + -> JAR -> From modules with dependencies

enter image description here

  1. Wählen Sie das Programm Main Class

enter image description here

Schritt 2 - MANIFEST-Pfad ändern

  1. Ändern Sie den Wert von Directory for META-INF/MANIFEST.MF In Ihr Projektstammverzeichnis.

    Zum Beispiel von /your/project/directory/src/main/kotlin Bis /your/project/directory

enter image description here

  1. Drücken Sie OK und dann Apply und OK.

Schritt 3 - Artefakt erstellen

  1. Zum Schluss gehen Sie zu Build -> Build Artifacts -> [your-artifact-name] -> Build.

Die generierte JAR -Datei befindet sich im Verzeichnis out/artifact/[your-artifact-name]. (y)

2
theapache64

Danke, für mich hat es funktioniert, indem wir den Glasabschnitt hinzugefügt haben

jar {
    manifest {
        attributes 'Main-Class': 'com.photofiles.Application'
    }

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

Keine Notwendigkeit für das Anwendungs-Plugin.

1
paucls

Für den Fall, dass Sie wie ich dumm sind:

Erstellen Sie Ihre IntelliJ-Laufkonfiguration nicht als Anwendung. IntelliJ geht davon aus, dass es Java ist und es wird nie funktionieren. Verwenden Sie stattdessen den Eintrag "Kotlin".

0
Tim Keating

Wenn Sie Gradle mit der KotlinDSL verwenden, hat meine duplicate -Frage eine Antwort auf:

import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar

plugins {
    kotlin("jvm") version "1.2.51"
    id("com.github.johnrengelman.shadow") version "2.0.4"
}

group = "xxx.yyy"
version = "1.0-SNAPSHOT"

repositories {
    mavenCentral()
}

dependencies {
    implementation(kotlin("stdlib-jdk8"))
}

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

tasks.withType<ShadowJar> {

    manifest.attributes.apply {
        put("Implementation-Title", "Gradle Jar File Example")
        //put("Implementation-Version" version)
        put("Main-Class", "HelloKotlinWorld.App")
    }

Welches ist meiner Meinung nach die einfachste Lösung. Oh, vielleicht verwenden Sie nur Kotlin selbst und nicht die DSL.

0
Thufir