Compilation failure in gradle 1.8 due to dependency ordering change

My build fails under gradle 1.8 but exactly the same code and dependency chain pass in 1.7. The build fails on the compileTestJava task and analysing the debug log shows that the same jars are passed to the compiler but in a different order. The release notes say

The order of resolved artifacts and resolved files has changed. This change is transparent to the vast majority of builds.

The particular failure appears to be because junit 4.10 and hamcrest 1.3 both contain the class ‘org.hamcrest.CoreMatchers’ and the order has swapped around in 1.8 so that I am now picking up junit when before I was picking up hamcrest.

I have 2 questions;

  • What strategies do I have to resolve this? Is it just a case of finding and excluding the offending dependency? * How does gradle now decide what order to list these in? How does this differ to 1.7?

Thanks

Hey,

What strategies do I have to resolve this? Is it just a case of finding and excluding the offending dependency?

Pretty much. If compilation depends on the order of jars then something is wrong with the classpath and it would be good to find the root cause.

Another option is to reorder the dependencies declared in your build to get the good dependency before the rogue dependency.

How does gradle now decide what order to list these in? How does this differ to 1.7?

It differs with 1.7 in the order of transitive dependencies. The current order follows the declaration of the dependencies in respective metadata (e.g. pom.xml or ivy.xml). However, we don’t really treat the order of returned dependencies as a public contract. We do, however, want to be backwards compatible and the fact that your build suffers is not very nice. In this case we needed to clean up related code, make it simpler and faster. So we decided that performance improvements and code simplifications are good justifications to make this potentially breaking change. During the rc phase, none of the users reported any issues with the order of classpath.

Hope that helps!

OK thanks for the info. The previous ordering sounds intuitively correct but the new ordering sounds like it will be somewhat brittle. There are 2 obvious cases; bundled jars n levels deep into the dependency tree & when building applications as opposed to jars (when classpath ordering often does really start to matter).

Are there any plans to allow finer grained control over ordering? perhaps as part of the component metadata features?

The previous ordering sounds intuitively correct

The previous ordering didn’t follow any particular rules. It was consistent and it honored the fist level dependency order. Those 2 requirements are still satisfied by the new ordering.

If the classpath order matters then something is already brittle and can start failing when some dependencies are updated.

Are there any plans to allow finer grained control over ordering? perhaps as part of the component metadata features?

Possibly. However, we would need to have some real use cases at hand (e.g. manipulating the classpath order is not really a use case - is an implementation). You already can manipulate the order of classpath in most tasks because the classpath is a FileCollection.

The current order follows the declaration of the dependencies in respective metadata (e.g. pom.xml or ivy.xml)

do you mean it lists them in a depth first manner? if so, I thought (albeit without having examined the dependency tree in detail) that was what the earlier impl was doing.

However, we would need to have some real use cases at hand

yes fair comment, I can’t think of an actual use case off hand that couldn’t reasonably be described as a hack