I can't for the life of me get an executable JAR f...
# announcements
k
I can't for the life of me get an executable JAR for my kotlin project. I have tried adding an artifact to my project and specifying Main-Class in MANIFEST.MF, but still I get "no main manifest attribute" when running
java -jar
l
Do you use Gradle? I usually just add the
Shadow
plugin and let it do the rest xD
k
yes
I can look into that
l
It embeds all the libraries in a big jar for you to execute
k
yeah i've got that much working, so I can at least java -cp my.jar Main
but I can't java -jar my.jar
b
Here's how I've done it https://gitlab.com/mp.bootstrappers/kotlin-fullstack-mpp/blob/master/build.gradle.kts It might be a bit outdated by now
or this:
Copy code
getByName("jar", Jar::class) {
      dependsOn("frontendJar", "backendJar")
      group = "package"
      manifest {
        attributes(
            mapOf(
                "Implementation-Title" to rootProject.name,
                "Implementation-Group" to rootProject.group,
                "Implementation-Version" to rootProject.version,
                "Timestamp" to System.currentTimeMillis(),
                "Main-Class" to mainClassName
            )
        )
      }
      val dependencies = configurations["backendRuntimeClasspath"].filter { it.name.endsWith(".jar") } +
          project.tasks["backendJar"].outputs.files +
          project.tasks["frontendJar"].outputs.files
      dependencies.forEach {
        if (it.isDirectory) from(it) else from(zipTree(it))
      }
      exclude("META-INF/*.RSA", "META-INF/*.SF", "META-INF/*.DSA")
      inputs.files(dependencies)
      outputs.file(archiveFile)
    }
k
shadow seems to be what I am looking for, however it appears to use the configuration from the java plugin, and
java
is kind of ambiguous in the gradle script
specifically it returns a type of JavaPluginExtension, which is very different than the plugin type itself
Copy code
public interface JavaPluginExtension {
    /**
     * Returns the source compatibility used for compiling Java sources.
     */
    JavaVersion getSourceCompatibility();

    /**
     * Sets the source compatibility used for compiling Java sources.
     *
     * @param value The value for the source compatibility
     */
    void setSourceCompatibility(JavaVersion value);

    /**
     * Returns the target compatibility used for compiling Java sources.
     */
    JavaVersion getTargetCompatibility();

    /**
     * Sets the target compatibility used for compiling Java sources.
     *
     * @param value The value for the target compatibility
     */
    void setTargetCompatibility(JavaVersion value);
}
no manifest function
b
I was facing the same issues myself with it, thus in the end I've decided to just do it manually
It's quite easy too
Dont forget to add Kt to your main class btw
As in com.package.MainKt
k
i've tried every permutation of adding main
b
Also, if you could post a snippet of your error i could assist better
I think i had some issues with manifest in the past too
k
i see that the gradle block is actually supposed to be
jar
, not
java
, but that doesn't work either
b
Are you able to post your gradle config for inspection? The one where you tried manual approach
k
well, the jar creation is outside of the gradle file. it's an IDEA feature.
b
Umm, why don't you just do that in gradle? Seems much easier
k
because i need to create a fat jar... and it would have taken me a week to figure that out 😛
i am going to give this shadow a try, i see how I can configure it
b
If you can post your gradlefile i can write up a fatJar gradle task for you
k
i appreciate that, but I would much prefer to leverage a plugin than maintain that myself
b
No worries. It all comes down to preferences in the end
🍻 1
k
shadow works 😃
🎉 1
j
-cp./target/lib/* with maven deps plugin (not sure how to do same with gradle) makes a simple painless footprint with no uberjar manifest collisions