Incorrect dependency path, when using a dynamically set version, and a "fat jar"


(Ben Gruver) #1

Let’s say I have a placeholder base project, with 2 subprojects. In the placeholder project, I have some logic to change the version depending on if the “release” task in in the taskGraph or not

subprojects {

gradle.taskGraph.whenReady {

if (!it.hasTask(release)) {

version = version + ‘-dev’

}

}

}

And then, subproject A has a dependency on subproject B

dependencies {

compile project(’:ProjectB’)

}

So far, all is fine. Everything works as expected.

However, once I try to create a “fat jar” in project A, things go bad:

jar {

from { configurations.compile.collect { it.isDirectory() ? it : zipTree(it) } }

}

This causes a compile error in the compileJava task in project A, due to it not being able to find any of the classes defined in project B.

I used --debug and looked at the classpath that was used for compiling - it is using the “old” version number for the project b jar - ProjectB-1.0.0.jar, rather than the dynamically set version number - ProjectB-1.0.0-dev.jar.

I’m guessing that referencing the configurations from the jar task causes the configurations to be resolved before the dynamic version is set, and so when the configuration is resolved, it is resolved using the old version number, rather than the one that is dynamically set.

I further confirmed this by adding a print statement to the gradle.taskGraph.whenReady closure, and in the closure in the jar task that retrieves the dependencies. The closure in the jar task is in fact running before taskGraph.whenReady is called.

I’m at a bit of a loss as to the best way to resolve this situation.


(Ben Gruver) #2

I was able to find a decent solution:

In project A’s build.gradle, I moved the configuration of the jar task to a taskGraph.whenReady action

gradle.taskGraph.whenReady {

// build a jar containing all dependencies

jar {

from { configurations.compile.collect { it.isDirectory() ? it : zipTree(it) } }

}

}

This seems to work. I’m not sure if this is the best way to resolve the situation though.


(Peter Niederwieser) #3

The problem is probably caused by ‘autowiring’ - the inputs of the ‘jar’ task need to be evaluated when building the task graph to infer further task dependencies. I think your solution is about as good as it gets.

A potential alternative is to check whether ‘release’ is contained in the tasks provided on the command line (‘gradle.startParameter.taskNames’). This can be checked in the configuration phase and hence avoids any timing problems. On the downside it won’t work for cases where you invoke a task that depends on ‘release’.

PS: For a fat Jar you should use ‘configurations.runtime’.