coming from maven world you are actually able to control classpath order as of version 2.0.9 maven uses pom order for classpath so you can manipulate it freely and it has proven very useful in the past for us.
From what I read (and I may be wrong) Gradle doesn’t give any guarantees about the classpath ordering.
Can someone point me to the right direction how to implement similar behavior as Maven provides? Meaning preserves the ordering inside dependencies block. Even if it means writing a plugin or whatever.
You are kind of right. Dependency ordering is preserved, but for example all compile dependencies will be before testCompile dependencies no matter of how you order them.
Depending on the nature of your conflict you could also exclude the dependency from ‘testCompile’ rather than force the correct one higher on the classpath.
I have noticed that if you add the dependency programmatically, i.e. project.dependencies.add(‘compile’, ‘my.group:my-artifact’) order is not preserved.
Not only that but although it evaluates to the same thing across invocations, it’s not the same on different machines. Do you have any ideas / recommendations how to deal with this apart from sorting the compileClasspath and setting it explicitly on each compile task?
The reason i have to do the programmatic dependency addition is that i am migrating a very old build that uses maven2 + ant still and in order to keep exactly the same resolution rules while migration is in progress i still read dependencies from pom (via ant-maven plugin) and set them to gradle not as files but gradle managed ones to be able to pull sources etc.
This doesn’t seem to be true? If there’s any relationship between their order in the build file and their order in the classpath, I can’t work out what it is.
That is difficult if you are using third-party commercial libraries which contain older implementations of (say) commons-lang classes. It’s awkward, but it happens.
I wish to find some evidence of this in the API, but I can’t find anything. Traversing the dependency tree is done using sets, not lists. For example, we start with:
task printDeps {
doLast {
for (def rd in configurations.toArray()) { // toArray() looks promising
println(rd)
if (!rd.isCanBeResolved()) continue
def rc = rd.getResolvedConfiguration() // This returns a ResolvedConfiguration
printResolvedConfiguration(rc)
}
}
}
From ResolvedConfiguration, it’s only sets, not lists. The rest of the code for the example is in this gist. It’s sets all the way down. I understand that order should not matter, but I am working in an environment where controlling the order is a requirement.
It’s probably an ordered set then.
But there is no interface for ordered set.
I’m also pretty sure order within the dependencies block is preserved.
And while in an optimal world order shouldn’t be important, it in reality is.
And I think Gradle also is aware of that and thus does not use lib/* for example for the classpath in the generated start scripts, but instead lists all the dependencies in order.