Gradle - pas d'attribut manifeste principal

92

Je deviens fou avec cette erreur que j'obtiens lors de l'exécution d'un fichier JAR construit à partir de Gradle. L'erreur lit "pas d'attribut manifeste principal, dans RxJavaDemo.jar" J'ai essayé de manipuler la propriété Manifest mais je pense que j'oublie d'y ajouter les dépendances ou quelque chose. Qu'est-ce que je fais exactement de mal?

apply plugin: 'java'
apply plugin: 'application'

mainClassName = 'demo.MainDashboard'

dependencies {
    compile files ("H:/Processes/Development/libraries/hikari-cp/HikariCP-2.4.1.jar")
    compile files ("H:/Processes/Development/libraries/controls-fx/controlsfx.jar")
    compile files ("H:/Processes/Development/libraries/database_connections/sqlite-jdbc-3.8.6.jar")
    compile files ("H:/Processes/Development/libraries/guava/guava-18.0.jar")
    compile files ("H:/Processes/Development/libraries/rxjava/rxjava-1.0.12.jar")
    compile files ("H:/Processes/Development/libraries/rxjava-extras/rxjava-extras-0.5.15.jar")
    compile files ("H:/Processes/Development/libraries/rxjavafx/RxJavaFX-1.0.0-RC1-SNAPSHOT.jar")
    compile files ("H:/Processes/Development/libraries/rxjavaguava/rxjava-guava-1.0.3.jar")
    compile files ("H:/Processes/Development/libraries/rxjava-jdbc/rxjava-jdbc-0.6.3.jar")
    compile files ("H:/Processes/Development/libraries/slf4j/slf4j-api-1.7.12.jar")
    compile files ("H:/Processes/Development/libraries/tom-commons/tom-commons.jar")
}

sourceSets {
    main.java.srcDir "src/main/java"
    main.resources.srcDir "src/main/resources"
}

jar { 
    manifest {
    attributes(
        "Class-Path": configurations.compile.collect { it.getName() }.join(' '))
    }
    from configurations.compile.collect { entry -> zipTree(entry) }
}
tmn
la source

Réponses:

143

Essayez de modifier vos attributs manifestes comme:

jar {
  manifest {
    attributes(
      'Class-Path': configurations.compile.collect { it.getName() }.join(' '),
      'Main-Class': 'hello.HelloWorld'
    )
  }
}

Et puis changez simplement 'hello.helloWorld'en '<your packagename>.<the name of your Main class>'(où votre classe Main a une méthode principale). Dans ce cas, vous créez dans votre manifeste un attribut, qui pointe vers cette classe, puis un fichier jar est en cours d'exécution.

Stanislav
la source
1
La valeur de @Stanislav 'Main-Class' est la classe principale? Que signifient hello et helloWorld dans votre exemple?
Daniela Maia
2
@DanielaMaia c'est juste un nom de classe qualifié complet, bien sûr qu'il doit être écrit comme bonjour.HelloWorld, où bonjour est le package où se trouve la classe HelloWorld
Stanislav
9
J'avais besoin de retirer la collect {}partie pour qu'elle fonctionne pour moi. Votre code suppose que toutes les dépendances se trouvent dans le même dossier que votre classe principale.
AutonomousApps
1

FWIW - J'ai utilisé la tâche jar suivante pour assembler toutes mes dépendances de compilation dans le fichier jar, et utilisé la recommandation ci-dessus pour obtenir le chemin de classe correctement défini

apply plugin: 'java-library'

jar {
  manifest {
    attributes(
      'Class-Path': configurations.compile.collect { it.getName() }.join(' '),
      'Main-Class': 'your.main.class.goes.here'
    )
  }

  // You can reference any part of the dependency configurations,
  // and you can have as many from statements as you need
  from configurations.compile  
  // I just copied them into the top of the jar, so it looks like the eclipse exported 
  // runnable jar, but you could designate a lib directory, and reference that in the 
  // classpath as "lib/$it.name" instead of it.getName()
  into ''   
}
Eric Hallander
la source
0

Pour rendre le jarfichier exécutable (afin que la java -jarcommande fonctionne), spécifiez l' Main-Classattribut dans MANIFEST.MF.

Dans Gradle, vous pouvez le faire en configurant la jartâche.

  • pour Groovy DSL voir ces réponses ( [1] , [2] )
  • pour Kotlin DSL, vous pouvez utiliser l'extrait de code suivant:
tasks.withType<Jar> {
    manifest {
        attributes["Main-Class"] = "com.caco3.Main"
    }
}

Pourquoi mainClassNamene fonctionne pas comme prévu?

Ou pourquoi mainClassNamene spécifie pas l'attribut dans le manifeste?

La mainClassNamepropriété provient du applicationplugin . Le plugin:

facilite le démarrage de l'application localement pendant le développement et le package de l'application sous forme de TAR et / ou ZIP, y compris les scripts de démarrage spécifiques au système d'exploitation .

Ainsi , le applicationplug - in ne vise pas à produire des exécutables jars

Lorsqu'une mainClassNamepropriété est définie, alors:

  1. $ ./gradlew runlancera la mainméthode dans la classe spécifiée dans l'attribut
  2. l' archive zip/ tarconstruite à l'aide de distZip/ distTartasks contiendra un script, qui lancera la mainméthode de la classe précédemment spécifiée.

Voici la ligne de script shell définissant la classe principale:

$ grep Main2 gradletest
eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLETEST_OPTS -classpath "\"$CLASSPATH\"" com.caco3.gradletest.Main2 "$APP_ARGS"
Denis Zavedeev
la source