168 votes

Utiliser Gradle pour construire un JAR avec des dépendances

J'ai une construction multiprojets et j'ai mis une tâche pour construire un JAR lourd dans l'un des sous-projets. J'ai créé une tâche similaire à celle de décrits dans ce livre de cuisine .

jar {
  from configurations.compile.collect { it.isDirectory() ? it : zipTree(it) }
  manifest { attributes 'Main-Class': 'com.benmccann.gradle.test.WebServer' }
}

En l'exécutant, on obtient l'erreur suivante :

Cause : Vous ne pouvez pas modifier une qui n'est pas dans la catégorie non résolue !

Je ne suis pas sûr de la signification de cette erreur. Je l'ai également signalé sur le JIRA de Gradle au cas où il s'agirait d'un bogue .

255voto

Ben McCann Points 3755

J'ai posté une solution dans JIRA contre Gradle :

// Include dependent libraries in archive.
mainClassName = "com.company.application.Main"

jar {
  manifest { 
    attributes "Main-Class": "$mainClassName"
  }  

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

Il convient de noter que mainClassName doit apparaître AVANT jar { .

85voto

blootsvoets Points 1077

La réponse de @felix a failli m'y conduire. J'avais deux problèmes :

  1. Avec Gradle 1.5, la balise manifest n'était pas reconnue à l'intérieur de la tâche fatJar, de sorte que l'attribut Main-Class ne pouvait pas être directement défini.
  2. le jar avait des fichiers META-INF externes conflictuels.

La configuration suivante permet de résoudre ce problème

jar {
  manifest {
    attributes(
      'Main-Class': 'my.project.main',
    )
  }
}

task fatJar(type: Jar) {
  manifest.from jar.manifest
  classifier = 'all'
  from {
    configurations.runtimeClasspath.collect { it.isDirectory() ? it : zipTree(it) }
  } {
    exclude "META-INF/*.SF"
    exclude "META-INF/*.DSA"
    exclude "META-INF/*.RSA"
  }
  with jar
}

Pour ajouter ceci à la tâche standard d'assemblage ou de construction, ajoutez :

artifacts {
    archives fatJar
}

Edit : merci à @mjaggard : dans les versions récentes de Gradle, changez configurations.runtime a configurations.runtimeClasspath

66voto

Felix Points 401

Si vous souhaitez que le jar de se comporter normalement et d'avoir une tâche supplémentaire à accomplir. fatJar utiliser ce qui suit :

task fatJar(type: Jar) {
    classifier = 'all'
    from { configurations.compile.collect { it.isDirectory() ? it : zipTree(it) } }
    with jar
}

La partie importante est with jar . Sans cela, les classes de ce projet ne sont pas incluses.

25voto

user1959190 Points 29

Étant donné que l'utilisation de compiler pour lister les dépendances est désormais obsolète et il convient de passer à l'option mise en œuvre la solution pour construire un Jar avec toutes les dépendances devrait utiliser l'exemple de ce site web.

https://docs.gradle.org/current/userguide/working_with_files.html#sec:creating_uber_jar_example

En particulier, cette commande :

configurations.runtimeClasspath.findAll { it.name.endsWith('jar') }.collect { zipTree(it)

Voici la section complète de gradle : [1] : https://docs.gradle.org/current/userguide/working_with_files.html#sec:creating_uber_jar_example

task uberJar(type: Jar) {
archiveClassifier = 'uber'

from sourceSets.main.output

dependsOn configurations.runtimeClasspath
from {
    configurations.runtimeClasspath.findAll { it.name.endsWith('jar') }.collect { zipTree(it) }
}}

10voto

Cela me convient parfaitement.

Ma classe principale :

package com.curso.online.gradle;

import org.apache.commons.lang3.StringUtils;
import org.apache.log4j.Logger;

public class Main {

    public static void main(String[] args) {
        Logger logger = Logger.getLogger(Main.class);
        logger.debug("Starting demo");

        String s = "Some Value";

        if (!StringUtils.isEmpty(s)) {
            System.out.println("Welcome ");
        }

        logger.debug("End of demo");
    }

}

Et c'est le contenu de mon fichier build.gradle :

apply plugin: 'java'

apply plugin: 'eclipse'

repositories {
    mavenCentral()
}

dependencies {
    compile group: 'commons-collections', name: 'commons-collections', version: '3.2'
    testCompile group: 'junit', name: 'junit', version: '4.+'
    compile  'org.apache.commons:commons-lang3:3.0'
    compile  'log4j:log4j:1.2.16'
}

task fatJar(type: Jar) {
    manifest {
        attributes 'Main-Class': 'com.curso.online.gradle.Main'
    }
    baseName = project.name + '-all'
    from { configurations.compile.collect { it.isDirectory() ? it : zipTree(it) } }
    with jar
}

Et j'écris ce qui suit dans ma console :

java -jar ProyectoEclipseTest-all.jar

Et le résultat est excellent :

log4j:WARN No appenders could be found for logger (com.curso.online.gradle.Main)
.
log4j:WARN Please initialize the log4j system properly.
log4j:WARN See http://logging.apache.org/log4j/1.2/faq.html#noconfig for more in
fo.
Welcome

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X