Gradle - brak głównego atrybutu manifestu

91

W pewnym sensie wariuję z powodu tego błędu, który otrzymuję podczas uruchamiania pliku JAR zbudowanego na Gradle. Błąd brzmi „brak głównego atrybutu manifestu w RxJavaDemo.jar”. Próbowałem manipulować właściwością Manifest, ale myślę, że zapomniałem dodać zależności lub coś do tego. Co właściwie robię źle?

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
źródło

Odpowiedzi:

142

Spróbuj zmienić swoje atrybuty manifestu, takie jak:

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

A potem po prostu zmień 'hello.helloWorld'na '<your packagename>.<the name of your Main class>'(gdzie Twoja klasa Main ma metodę główną). W tym przypadku należy wprowadzić w swoim manifeście atrybut wskazujący na tę klasę, a następnie działa jar.

Stanislav
źródło
1
Wartość @Stanislav 'Main-Class' jest klasą główną? Jakie są hello i helloWorld w twoim przykładzie?
Daniela Maia
2
@DanielaMaia to tylko pełna kwalifikowana nazwa klasy, na pewno musi być napisana jako hello.HelloWorld, gdzie hello to pakiet, w którym znajduje się klasa HelloWorld
Stanislav
9
Musiałem usunąć tę collect {}porcję, aby działała dla mnie. Twój kod zakłada, że ​​wszystkie zależności znajdują się w tym samym folderze co główna klasa.
AutonomousApps
1

FWIW - Użyłem następującego zadania jar, aby złożyć wszystkie moje zależności kompilacji w pliku jar i zastosowałem powyższe zalecenie, aby uzyskać prawidłowo ustawioną ścieżkę klasy

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
źródło
0

Aby jarplik był wykonywalny (aby java -jarpolecenie działało), określ Main-Classatrybut w MANIFEST.MF.

W Gradle możesz to zrobić, konfigurując jarzadanie.

  • dla Groovy DSL zobacz te odpowiedzi ( [1] , [2] )
  • dla Kotlin DSL możesz użyć następującego fragmentu kodu:
tasks.withType<Jar> {
    manifest {
        attributes["Main-Class"] = "com.caco3.Main"
    }
}

Dlaczego mainClassNamenie działa zgodnie z oczekiwaniami?

Albo dlaczego mainClassNamenie określa atrybutu w manifeście?

mainClassNameNieruchomość pochodzi z applicationwtyczki . Wtyczka:

ułatwia lokalne uruchamianie aplikacji podczas programowania oraz pakowanie aplikacji jako TAR i / lub ZIP, w tym skrypty startowe specyficzne dla systemu operacyjnego .

Więc applicationplugin nie ma na celu produkcję wykonywalne jars

Gdy mainClassNamewłaściwość jest ustawiona, wówczas:

  1. $ ./gradlew runuruchomi mainmetodę w klasie określonej w atrybucie
  2. zip/ tararchiwizować zbudowany z wykorzystaniem distZip/ distTarzadań będzie zawierać skrypt, który będzie uruchamiał mainsposobu podanego poprzednio klasie.

Oto linia skryptu powłoki ustawiającego główną klasę:

$ grep Main2 gradletest
eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLETEST_OPTS -classpath "\"$CLASSPATH\"" com.caco3.gradletest.Main2 "$APP_ARGS"
Denis Zavedeev
źródło