Kotlin JVM App missing "main manifest attribute"

(Kregap) #1

Hi,
I want to write simple Kotlin JVM CLI app.
After reading documentation of

gradle init

I used the following command:
gradle init --dsl kotlin --package tools.instrumented_tests_runner --test-framework kotlintest --type kotlin-application
I am using Gradle 5.3.1.

Project was generated successfully.
Then I run ./gradlew jar which generated .jar unfortunately trying to run given JAR file output is:
no main manifest attribute, in build/libs/Instrumented Tests Runner.jar
If I understand correctly it is suggesting missing main class reference in manifest, but actually gradle init did add it there.
This is how build.gradle.kts looks like:

 * This file was generated by the Gradle 'init' task.
 *
 * This generated file contains a sample Kotlin application project to get you started.
 */

plugins {
    // Apply the Kotlin JVM plugin to add support for Kotlin on the JVM.
    id("org.jetbrains.kotlin.jvm").version("1.3.21")

    // Apply the application plugin to add support for building a CLI application.
    application
}

repositories {
    // Use jcenter for resolving your dependencies.
    // You can declare any Maven/Ivy/file repository here.
    jcenter()
}

dependencies {
    // Use the Kotlin JDK 8 standard library.
    implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8")

    // Use the Kotlin test library.
    testImplementation("org.jetbrains.kotlin:kotlin-test")

    // Use the Kotlin JUnit integration.
    testImplementation("org.jetbrains.kotlin:kotlin-test-junit")
}

application {
    // Define the main class for the application.
    mainClassName = "tools.instrumented_tests_runner.AppKt"
}

What am I missing?

0 Likes

(Bartłomiej Hołota) #2

Jar file needs manifest configuration, especially to know where is main function. Sometimes is also nice to build-in all dependencies in single jar instead of passing those through class path:

tasks {
  withType<Jar> {
    manifest {
      attributes["Main-Class"] = application.mainClassName
    }
  // here zip stuff found in runtimeClasspath:
  from(configurations.runtimeClasspath.get().map {if (it.isDirectory) it else zipTree(it)})
}

}
To build ‘fat jar’ you can look into plugins like shadowJar.

1 Like

(Kregap) #3

‘fat jar’ info helped a lot. Thanks to this , your snippet and a snippet found for Kotlin DSL I managed to make it work with following code addition:

tasks.withType<Jar>() {
    manifest {
        attributes["Main-Class"] = "tools.instrumented_tests_runner.AppKt"
    }
    configurations["compileClasspath"].forEach { file: File ->
        from(zipTree(file.absoluteFile))
    }
}
0 Likes