anchor.diff:  == Handling mutually exclusive dependencies
   
   [[sec:capabilities]]
  -=== Component capabilities
  -
  -==== Introduction to capabilities
  +=== Introduction to component capabilities
   
   Often a dependency graph would accidentally contain multiple implementations of the same API.
   This is particularly common with logging frameworks, where multiple bindings are available, and that one library chooses a binding when another transitive dependency chooses another.
  
positive.code: Intuitively, it means that if Gradle finds two components that provide the same thing on classpath, it's going to fail with an error indicating what modules are in conflict.
  In our example, it means that different bindings of a logging framework provide the same capability.
  
  ==== Capability coordinates
  
  A _capability_ is defined by a `(group, module, version)` triplet.
  Each component defines an implicit capability corresponding to its GAV coordinates (group, artifact, version).
  For example, the `org.apache.commons:commons-lang3:3.8` module has an implicit capability with group `org.apache.commons`, name `commons-lang3` and version `3.8`.
  It is important to realize that capabilities are _versioned_.
  
  ==== Solving capability conflicts
  
  By default, Gradle will fail if two components in the dependency graph provide the same capability.
  It is however possible to tell it to choose the component with the highest capability version instead, just like regular version conflict resolution provides.
  This can be useful whenever a component is relocated at different coordinates in a new release.
  For example, the ASM library lived at `asm:asm` coordinates until version `3.3.1`, then changed to `org.ow2.asm:asm` since `4.0`.
  It is illegal to have both ASM <=3.3.1 and 4.0+ on the classpath, because they provide the same feature, it's just that the component has been relocated.
  Because each component has an implicit capability corresponding to its GAV coordinates, we can fix this by having a rule that will declare that the `asm:asm` module provides the `org.ow2.asm:asm` capability:
  
  .Conflict resolution by capability versioning
  ====
  include::sample[dir="userguide/dependencyManagement/managingTransitiveDependencies/declaringCapabilities/groovy",files="build.gradle[tags=fix_asm]"]
  include::sample[dir="userguide/dependencyManagement/managingTransitiveDependencies/declaringCapabilities/kotlin",files="build.gradle.kts[tags=fix_asm]"]
  ====
  
  And then we can say that we will solve the conflict by automatically choosing the component which has the highest capability version:
  
  .Conflict resolution by capability versioning
  ====
  
negative.code: However, tasks to build the replaced dependency will not be executed in order to resolve the depending `Configuration`.
  
  [[sec:conditional_dependency_substitution]]
  ==== Conditionally substituting a dependency
  
  A common use case for dependency substitution is to allow more flexible assembly of sub-projects within a multi-project build.
  This can be useful for developing a local, patched version of an external dependency or for building a subset of the modules within a large multi-project build.
  