Skip to content

Commit 528c238

Browse files
committed
Improve documentation for dependency version declaration
This documents the version syntax (mostly copied from the version constraint javadocs) as well as the new strict version short-hand notation.
1 parent 345393a commit 528c238

File tree

5 files changed

+141
-0
lines changed

5 files changed

+141
-0
lines changed

subprojects/docs/src/docs/userguide/dep-man/02-declaring-dependency-versions/declaring_dependency_versions.adoc

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
[[declaring-dependency-versions]]
22
= Declaring dependency versions
33

4+
include::single_versions.adoc[leveloffset=+1]
5+
46
include::rich_versions.adoc[leveloffset=+1]
57

68
[[sec:declaring_without_version]]

subprojects/docs/src/docs/userguide/dep-man/02-declaring-dependency-versions/rich_versions.adoc

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
Gradle supports a rich model for declaring versions, which allows to combine different level of version information.
55
The terms and their meaning are explained below, from the strongest to the weakest:
66

7+
[[sec:strict-version]]
78
`strictly`::
89
Any version not matched by this version notation will be excluded.
910
This is the strongest version declaration.
@@ -12,13 +13,15 @@ This term supports dynamic versions.
1213
+
1314
When defined, overrides previous `require` declaration and clears previous `reject`.
1415

16+
[[sec:required-version]]
1517
`require`::
1618
Implies that the selected version cannot be lower than what `require` accepts but could be higher through conflict resolution, even if higher has an exclusive higher bound.
1719
This is what a direct version on a dependency translates to.
1820
This term supports dynamic versions.
1921
+
2022
When defined, overrides previous `strictly` declaration and clears previous `reject`.
2123

24+
[[sec:preferred-version]]
2225
`prefer`::
2326
This is a very soft version declaration.
2427
It applies only if there is no stronger non dynamic opinion on a version for the module.
@@ -28,6 +31,7 @@ Definition can complement `strictly` or `require`.
2831

2932
There is also an additional term outside of the level hierarchy:
3033

34+
[[sec:rejected-version]]
3135
`reject`::
3236
Declares that specific version(s) are not accepted for the module.
3337
This will cause dependency resolution to fail if the only versions selectable are also rejected.
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
[[single-version-declarations]]
2+
= Single version declarations
3+
4+
The simplest version declaration is a _simple string_ representing the version to use.
5+
Gradle supports different ways of declaring a version string:
6+
7+
* An exact version: e.g. `1.3`, `1.3.0-beta3`, `1.0-20150201.131010-1`
8+
* A Maven-style version range: e.g. `[1.0,)`, `[1.1, 2.0)`, `(1.2, 1.5]`
9+
** The `[` and `]` symbols indicate an inclusive bound; `(` and `)` indicate an exclusive bound.
10+
** When the upper or lower bound is missing, the range has no upper or lower bound.
11+
** The symbol `]` can be used instead of `(` for an exclusive lower bound, and `[` instead of `)` for exclusive upper bound. e.g `]1.0, 2.0[`
12+
* A _prefix_ version range: e.g. `1.+`, `1.3.+`
13+
** Only versions exactly matching the portion before the `+` are included.
14+
** The range `+` on it's own will include any version.
15+
* A `latest-status` version: e.g. `latest.integration`, `latest.release`
16+
** Will match the highest versioned module with the specified status. See link:{javadocPath}/org/gradle/api/artifacts/ComponentMetadata.html#getStatus--[ComponentMetadata.getStatus()].
17+
* A Maven `SNAPSHOT` version identifier: e.g. `1.0-SNAPSHOT`, `1.4.9-beta1-SNAPSHOT`
18+
19+
== Version ordering
20+
21+
Versions have an implicit ordering. Version ordering is used to:
22+
* Determine if a particular version is included in a range.
23+
* Determine which version is 'newest' when performing conflict resolution.
24+
25+
Versions are ordered based on the following rules:
26+
27+
* Each version is split into it's constituent "parts":
28+
** The characters `[. - _ +]` are used to separate the different "parts" of a version.
29+
** Any part that contains both digits and letters is split into separate parts for each: `1a1 == 1.a.1`
30+
** Only the parts of a version are compared. The actual separator characters are not significant: `1.a.1 == 1-a+1 == 1.a-1 == 1a1`
31+
* The equivalent parts of 2 versions are compared using the following rules:
32+
** If both parts are numeric, the highest numeric value is **higher**: `1.1` < `1.2`
33+
** If one part is numeric, it is considered **higher** than the non-numeric part: `1.a` < `1.1`
34+
** If both are not numeric, the parts are compared **alphabetically, case-sensitive**: `1.a` < `1.A` < `1.b` < `1.B`
35+
** A version with an extra numeric part is considered **higher** than a version without: `1.1` < `1.1.0`
36+
** A version with an extra non-numeric part is considered **lower** than a version without: `1.1` < `1.1.a`
37+
* Certain string values have special meaning for the purposes of ordering:
38+
** The string `dev` is consider **lower** than any other string part: `1.0-dev` < `1.0-alpha` < `1.0-rc`.
39+
** The strings `rc`, `release` and `final` are considered **higher** than any other string part (sorted in that order): `1.0-zeta` < `1.0-rc` < `1.0-release` < `1.0-final` < `1.0`.
40+
** The string `SNAPSHOT` has **no special meaning**, and is sorted alphabetically like any other string part: `1.0-alpha` < `1.0-SNAPSHOT` < `1.0-zeta` < `1.0-rc` < `1.0`.
41+
** Numeric snapshot versions have **no special meaning**, and are sorted like any other numeric part: `1.0` < `1.0-20150201.121010-123` < `1.1`.
42+
43+
== Simple version declaration semantics
44+
45+
When you declare a version using the short-hand notation, for example:
46+
47+
.A simple declaration
48+
====
49+
include::sample[dir="userguide/dependencyManagement/declaringDependencies/concreteVersion/groovy",files="build.gradle[tags=required-version]"]
50+
include::sample[dir="userguide/dependencyManagement/declaringDependencies/concreteVersion/kotlin",files="build.gradle.kts[tags=required-version]"]
51+
====
52+
53+
Then the version is considered a <<rich_versions.adoc#sec:required-version,required version>> which means that it should _minimally_ be `1.7.15` but can be upgraded by the engine (optimistic upgrade).
54+
55+
There is, however, a shorthand notation for <<rich_versions.adoc#sec:strict-version,strict versions>>, using the `!!` notation:
56+
57+
.Shorthand notation for strict dependencies
58+
====
59+
include::sample[dir="userguide/dependencyManagement/declaringDependencies/concreteVersion/groovy",files="build.gradle[tags=strict-shorthand]"]
60+
include::sample[dir="userguide/dependencyManagement/declaringDependencies/concreteVersion/kotlin",files="build.gradle.kts[tags=strict-shorthand]"]
61+
====
62+
63+
A strict version _cannot be upgraded_ and overrides whatever transitive dependencies originating from this dependency provide.
64+
It is recommended to use ranges for strict versions.
65+
66+
The notation `[1.7, 1.8[!!1.7.25` above is equivalent to:
67+
68+
* strictly `[1.7, 1.8[`
69+
* prefer `1.7.25`
70+
71+
which means that the engine **must** select a version between 1.7 (included) and 1.8 (excluded), and that if no other component in the graph needs a different version, it should _prefer_ `1.7.25`.
72+
73+
The section below explains the semantics of rich version constraints in details.

subprojects/docs/src/samples/userguide/dependencyManagement/declaringDependencies/concreteVersion/groovy/build.gradle

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,37 @@ dependencies {
3232
}
3333
// end::rich-version[]
3434

35+
/*
36+
// tag::required-version[]
37+
dependencies {
38+
implementation('org.slf4j:slf4j-api:1.7.15')
39+
}
40+
// end::required-version[]
41+
42+
// tag::strict-shorthand[]
43+
dependencies {
44+
// short-hand notation with !!
45+
implementation('org.slf4j:slf4j-api:1.7.15!!')
46+
// is equivalent to
47+
implementation("org.slf4j:slf4j-api") {
48+
version {
49+
strictly '1.7.15'
50+
}
51+
}
52+
53+
// or...
54+
implementation('org.slf4j:slf4j-api:[1.7, 1.8[!!1.7.25')
55+
// is equivalent to
56+
implementation('org.slf4j:slf4j-api') {
57+
version {
58+
strictly '[1.7, 1.8['
59+
prefer '1.7.25'
60+
}
61+
}
62+
}
63+
// end::strict-shorthand[]
64+
*/
65+
3566
task copyLibs(type: Copy) {
3667
from configurations.compileClasspath
3768
into "$buildDir/libs"

subprojects/docs/src/samples/userguide/dependencyManagement/declaringDependencies/concreteVersion/kotlin/build.gradle.kts

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,3 +36,34 @@ tasks.register<Copy>("copyLibs") {
3636
from(configurations.compileClasspath)
3737
into("$buildDir/libs")
3838
}
39+
40+
/*
41+
// tag::required-version[]
42+
dependencies {
43+
implementation("org.slf4j:slf4j-api:1.7.15")
44+
}
45+
// end::required-version[]
46+
47+
// tag::strict-shorthand[]
48+
dependencies {
49+
// short-hand notation with !!
50+
implementation("org.slf4j:slf4j-api:1.7.15!!")
51+
// is equivalent to
52+
implementation("org.slf4j:slf4j-api") {
53+
version {
54+
strictly("1.7.15")
55+
}
56+
}
57+
58+
// or...
59+
implementation("org.slf4j:slf4j-api:[1.7, 1.8[!!1.7.25")
60+
// is equivalent to
61+
implementation("org.slf4j:slf4j-api") {
62+
version {
63+
strictly([1.7, 1.8[")
64+
prefer("1.7.25")
65+
}
66+
}
67+
}
68+
// end::strict-shorthand[]
69+
*/

0 commit comments

Comments
 (0)