Making an executable jar with dependencies


(Kirk) #1

I’ve found some discussion of this on the site, but nothing I’ve seen answers my question.

I want to make a directory, lets say,

MyApplication

Inside this directory I want to put a jar file (the result of my build), and a lib directory with all my project’s runtime dependencies. So it ends up like this:

MyApplication
        MyApplication.jar
        lib
            dependency1.jar
            dependency2.jar

The jar file needs to have a manifest that contains a Class-Path property that includes the jars in the lib directory.

The plugins available for this task have so-far shown themselves to not quite be right. For example, I do not want a shell script, and I do not want the project’s position in the overall project hierarchy to be baked into the resulting structure.

So, the copy tasks are easy enough to make and I can construct the above directory structure by hand.

But I’ve been unable to get the Class-Path string into the jar file. Here’s what I’ve tried:

project.ext.cpString = {
         // Build the string that will go in the manifest's
         //
Class-Path attribute
        String result
        configurations.runtime.resolve().each { f ->
            result = result + " lib/${f.name}"
        }
        result
    }

Then

jar {
        manifest {
            attributes('Main-Class': 'mypackage.MyMainClass')
            attributes('Class-Path': project.ext.cpString )
        }
    }

And many variations. I’ve tried making the string generator a function, I’ve tried defining the property and then setting that property in a task wich jar depends on. Lots of things. The Class-Path attribute in the jar always ends up blank.

I’m sure I’m just missing some detail about the gradle build phases or something. Any help?


(Peter Niederwieser) #2

Your code is never calling the ‘cpString’ closure. You could also turn it into a method. You’d also have to defer the work until you can be sure that the ‘jar’ task is really going to be executed, for example with ‘jar.doFirst { … }’. I recommend to check out the gradle-one-jar plugin.


(Kirk) #3

Thanks Peter,

Reordering things seems to have done the trick. The closure does appear to get called when the property is evaluated in the jar task.