There are a couple of different meanings for ‘conflict' here, so we should clarify which ones we’re talking about. One kind of conflict is when two consumers of a component ask for different version of that component. This may or may not be a problem, depending on the changes between the two requested versions. In the jvm world, this kind of conflict happens all the time and is not a problem maybe 80% of the time. Let’s call this kind of conflict a ‘version mismatch’.
The other kind of conflict is where dependency resolution chooses some component implementation that is incompatible with some consumer, so that the code fails in odd ways at runtime. Let’s call this a ‘dependency conflict'. Some version mismatches lead to a dependency conflict, but not all version mismatches do (or even most). Dependency conflicts can also happen when dependencies are opaque to Gradle. Here are some examples: - using file dependencies - using `gradleApi()` - when a project’s build script inherits stuff from one of its ancestor projects - when the project’s classes conflict with something in the dependency graph - when a thing provides the same classes as some other thing (eg log4j and log4j-over-slf4j). So, there are two problems with switching on `failOnVersionConflict()` as a default. First, it fails on version mismatches rather than dependency conflicts, which means it will fail in perfectly valid cases. Secondly, it considers only (group, module, version) and so misses other sources for dependency conflicts. Plus there’s the backwards compatibility issue. Our plan to solve this problem has several parts: 1. Split the single build script dependency graph into a dependency graph per plugin, thereby making the graphs much smaller and the chance of a conflict much less likely. There will still be the chance of a conflict, if two plugins expose different versions of a thing via their APIs (an argument for not exposing the classes of a plugin to the build script as a default). 2. Fail on dependency conflict by default (but not version mismatch), and add various way for Gradle to infer when there is likely to be a dependency conflict. For example, the meta-data for a component might declare that ‘this component uses semantic versioning’, in which case we can fail when there is a version mismatch that requests different major versions. Or the meta-data for a component might declare that ‘this component works only with some-lib:1.2.3` and so on. Richer meta-data and dependency declarations, basically. 3. Make some of the opaque cases above more transparent. For example, for `gradleApi()` one part of Gradle knows exactly which versions of which components are included, but never passes this information on to the part of Gradle that does conflict resolution. Another example: In the native language plugins, there’s a way to attach meta-data to file dependencies, allowing conflict resolution to happen. The plan is to roll this back into the jvm world. 4. Add some real language-specific conflict detection. The stuff we plan to do for incremental java compilation means that we can do some conflict detection that considers the actual contents of the artefacts, rather than just their (group, name, version). For example, these two jars contain the same classes, so they may conflict, or this method has changed in an incompatible way, so there is a conflict. You could summarise the last 3 points as: assume there is not a conflict but fail if we can infer that there is, and gradually add more cases that we can infer this for. On 24 Dec 2013, at 7:40 am, Xavier Ducrohet <x...@google.com> wrote: > What I'm wondering if this should become a default though. > > Most people won't know what's going on when they apply two plugins with > incompatible dependencies and the lack of diagnostic output doesn't help. I > do realize it might break compatibility for some (many?) people but that > would be easy to fix in the build file anyway and it just seem safer to me. > > > On Mon, Dec 23, 2013 at 12:33 PM, Luke Daley <luke.da...@gradleware.com> > wrote: > You can do this today by: > > buildscript { > configurations.classpath.resolutionStrategy.failOnVersionConflict() > > } > > When is it planned for? > > It's something we are working on, but it's probably going to be at least 2 - > 3 release cycles at best before it would effectively resolve this kind of > problem. > > > On 23 Dec 2013, at 20:23, Xavier Ducrohet wrote: > > That makes sense. I'm glad to hear it's coming. > > When is it planned for? If it's in a while, would it be possible to make > resolution strict for plugin classpath (ie, consider the dependencies to be > exactly the version they declare, and break on all conflict)? this would > make figuring out conflict easier and would still allow for fixing this > through the conflict resolution already in place. > > Xav > > > On Sat, Dec 21, 2013 at 5:33 AM, Luke Daley <luke.da...@gradleware.com>wrote: > > > On 20 Dec 2013, at 18:16, Xavier Ducrohet wrote: > > Hello, > > We have a user who had an issue with two different plugins that depended > on > different versions of ASM. > > Is there a way to see the build script dependency graph (similar to > running > the dependencies task)? > > > Not currently, though this would be something that would be good to add. > It's a little more complex than the proper configurations to visualise, but > we could do something. > > > > Can the dependency conflict resolution apply to the build script > classpath? > > > It does right now. > > > Is there any way to silo each plugin into their own separate classpath? > This seems fragile right now. > > > Not right now, but it's coming. > > A naive approach of simply completely isolating each plugin into its own > class loader doesn't work because then plugins can't collaborate. For > example, my plugin that builds on the Android plugin wouldn't have access > to the model classes from it because they'd be in a separate class loader. > To make this work we essentially have to provide our own dependency based > class loader visibility system like OSGi or ClassWorlds, which we have > started planning. > > Before we get there though there are some things we need to do: > > 1. Allow plugin classpath to be derived at application time (right now the > opposite is the case) > 2. Allow plugins to declare their public types > 3. Allow published plugins to declare their public/private classpaths > > There is more detail in this spec: https://github.com/gradle/ > gradle/blob/master/design-docs/publishing-and-sharing-plugins.md > > --------------------------------------------------------------------- > To unsubscribe from this list, please visit: > > http://xircles.codehaus.org/manage_email > > > > > --------------------------------------------------------------------- > To unsubscribe from this list, please visit: > > http://xircles.codehaus.org/manage_email > > > -- Adam Murdoch Gradle Co-founder http://www.gradle.org VP of Engineering, Gradleware Inc. - Gradle Training, Support, Consulting http://www.gradleware.com