Resolution and Conflicts
What Gradle does when two paths demand different versions: default conflict resolution, forcing and constraints, rewriting rules, substitution, capabilities, and locking. This is the area that separates Gradle users from Gradle debuggers.
on this pageshowhide
explore
- Default Conflict Resolution6 questions
- Forcing and Strict Constraints5 questions
- Resolution Strategy and eachDependency5 questions
- Dependency Substitution5 questions
- Capabilities and Conflicts5 questions
- Dependency Locking5 questions
- Resolution Result and Artifact View5 questions
- Module Replacement5 questions
questions
page 2 of 2What are the directionality and version semantics of a replacedBy rule? Does it pin or introduce the replacement module's version?
basics
~20 sIt is one-directional: old is replaced by new. It never pins or introduces the new module's version — the replacement is only chosen if it is already in the graph, and its version is resolved by Gradle's normal rules.
How does module replacement differ from dependency substitution, and when would you choose one over the other?
basics
~20 sSubstitution unconditionally swaps one selector for another module/project. Module replacement only states that two coordinates are the same logical library, so the old one is evicted during conflict resolution if both appear. Use replacement for renamed libraries, substitution for forced swaps.
How do you wire the artifacts of a configuration into a custom task lazily, and why does laziness matter here?
basics
~10 sUse configuration.incoming.artifactView{...}.artifacts.artifactFiles (a lazy FileCollection) as the task's @InputFiles. Resolution then happens at execution time, not configuration time, keeping builds fast and configuration-cache compatible.
How would you programmatically determine why Gradle selected a particular version of a dependency, using the ResolutionResult API?
basics
~10 sWalk the graph via incoming.resolutionResult.allComponents, find the ResolvedComponentResult for the module, and read its selectionReason — its descriptors explain the cause (conflict resolution, constraint, forced, etc.).
Engineers sometimes read a project extension property at the top of an eachDependency rule and are surprised by the value or by configuration cache warnings. Explain the configuration-time vs resolve-time subtlety and how to capture inputs safely.
basics
~20 sThe eachDependency closure runs at resolve time, but you register it at configuration time. Capturing live project state inside it can read stale values or break the configuration cache. Resolve inputs into a Provider/local val up front instead.
On a large multi-module build you must decide between eachDependency rules and Gradle's more declarative mechanisms for controlling versions. How do you reason about when eachDependency is the right tool versus a smell?
basics
~20 seachDependency is an imperative per-module callback — great for conditional or computed rewrites, but harder to read and reason about at scale. For broad version policy, prefer declarative constraints or a platform; reserve eachDependency for cases needing logic.
How do you substitute a dependency while preserving or targeting a specific variant, classifier, or capability?
basics
~10 sUse the variant-aware substitution DSL: substitute(module(...)).using(project(...)).withClassifier(...) or attach capabilities/attributes via variant { ... }, so the substitute resolves to the correct artifact instead of failing on a missing variant.
Using artifactView's componentFilter, how would you separate project (local) artifacts from external module artifacts, and when is that useful?
basics
~10 sSet componentFilter { id -> id is ProjectComponentIdentifier } to keep only local project artifacts, or ModuleComponentIdentifier for external ones. Useful for fat-jar/relocation logic that should treat your own code differently from third-party libs.
How does `resolutionStrategy.failOnVersionConflict()` interact with `force` and strict constraints, and when would you enable it?
basics
~20 sfailOnVersionConflict() makes Gradle fail whenever two versions of a module are requested, instead of silently picking the highest. force resolves such conflicts and avoids the failure; you enable it to surface every version disagreement and pin them deliberately.
How do you publish a component so that two of its optional features are mutually exclusive via capabilities, and what's the difference between feature variants and a capability conflict?
basics
~20 sWhen publishing, declare a capability on a variant via the Java library's registerFeature or by adding capabilities to outgoing configurations. If you give two alternative implementations the same capability, consumers can pick only one — Gradle enforces mutual exclusivity at resolution.
How would you roll out dependency locking across a large multi-module build, and what scope and policy decisions matter?
basics
~10 sDecide which configurations to lock (often all resolvable ones), generate per-project lockfiles, commit them, and enforce regeneration in CI. Use STRICT mode to forbid unlocked resolution, and define a standard --update-locks workflow for upgrades.
showing 31–41 of 41