]> git.proxmox.com Git - cargo.git/blob - src/doc/src/reference/resolver.md
Stabilize 2021 edition
[cargo.git] / src / doc / src / reference / resolver.md
1 # Dependency Resolution
2
3 One of Cargo's primary tasks is to determine the versions of dependencies to
4 use based on the version requirements specified in each package. This process
5 is called "dependency resolution" and is performed by the "resolver". The
6 result of the resolution is stored in the `Cargo.lock` file which "locks" the
7 dependencies to specific versions, and keeps them fixed over time.
8
9 The resolver attempts to unify common dependencies while considering possibly
10 conflicting requirements. The sections below provide some details on how these
11 constraints are handled, and how to work with the resolver.
12
13 See the chapter [Specifying Dependencies] for more details about how
14 dependency requirements are specified.
15
16 The [`cargo tree`] command can be used to visualize the result of the
17 resolver.
18
19 [Specifying Dependencies]: specifying-dependencies.md
20 [`cargo tree`]: ../commands/cargo-tree.md
21
22 ## SemVer compatibility
23
24 Cargo uses [SemVer] for specifying version numbers. This establishes a common
25 convention for what is compatible between different versions of a package. See
26 the [SemVer Compatibility] chapter for guidance on what is considered a
27 "compatible" change. This notion of "compatibility" is important because Cargo
28 assumes it should be safe to update a dependency within a compatibility range
29 without breaking the build.
30
31 Versions are considered compatible if their left-most non-zero
32 major/minor/patch component is the same. For example, `1.0.3` and `1.1.0` are
33 considered compatible, and thus it should be safe to update from the older
34 release to the newer one. However, an update from `1.1.0` to `2.0.0` would not
35 be allowed to be made automatically. This convention also applies to versions
36 with leading zeros. For example, `0.1.0` and `0.1.2` are compatible, but
37 `0.1.0` and `0.2.0` are not. Similarly, `0.0.1` and `0.0.2` are not
38 compatible.
39
40 As a quick refresher, the *version requirement* syntax Cargo uses for
41 dependencies is:
42
43 Requirement | Example | Equivalence | Description
44 --|--------|--|-------------
45 Caret | `1.2.3` or `^1.2.3` | <code>>=1.2.3,&nbsp;<2.0.0</code> | Any SemVer-compatible version of at least the given value.
46 Tilde | `~1.2` | <code>>=1.2.0,&nbsp;<1.3.0</code> | Minimum version, with restricted compatibility range.
47 Wildcard | `1.*` | <code>>=1.0.0,&nbsp;<2.0.0</code> | Any version in the `*` position.
48 Equals | `=1.2.3` | <code>=1.2.3</code> | Exactly the specified version only.
49 Comparison | `>1.1` | <code>>=1.2.0</code> | Naive numeric comparison of specified digits.
50 Compound | <code>>=1.2,&nbsp;<1.5</code> | <code>>1.2.0,&nbsp;<1.5.0</code> | Multiple requirements that must be simultaneously satisfied.
51
52 When multiple packages specify a dependency for a common package, the resolver
53 attempts to ensure that they use the same version of that common package, as
54 long as they are within a SemVer compatibility range. It also attempts to use
55 the greatest version currently available within that compatibility range. For
56 example, if there are two packages in the resolve graph with the following
57 requirements:
58
59 ```toml
60 # Package A
61 [dependencies]
62 bitflags = "1.0"
63
64 # Package B
65 [dependencies]
66 bitflags = "1.1"
67 ```
68
69 If at the time the `Cargo.lock` file is generated, the greatest version of
70 `bitflags` is `1.2.1`, then both packages will use `1.2.1` because it is the
71 greatest within the compatibility range. If `2.0.0` is published, it will
72 still use `1.2.1` because `2.0.0` is considered incompatible.
73
74 If multiple packages have a common dependency with semver-incompatible
75 versions, then Cargo will allow this, but will build two separate copies of
76 the dependency. For example:
77
78 ```toml
79 # Package A
80 [dependencies]
81 rand = "0.7"
82
83 # Package B
84 [dependencies]
85 rand = "0.6"
86 ```
87
88 The above will result in Package A using the greatest `0.7` release (`0.7.3`
89 at the time of this writing) and Package B will use the greatest `0.6` release
90 (`0.6.5` for example). This can lead to potential problems, see the
91 [Version-incompatibility hazards] section for more details.
92
93 Multiple versions within the same compatibility range are not allowed and will
94 result in a resolver error if it is constrained to two different versions
95 within a compatibility range. For example, if there are two packages in the
96 resolve graph with the following requirements:
97
98 ```toml
99 # Package A
100 [dependencies]
101 log = "=0.4.11"
102
103 # Package B
104 [dependencies]
105 log = "=0.4.8"
106 ```
107
108 The above will fail because it is not allowed to have two separate copies of
109 the `0.4` release of the `log` package.
110
111 [SemVer]: https://semver.org/
112 [SemVer Compatibility]: semver.md
113 [Version-incompatibility hazards]: #version-incompatibility-hazards
114
115 ### Version-incompatibility hazards
116
117 When multiple versions of a crate appear in the resolve graph, this can cause
118 problems when types from those crates are exposed by the crates using them.
119 This is because the types and items are considered different by the Rust
120 compiler, even if they have the same name. Libraries should take care when
121 publishing a SemVer-incompatible version (for example, publishing `2.0.0`
122 after `1.0.0` has been in use), particularly for libraries that are widely
123 used.
124
125 The "[semver trick]" is a workaround for this problem of publishing a breaking
126 change while retaining compatibility with older versions. The linked page goes
127 into detail about what the problem is and how to address it. In short, when a
128 library wants to publish a SemVer-breaking release, publish the new release,
129 and also publish a point release of the previous version that reexports the
130 types from the newer version.
131
132 These incompatibilities usually manifest as a compile-time error, but
133 sometimes they will only appear as a runtime misbehavior. For example, let's
134 say there is a common library named `foo` that ends up appearing with both
135 version `1.0.0` and `2.0.0` in the resolve graph. If [`downcast_ref`] is used
136 on a object created by a library using version `1.0.0`, and the code calling
137 `downcast_ref` is downcasting to a type from version `2.0.0`, the downcast
138 will fail at runtime.
139
140 It is important to make sure that if you have multiple versions of a library
141 that you are properly using them, especially if it is ever possible for the
142 types from different versions to be used together. The [`cargo tree
143 -d`][`cargo tree`] command can be used to identify duplicate versions and
144 where they come from. Similarly, it is important to consider the impact on the
145 ecosystem if you publish a SemVer-incompatible version of a popular library.
146
147 [semver trick]: https://github.com/dtolnay/semver-trick
148 [`downcast_ref`]: ../../std/any/trait.Any.html#method.downcast_ref
149
150 ### Pre-releases
151
152 SemVer has the concept of "pre-releases" with a dash in the version, such as
153 `1.0.0-alpha`, or `1.0.0-beta`. Cargo will avoid automatically using
154 pre-releases unless explicitly asked. For example, if `1.0.0-alpha` of package
155 `foo` is published, then a requirement of `foo = "1.0"` will *not* match, and
156 will return an error. The pre-release must be specified, such as `foo =
157 "1.0.0-alpha"`. Similarly [`cargo install`] will avoid pre-releases unless
158 explicitly asked to install one.
159
160 Cargo allows "newer" pre-releases to be used automatically. For example, if
161 `1.0.0-beta` is published, then a requirement `foo = "1.0.0-alpha"` will allow
162 updating to the `beta` version. Beware that pre-release versions can be
163 unstable, and as such care should be taken when using them. Some projects may
164 choose to publish breaking changes between pre-release versions. It is
165 recommended to not use pre-release dependencies in a library if your library
166 is not also a pre-release. Care should also be taken when updating your
167 `Cargo.lock`, and be prepared if a pre-release update causes issues.
168
169 The pre-release tag may be separated with periods to distinguish separate
170 components. Numeric components will use numeric comparison. For example,
171 `1.0.0-alpha.4` will use numeric comparison for the `4` component. That means
172 that if `1.0.0-alpha.11` is published, that will be chosen as the greatest
173 release. Non-numeric components are compared lexicographically.
174
175 [`cargo install`]: ../commands/cargo-install.md
176
177 ### Version metadata
178
179 SemVer has the concept of "version metadata" with a plus in the version, such
180 as `1.0.0+21AF26D3`. This metadata is usually ignored, and should not be used
181 in a version requirement. You should never publish multiple versions that
182 differ only in the metadata tag (note, this is a [known issue] with
183 [crates.io] that currently permits this).
184
185 [known issue]: https://github.com/rust-lang/crates.io/issues/1059
186 [crates.io]: https://crates.io/
187
188 ## Other constraints
189
190 Version requirements aren't the only constraint that the resolver considers
191 when selecting and unifying dependencies. The following sections cover some of
192 the other constraints that can affect resolution.
193
194 ### Features
195
196 For the purpose of generating `Cargo.lock`, the resolver builds the dependency
197 graph as-if all [features] of all [workspace] members are enabled. This
198 ensures that any optional dependencies are available and properly resolved
199 with the rest of the graph when features are added or removed with the
200 [`--features` command-line flag](features.md#command-line-feature-options).
201 The resolver runs a second time to determine the actual features used when
202 *compiling* a crate, based on the features selected on the command-line.
203
204 Dependencies are resolved with the union of all features enabled on them. For
205 example, if one package depends on the [`im`] package with the [`serde`
206 dependency] enabled and another package depends on it with the [`rayon`
207 dependency] enabled, then `im` will be built with both features enabled, and
208 the `serde` and `rayon` crates will be included in the resolve graph. If no
209 packages depend on `im` with those features, then those optional dependencies
210 will be ignored, and they will not affect resolution.
211
212 When building multiple packages in a workspace (such as with `--workspace` or
213 multiple `-p` flags), the features of the dependencies of all of those
214 packages are unified. If you have a circumstance where you want to avoid that
215 unification for different workspace members, you will need to build them via
216 separate `cargo` invocations.
217
218 The resolver will skip over versions of packages that are missing required
219 features. For example, if a package depends on version `^1` of [`regex`] with
220 the [`perf` feature], then the oldest version it can select is `1.3.0`,
221 because versions prior to that did not contain the `perf` feature. Similarly,
222 if a feature is removed from a new release, then packages that require that
223 feature will be stuck on the older releases that contain that feature. It is
224 discouraged to remove features in a SemVer-compatible release. Beware that
225 optional dependencies also define an implicit feature, so removing an optional
226 dependency or making it non-optional can cause problems, see [removing an
227 optional dependency].
228
229 [`im`]: https://crates.io/crates/im
230 [`perf` feature]: https://github.com/rust-lang/regex/blob/1.3.0/Cargo.toml#L56
231 [`rayon` dependency]: https://github.com/bodil/im-rs/blob/v15.0.0/Cargo.toml#L47
232 [`regex`]: https://crates.io/crates/regex
233 [`serde` dependency]: https://github.com/bodil/im-rs/blob/v15.0.0/Cargo.toml#L46
234 [features]: features.md
235 [removing an optional dependency]: semver.md#cargo-remove-opt-dep
236 [workspace]: workspaces.md
237
238 #### Feature resolver version 2
239
240 When `resolver = "2"` is specified in `Cargo.toml` (see [resolver
241 versions](#resolver-versions) below), a different feature resolver is used
242 which uses a different algorithm for unifying features. The version `"1"`
243 resolver will unify features for a package no matter where it is specified.
244 The version `"2"` resolver will avoid unifying features in the following
245 situations:
246
247 * Features for target-specific dependencies are not enabled if the target is
248 not currently being built. For example:
249
250 ```toml
251 [dependency.common]
252 version = "1.0"
253 features = ["f1"]
254
255 [target.'cfg(windows)'.dependencies.common]
256 version = "1.0"
257 features = ["f2"]
258 ```
259
260 When building this example for a non-Windows platform, the `f2` feature will
261 *not* be enabled.
262
263 * Features enabled on [build-dependencies] or proc-macros will not be unified
264 when those same dependencies are used as a normal dependency. For example:
265
266 ```toml
267 [dependencies]
268 log = "0.4"
269
270 [build-dependencies]
271 log = {version = "0.4", features=['std']}
272 ```
273
274 When building the build script, the `log` crate will be built with the `std`
275 feature. When building the library of your package, it will not enable the
276 feature.
277
278 * Features enabled on [dev-dependencies] will not be unified when those same
279 dependencies are used as a normal dependency, unless those dev-dependencies
280 are currently being built. For example:
281
282 ```toml
283 [dependencies]
284 serde = {version = "1.0", default-features = false}
285
286 [dev-dependencies]
287 serde = {version = "1.0", features = ["std"]}
288 ```
289
290 In this example, the library will normally link against `serde` without the
291 `std` feature. However, when built as a test or example, it will include the
292 `std` feature. For example, `cargo test` or `cargo build --all-targets` will
293 unify these features. Note that dev-dependencies in dependencies are always
294 ignored, this is only relevant for the top-level package or workspace
295 members.
296
297 [build-dependencies]: specifying-dependencies.md#build-dependencies
298 [dev-dependencies]: specifying-dependencies.md#development-dependencies
299 [resolver-field]: features.md#resolver-versions
300
301 ### `links`
302
303 The [`links` field] is used to ensure only one copy of a native library is
304 linked into a binary. The resolver will attempt to find a graph where there is
305 only one instance of each `links` name. If it is unable to find a graph that
306 satisfies that constraint, it will return an error.
307
308 For example, it is an error if one package depends on [`libgit2-sys`] version
309 `0.11` and another depends on `0.12`, because Cargo is unable to unify those,
310 but they both link to the `git2` native library. Due to this requirement, it
311 is encouraged to be very careful when making SemVer-incompatible releases with
312 the `links` field if your library is in common use.
313
314 [`links` field]: manifest.md#the-links-field
315 [`libgit2-sys`]: https://crates.io/crates/libgit2-sys
316
317 ### Yanked versions
318
319 [Yanked releases][yank] are those that are marked that they should not be
320 used. When the resolver is building the graph, it will ignore all yanked
321 releases unless they already exist in the `Cargo.lock` file.
322
323 [yank]: publishing.md#cargo-yank
324
325 ## Dependency updates
326
327 Dependency resolution is automatically performed by all Cargo commands that
328 need to know about the dependency graph. For example, [`cargo build`] will run
329 the resolver to discover all the dependencies to build. After the first time
330 it runs, the result is stored in the `Cargo.lock` file. Subsequent commands
331 will run the resolver, keeping dependencies locked to the versions in
332 `Cargo.lock` *if it can*.
333
334 If the dependency list in `Cargo.toml` has been modified, for example changing
335 the version of a dependency from `1.0` to `2.0`, then the resolver will select
336 a new version for that dependency that matches the new requirements. If that
337 new dependency introduces new requirements, those new requirements may also
338 trigger additional updates. The `Cargo.lock` file will be updated with the new
339 result. The `--locked` or `--frozen` flags can be used to change this behavior
340 to prevent automatic updates when requirements change, and return an error
341 instead.
342
343 [`cargo update`] can be used to update the entries in `Cargo.lock` when new
344 versions are published. Without any options, it will attempt to update all
345 packages in the lock file. The `-p` flag can be used to target the update for
346 a specific package, and other flags such as `--aggressive` or `--precise` can
347 be used to control how versions are selected.
348
349 [`cargo build`]: ../commands/cargo-build.md
350 [`cargo update`]: ../commands/cargo-update.md
351
352 ## Overrides
353
354 Cargo has several mechanisms to override dependencies within the graph. The
355 [Overriding Dependencies] chapter goes into detail on how to use overrides.
356 The overrides appear as an overlay to a registry, replacing the patched
357 version with the new entry. Otherwise, resolution is performed like normal.
358
359 [Overriding Dependencies]: overriding-dependencies.md
360
361 ## Dependency kinds
362
363 There are three kinds of dependencies in a package: normal, [build], and
364 [dev][dev-dependencies]. For the most part these are all treated the same from
365 the perspective of the resolver. One difference is that dev-dependencies for
366 non-workspace members are always ignored, and do not influence resolution.
367
368 [Platform-specific dependencies] with the `[target]` table are resolved as-if
369 all platforms are enabled. In other words, the resolver ignores the platform
370 or `cfg` expression.
371
372 [build]: specifying-dependencies.md#build-dependencies
373 [dev-dependencies]: specifying-dependencies.md#development-dependencies
374 [Platform-specific dependencies]: specifying-dependencies.md#platform-specific-dependencies
375
376 ### dev-dependency cycles
377
378 Usually the resolver does not allow cycles in the graph, but it does allow
379 them for [dev-dependencies]. For example, project "foo" has a dev-dependency
380 on "bar", which has a normal dependency on "foo" (usually as a "path"
381 dependency). This is allowed because there isn't really a cycle from the
382 perspective of the build artifacts. In this example, the "foo" library is
383 built (which does not need "bar" because "bar" is only used for tests), and
384 then "bar" can be built depending on "foo", then the "foo" tests can be built
385 linking to "bar".
386
387 Beware that this can lead to confusing errors. In the case of building library
388 unit tests, there are actually two copies of the library linked into the final
389 test binary: the one that was linked with "bar", and the one built that
390 contains the unit tests. Similar to the issues highlighted in the
391 [Version-incompatibility hazards] section, the types between the two are not
392 compatible. Be careful when exposing types of "foo" from "bar" in this
393 situation, since the "foo" unit tests won't treat them the same as the local
394 types.
395
396 If possible, try to split your package into multiple packages and restructure
397 it so that it remains strictly acyclic.
398
399 ## Resolver versions
400
401 A different feature resolver algorithm can be used by specifying the resolver
402 version in `Cargo.toml` like this:
403
404 ```toml
405 [package]
406 name = "my-package"
407 version = "1.0.0"
408 resolver = "2"
409 ```
410
411 The version `"1"` resolver is the original resolver that shipped with Cargo up to version 1.50.
412 The default is `"2"` if the root package specifies [`edition = "2021"`](manifest.md#the-edition-field) or a newer edition.
413 Otherwise the default is `"1"`.
414
415 The version `"2"` resolver introduces changes in [feature
416 unification](#features). See the [features chapter][features-2] for more
417 details.
418
419 The resolver is a global option that affects the entire workspace. The
420 `resolver` version in dependencies is ignored, only the value in the top-level
421 package will be used. If using a [virtual workspace], the version should be
422 specified in the `[workspace]` table, for example:
423
424 ```toml
425 [workspace]
426 members = ["member1", "member2"]
427 resolver = "2"
428 ```
429
430 [virtual workspace]: workspaces.md#virtual-manifest
431 [features-2]: features.md#feature-resolver-version-2
432
433 ## Recommendations
434
435 The following are some recommendations for setting the version within your
436 package, and for specifying dependency requirements. These are general
437 guidelines that should apply to common situations, but of course some
438 situations may require specifying unusual requirements.
439
440 * Follow the [SemVer guidelines] when deciding how to update your version
441 number, and whether or not you will need to make a SemVer-incompatible
442 version change.
443 * Use caret requirements for dependencies, such as `"1.2.3"`, for most
444 situations. This ensures that the resolver can be maximally flexible in
445 choosing a version while maintaining build compatibility.
446 * Specify all three components with the version you are currently using.
447 This helps set the minimum version that will be used, and ensures that
448 other users won't end up with an older version of the dependency that
449 might be missing something that your package requires.
450 * Avoid `*` requirements, as they are not allowed on [crates.io], and they
451 can pull in SemVer-breaking changes during a normal `cargo update`.
452 * Avoid overly broad version requirements. For example, `>=2.0.0` can pull
453 in any SemVer-incompatible version, like version `5.0.0`, which can result
454 in broken builds in the future.
455 * Avoid overly narrow version requirements if possible. For example, if you
456 specify a tilde requirement like `bar="~1.3"`, and another package
457 specifies a requirement of `bar="1.4"`, this will fail to resolve, even
458 though minor releases should be compatible.
459 * Try to keep the dependency versions up-to-date with the actual minimum
460 versions that your library requires. For example, if you have a requirement
461 of `bar="1.0.12"`, and then in a future release you start using new features
462 added in the `1.1.0` release of "bar", update your dependency requirement to
463 `bar="1.1.0"`.
464
465 If you fail to do this, it may not be immediately obvious because Cargo can
466 opportunistically choose the newest version when you run a blanket `cargo
467 update`. However, if another user depends on your library, and runs `cargo
468 update -p your-library`, it will *not* automatically update "bar" if it is
469 locked in their `Cargo.lock`. It will only update "bar" in that situation if
470 the dependency declaration is also updated. Failure to do so can cause
471 confusing build errors for the user using `cargo update -p`.
472 * If two packages are tightly coupled, then an `=` dependency requirement may
473 help ensure that they stay in sync. For example, a library with a companion
474 proc-macro library will sometimes make assumptions between the two libraries
475 that won't work well if the two are out of sync (and it is never expected to
476 use the two libraries independently). The parent library can use an `=`
477 requirement on the proc-macro, and re-export the macros for easy access.
478 * `0.0.x` versions can be used for packages that are permanently unstable.
479
480 In general, the stricter you make the dependency requirements, the more likely
481 it will be for the resolver to fail. Conversely, if you use requirements that
482 are too loose, it may be possible for new versions to be published that will
483 break the build.
484
485 [SemVer guidelines]: semver.md
486
487 ## Troubleshooting
488
489 The following illustrates some problems you may experience, and some possible
490 solutions.
491
492 ### SemVer-breaking patch release breaks the build
493
494 Sometimes a project may inadvertently publish a point release with a
495 SemVer-breaking change. When users update with `cargo update`, they will pick
496 up this new release, and then their build may break. In this situation, it is
497 recommended that the project should [yank] the release, and either remove the
498 SemVer-breaking change, or publish it as a new SemVer-major version increase.
499
500 If the change happened in a third-party project, if possible try to
501 (politely!) work with the project to resolve the issue.
502
503 While waiting for the release to be yanked, some workarounds depend on the
504 circumstances:
505
506 * If your project is the end product (such as a binary executable), just avoid
507 updating the offending package in `Cargo.lock`. This can be done with the
508 `--precise` flag in [`cargo update`].
509 * If you publish a binary on [crates.io], then you can temporarily add an `=`
510 requirement to force the dependency to a specific good version.
511 * Binary projects can alternatively recommend users to use the `--locked`
512 flag with [`cargo install`] to use the original `Cargo.lock` that contains
513 the known good version.
514 * Libraries may also consider publishing a temporary new release with stricter
515 requirements that avoid the troublesome dependency. You may want to consider
516 using range requirements (instead of `=`) to avoid overly-strict
517 requirements that may conflict with other packages using the same
518 dependency. Once the problem has been resolved, you can publish another
519 point release that relaxes the dependency back to a caret requirement.
520 * If it looks like the third-party project is unable or unwilling to yank the
521 release, then one option is to update your code to be compatible with the
522 changes, and update the dependency requirement to set the minimum version to
523 the new release. You will also need to consider if this is a SemVer-breaking
524 change of your own library, for example if it exposes types from the
525 dependency.
526