web-dev-qa-db-fra.com

Créer un fichier JAR exécutable avec Gradle

Jusqu'à présent, je créais des fichiers JAR exécutables via la fonctionnalité "Exporter ..." d'Eclipse, mais je passais maintenant à IntelliJ IDEA et à Gradle pour l'automatisation de la construction.

Certains articles suggèrent ici le plug-in "application", mais cela ne conduit pas entièrement au résultat auquel je m'attendais (juste un fichier JAR, pas de script de démarrage, ni rien de ce genre).

Comment puis-je obtenir le même résultat qu'Eclipse obtient avec la boîte de dialogue "Exporter ..."?

122
Hannes

Un fichier JAR exécutable est simplement un fichier JAR contenant une entrée Main-Class dans son manifeste. Il vous suffit donc de configurer la tâche jar pour pouvoir ajouter cette entrée dans son manifeste:

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

Vous pourriez également avoir besoin d'ajouter des entrées de chemin de classe dans le manifeste, mais cela se ferait de la même manière.

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

142
JB Nizet

Les réponses de JB Nizet et Jorge_B sont correctes.

Dans sa forme la plus simple, créer un fichier JAR exécutable avec Gradle consiste simplement à ajouter les entrées appropriées à manifeste . Cependant, il est beaucoup plus courant d'avoir des dépendances à inclure dans le chemin de classe, ce qui rend cette approche difficile en pratique.

Le plugin d'application fournit une autre approche; au lieu de créer un fichier JAR exécutable, il fournit:

  • une tâche run pour faciliter l'exécution de l'application directement à partir de la construction
  • une tâche installDist qui génère une structure de répertoires comprenant le fichier JAR créé, tous les fichiers JAR dont elle dépend et un script de démarrage qui regroupe tous ces éléments dans un programme que vous pouvez exécuter
  • distZip et distTar tâches qui créent des archives contenant une distribution complète de l'application (scripts de démarrage et JAR)

Une troisième approche consiste à créer un "gros fichier JAR", qui est un fichier JAR exécutable qui inclut non seulement le code de votre composant, mais également toutes ses dépendances. Quelques plugins différents utilisent cette approche. J'ai inclus des liens vers quelques-uns que je connais; Je suis sûr qu'il y en a plus.

90
davidmc24

Comme d'autres l'ont noté, pour qu'un fichier jar soit exécutable, le point d'entrée de l'application doit être défini dans l'attribut Main-Class du fichier manifeste. Si les fichiers de classe de dépendance ne sont pas colocalisés, vous devez les définir dans l'entrée Class-Path du fichier manifeste.

J'ai essayé toutes sortes de combinaisons de plug-ins, mais pas uniquement pour la simple tâche de créer un fichier jar exécutable et, d'une certaine manière, d'inclure les dépendances. Tous les plugins semblent manquer d'une manière ou d'une autre, mais finalement je l'ai eu comme je le voulais. Pas de scripts mystérieux, pas un million de mini-fichiers différents polluant le répertoire de construction, un fichier de script de construction assez propre, et surtout: pas un million de fichiers de classe tiers étrangers fusionnés dans mon archive jar.

Ce qui suit est un copier-coller de ici pour votre commodité ..

[How-to] créer un fichier Zip de distribution avec les jars de dépendances dans le sous-répertoire /lib et ajouter toutes les dépendances à l'entrée Class-Path du fichier manifeste:

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
}

Hébergé en tant que Gist ici .

Le résultat peut être trouvé dans build/distributions et le contenu décompressé ressemble à ceci:

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

Contenu de MyJarFile.jar#META-INF/MANIFEST.mf:

Manifest-Version: 1.0
Classe principale: com.somepackage.MainClass
Class-Path: lib/commons-lang3-3.3.2.jar

31
Martin Andersson

La solution la moins onéreuse pour moi était d’utiliser le gradle-shadow-plugin

En plus d'appliquer le plugin, tout ce qui reste à faire est:

Configurez la tâche jar pour que votre classe Main devienne manifeste.

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

Exécuter la tâche de gradle

./gradlew shadowJar

Prenez le app-version-all.jar de build/libs/

Et enfin l'exécuter via:

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

Avez-vous essayé la tâche 'installApp'? Ne crée-t-il pas un répertoire complet avec un ensemble de scripts de démarrage?

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

5
Jorge_B

Merci Konstantin, cela a fonctionné comme un charme avec quelques nuances. Pour une raison quelconque, la spécification de la classe principale dans le fichier manifeste du fichier jar ne fonctionnait pas correctement et souhaitait plutôt l'attribut mainClassName. Voici un extrait de build.gradle qui inclut tout pour que cela fonctionne:

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

Après avoir exécuté gradle shadowJar, vous obtenez myapp- {version} -all.jar dans votre dossier de construction, qui peut être exécuté sous le nom Java -jar myapp- {version} -all.jar.

4
Alex Yavorskiy

Vous pouvez définir un artefact JAR dans les paramètres du module (ou la structure du projet).

  • Cliquez avec le bouton droit de la souris sur le module> Ouvrir les paramètres du module> Artefacts> +> JAR> dans les modules avec dépendances.
  • Définissez la classe principale.

Faire un pot est aussi simple que de cliquer sur "Construire un artefact ..." dans le menu Construire. En prime, vous pouvez regrouper toutes les dépendances dans un seul pot.

Testé sur IntelliJ IDEA 14 Ultimate.

3
Mondain

J'ai vérifié pas mal de liens pour trouver la solution, puis j'ai finalement suivi les étapes mentionnées ci-dessous pour la faire fonctionner. J'utilise Gradle 2.9.

Apportez les modifications suivantes dans votre fichier de construction, fichier de classement:

  1. Mention plugin:

    apply plugin: 'eu.appsatori.fatjar'
    
  2. Fournir le Buildscript:

    buildscript {
    repositories {
        jcenter()
    }
    
    dependencies {
        classpath "eu.appsatori:gradle-fatjar-plugin:0.3"
    }
    }
    
  3. Fournir la classe principale:

    fatJar {
      classifier 'fat'
      manifest {
        attributes 'Main-Class': 'my.project.core.MyMainClass'
      }
      exclude 'META-INF/*.DSA', 'META-INF/*.RSA', 'META-INF/*.SF'
    }
    
  4. Créez le fatjar:

    ./gradlew clean fatjar
    
  5. Exécutez le fatjar à partir de/build/libs /:

    Java -jar MyFatJar.jar
    
2
Sandeep Sarkar