it-swarm.com.de

Erstellen von lauffähigem JAR mit Gradle

Bisher habe ich ausführbare JAR-Dateien über die Eclipse-Funktion "Exportieren ..." erstellt, aber jetzt bin ich für die Build-Automatisierung auf IntelliJ IDEA und Gradle umgestiegen.

In einigen Artikeln wird das Plugin "application" vorgeschlagen, dies führt jedoch nicht zu dem erwarteten Ergebnis (nur eine JAR, keine Startskripte oder ähnliches).

Wie kann ich dasselbe Ergebnis erzielen, das Eclipse mit dem Dialogfeld "Exportieren ..." erzielt?

122
Hannes

Eine ausführbare JAR-Datei ist nur eine JAR-Datei, die einen Hauptklasseneintrag in ihrem Manifest enthält. Sie müssen also nur die jar-Task konfigurieren, um diesen Eintrag in das Manifest einzufügen:

jar {
    manifest {
        attributes 'Main-Class': 'com.foo.bar.MainClass'
    }
}

Möglicherweise müssen Sie auch Klassenpfadeinträge in das Manifest einfügen, dies geschieht jedoch auf die gleiche Weise.

Siehe http://docs.Oracle.com/javase/tutorial/deployment/jar/manifestindex.html

142
JB Nizet

Die Antworten von JB Nizet und Jorge_B sind korrekt.

In der einfachsten Form müssen zum Erstellen einer ausführbaren JAR-Datei mit Gradle nur die entsprechenden Einträge zum Manifest hinzugefügt werden. Abhängigkeiten, die in den Klassenpfad aufgenommen werden müssen, sind jedoch weitaus häufiger, was diesen Ansatz in der Praxis schwierig macht.

Das Anwendungs-Plugin bietet einen alternativen Ansatz. Anstatt eine ausführbare JAR-Datei zu erstellen, bietet sie Folgendes:

  • eine run Aufgabe, um das einfache Ausführen der Anwendung direkt aus dem Build heraus zu erleichtern
  • eine installDist -Aufgabe, die eine Verzeichnisstruktur generiert, die die erstellte JAR, alle JARs, von denen sie abhängt, und ein Startskript enthält, das alles in einem Programm zusammenfasst, das Sie ausführen können
  • distZip und distTar Aufgaben, die Archive erstellen, die eine vollständige Anwendungsverteilung enthalten (Startskripte und JARs)

Ein dritter Ansatz besteht darin, eine sogenannte "fat JAR" zu erstellen, bei der es sich um eine ausführbare JAR handelt, die nicht nur den Code Ihrer Komponente, sondern auch alle Abhängigkeiten enthält. Es gibt einige verschiedene Plugins, die diesen Ansatz verwenden. Ich habe Links zu einigen hinzugefügt, die mir bekannt sind. Ich bin mir sicher, dass es noch mehr gibt.

90
davidmc24

Wie bereits erwähnt, muss der Einstiegspunkt der Anwendung im Attribut Main-Class Der Manifestdatei festgelegt werden, damit eine JAR-Datei ausführbar ist. Wenn die Abhängigkeitsklassendateien nicht zusammengestellt sind, müssen sie im Eintrag Class-Path Der Manifestdatei festgelegt werden.

Ich habe alle möglichen Plugin-Kombinationen ausprobiert und was nicht für die einfache Aufgabe, ein ausführbares Jar zu erstellen und irgendwie die Abhängigkeiten einzubeziehen. Alle Plugins scheinen auf die eine oder andere Weise zu fehlen, aber schließlich habe ich es so bekommen, wie ich es wollte. Keine mysteriösen Skripte, keine Millionen verschiedene Mini-Dateien, die das Build-Verzeichnis verschmutzen, keine ziemlich saubere Build-Skript-Datei und vor allem: Keine Million fremde Dateien von Drittanbietern, die in mein JAR-Archiv aufgenommen wurden.

Das Folgende ist ein Kopieren-Einfügen von hier für Ihre Bequemlichkeit.

[How-to] Erstellen Sie eine Distributions-Zip-Datei mit Dependency Jars im Unterverzeichnis /lib Und fügen Sie alle Abhängigkeiten zum Eintrag Class-Path In der Manifest-Datei hinzu:

apply plugin: 'Java'
apply plugin: 'Java-library-distribution'

repositories {
    mavenCentral()
}

dependencies {
    compile 'org.Apache.commons:commons-lang3:3.3.2'
}

// Task "distZip" added by plugin "Java-library-distribution":
distZip.shouldRunAfter(build)

jar {
    // Keep jar clean:
    exclude 'META-INF/*.SF', 'META-INF/*.DSA', 'META-INF/*.RSA', 'META-INF/*.MF'

    manifest {
        attributes 'Main-Class': 'com.somepackage.MainClass',
                   'Class-Path': configurations.runtime.files.collect { "lib/$it.name" }.join(' ')
    }
    // How-to add class path:
    //     https://stackoverflow.com/questions/22659463/add-classpath-in-manifest-using-gradle
    //     https://Gist.github.com/simon04/6865179
}

Als Kernstück gehostet hier .

Das Ergebnis befindet sich in build/distributions Und der entpackte Inhalt sieht folgendermaßen aus:

lib/commons-lang3-3.3.2.jar
MyJarFile.jar

Inhalt von MyJarFile.jar#META-INF/MANIFEST.mf:

Manifest-Version: 1.0
Hauptklasse: com.somepackage.MainClass
Klassenpfad: lib/commons-lang3-3.3.2.jar

31

Die Lösung mit dem geringsten Aufwand bestand für mich darin, das Gradle-Shadow-Plugin zu verwenden

Neben dem Anwenden des Plugins ist alles, was getan werden muss,:

Konfigurieren Sie die JAR-Task, um Ihre Main-Klasse in das Manifest zu setzen

jar {
  manifest {
   attributes 'Main-Class': 'com.my.app.Main'
  }
}

Führen Sie die Gradle-Aufgabe aus

./gradlew shadowJar

Nimm das app-version-all.jar aus build/libs /

Und schließlich führen Sie es aus über:

Java -jar app-version-all.jar
22
Ostkontentitan

Haben Sie die Task 'installApp' ausprobiert? Erstellt es kein vollständiges Verzeichnis mit einer Reihe von Startskripten?

http://www.gradle.org/docs/current/userguide/application_plugin.html

5
Jorge_B

Vielen Dank, Konstantin, es hat wie ein Zauber mit wenigen Nuancen funktioniert. Aus irgendeinem Grund funktionierte die Angabe der Hauptklasse als Teil des JAR-Manifests nicht ganz und es sollte stattdessen das Attribut mainClassName verwendet werden. Hier ist ein Ausschnitt aus build.gradle, der alles enthält, damit es funktioniert:

plugins {
  id 'Java' 
  id 'com.github.johnrengelman.shadow' version '1.2.2'
}
...
...
apply plugin: 'application'
apply plugin: 'com.github.johnrengelman.shadow'
...
...
mainClassName = 'com.acme.myapp.MyClassMain'
...
...
...
shadowJar {
    baseName = 'myapp'
}

Nach dem Ausführen von gradle shadowJar erhalten Sie myapp- {version} -all.jar in Ihrem Build-Ordner, das als Java -jar myapp- {version} -all.jar ausgeführt werden kann.

4
Alex Yavorskiy

Sie können ein Jar-Artefakt in den Moduleinstellungen (oder der Projektstruktur) definieren.

  • Klicken Sie mit der rechten Maustaste auf das Modul> Moduleinstellungen öffnen> Artefakte> +> JAR> aus Modulen mit Abhängigkeiten.
  • Legen Sie die Hauptklasse fest.

Das Erstellen eines Glases ist dann so einfach wie das Klicken auf "Artefakt erstellen ..." im Menü "Erstellen". Als Bonus können Sie alle Abhängigkeiten in einem einzigen Glas verpacken.

Getestet auf IntelliJ IDEA 14 Ultimate.

3
Mondain

Ich habe einige Links auf die Lösung überprüft und schließlich die folgenden Schritte ausgeführt, um sie zum Laufen zu bringen. Ich benutze Gradle 2.9.

Nehmen Sie die folgenden Änderungen in Ihrer Build-Gradle-Datei vor:

  1. Plugin erwähnen:

    apply plugin: 'eu.appsatori.fatjar'
    
  2. Stellen Sie das Buildscript bereit:

    buildscript {
    repositories {
        jcenter()
    }
    
    dependencies {
        classpath "eu.appsatori:gradle-fatjar-plugin:0.3"
    }
    }
    
  3. Geben Sie die Hauptklasse an:

    fatJar {
      classifier 'fat'
      manifest {
        attributes 'Main-Class': 'my.project.core.MyMainClass'
      }
      exclude 'META-INF/*.DSA', 'META-INF/*.RSA', 'META-INF/*.SF'
    }
    
  4. Erstelle den Fatjar:

    ./gradlew clean fatjar
    
  5. Führen Sie das fatjar aus/build/libs /:

    Java -jar MyFatJar.jar
    
2
Sandeep Sarkar