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