Making an executable jar with dependencies

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?

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.

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.