Gradle - немає основного атрибута маніфесту


91

Я якось божеволію від цієї помилки, яку отримую під час запуску файлу JAR, побудованого на Gradle. Помилка читає "немає основного атрибута маніфесту, у RxJavaDemo.jar". Я спробував маніпулювати властивістю "Маніфест", але, думаю, забуваю додати до нього залежності чи щось інше. Що саме я роблю не так?

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

Відповіді:


142

Спробуйте змінити атрибути маніфесту, наприклад:

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

А потім просто перейдіть 'hello.helloWorld'на '<your packagename>.<the name of your Main class>'(де ваш Main-клас має основний метод). У цьому випадку ви вносите у свій маніфест атрибут, який вказує на цей клас, тоді jar працює.


1
Значення @Stanislav 'Main-Class' є основним класом? Що таке привіт і привітСвіт у вашому прикладі?
Даніела Майя

2
@DanielaMaia - це просто повне ім'я кваліфікованого класу, впевнене, що його потрібно писати як hello.HelloWorld, де hello - пакет, де знаходиться клас HelloWorld
Станіслав

9
Мені потрібно було вилучити collect {}частину, щоб вона працювала для мене. Ваш код передбачає, що всі залежності знаходяться в тій же папці, що і ваш основний клас.
AutonomousApps

1

FWIW - Я використав наступне завдання jar, щоб зібрати всі свої залежності компіляції у файл jar, і використав вищезазначену рекомендацію, щоб правильно встановити шлях до класу

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

0

Щоб зробити jarфайл виконуваним (щоб java -jarкоманда працювала), вкажіть Main-Classатрибут у MANIFEST.MF.

У Gradle це можна зробити, налаштувавши jarзавдання.

  • щодо Groovy DSL див. ці відповіді ( [1] , [2] )
  • для Kotlin DSL ви можете використовувати такий фрагмент коду:
tasks.withType<Jar> {
    manifest {
        attributes["Main-Class"] = "com.caco3.Main"
    }
}

Чому mainClassNameне працює, як очікувалося?

Або чому mainClassNameв маніфесті не вказано атрибут?

mainClassNameВластивість приходить з applicationплагіна . Плагін:

дозволяє легко запускати програму локально під час розробки та упаковувати програму як TAR та / або ZIP, включаючи сценарії запуску, специфічні для операційної системи .

Таким чином, applicationплагін не має на меті отримання виконуваних jarсек

Коли mainClassNameвластивість встановлена, тоді:

  1. $ ./gradlew runзапустить mainметод у класі, вказаному в атрибуті
  2. zip/ tarАрхівування побудована з використанням distZip/ distTarзавдань буде містити скрипт, який буде запускати mainметод зазначеного раніше класу.

Ось рядок сценарію оболонки, що встановлює основний клас:

$ grep Main2 gradletest
eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLETEST_OPTS -classpath "\"$CLASSPATH\"" com.caco3.gradletest.Main2 "$APP_ARGS"
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.