How does cargo manage dependency versions? - rust

I was reading this at the guessing game tutorial inside the rust book
Ensuring Reproducible Builds with the Cargo.lock File
Cargo has a mechanism that ensures you can rebuild the same artifact every time you or anyone else builds your code: Cargo will use only the versions of the dependencies you specified until you indicate otherwise. For example, say that next week version 0.8.4 of the rand crate comes out, and that version contains an important bug fix, but it also contains a regression that will break your code. To handle this, Rust creates the Cargo.lock file the first time you run cargo build, so we now have this in the guessing_game directory.
When you build a project for the first time, Cargo figures out all the versions of the dependencies that fit the criteria and then writes them to the Cargo.lock file. When you build your project in the future, Cargo will see that the Cargo.lock file exists and use the versions specified there rather than doing all the work of figuring out versions again. This lets you have a reproducible build automatically. In other words, your project will remain at 0.8.3 until you explicitly upgrade, thanks to the Cargo.lock file.
but didn't quite understand how cargo garantees that we have/need the correct version of a dependency. For instance, if we put in the [dependecies] rand="0.8.3" it will not exactly download the crate at this version, but the crate the match the needs of our program but it's compatible with this version(?)
Please clarify this logic!

When specifying a crate in Cargo.toml, you can give an exact version (e.g. =0.8.3) or more general indications (e.g. 0.8.*).
If you specify rand = "=0.8.3" in Cargo.toml, then cargo will take version 0.8.3 (note the extra = inside the version requirement). But if you specify rand = "*", then the first time you build your crate it will take the latest version and write this version to Cargo.lock. That way if you rebuild your crate later cargo will reuse the same version even if a new version has been published on crates.io in the meantime.
Note btw that specifying rand = "0.8.3" does not mean "exactly version 0.8.3", but instead means "any version >=0.8.3 and <0.9": link.

Related

How do I fetch and compile only the dev-dependencies? [duplicate]

This question already has answers here:
Can Cargo download and build dependencies without also building the application?
(6 answers)
Closed 10 months ago.
The Rust Cargo.toml specification file allows for development dependencies section, e.g. [dev-dependencies]
Cargo.toml:
[dev-dependencies]
tempdir = "0.3"
What is the command to fetch and compile those development dependencies?
To be clear, I want to fetch and compile only the [dev-dependencies]. The Linked questions differ in that they address fetching and compiling all dependencies and then building the application.
I do not have enough reputation so I just answer.
As declare by your link and rust-by-example, it is impossible to "build" a binary from dev-dependencies.
Sometimes there is a need to have dependencies for tests (or examples,
or benchmarks) only. Such dependencies are added to Cargo.toml in the
[dev-dependencies] section
To be sneaky, may be you can put some function under #[cfg(test)] and run cargo test so that your goal can be achieved.
A more appropriate way to selectively build by cargo using the feature flag, in cargo.toml and cargo command. You can take a look at the cargo command to toggle feature here and optional dependencies which help control categorizing of features.

How do I resolve a cyclic dependency in Cargo?

I have the crates oauth2 (v4.1.0) and sqlx[json] (v0.5.5):
[dependencies]
oauth2 = "4.1.0"
sqlx = { version = "0.5.5", features = ["json"] }
When attempting to build, I am getting the following error:
error: cyclic package dependency: package `ahash v0.7.4` depends on itself. Cycle:
package `ahash v0.7.4`
... which is depended on by `hashbrown v0.11.2`
... which is depended on by `indexmap v1.7.0`
... which is depended on by `serde_json v1.0.64`
... which is depended on by `wasm-bindgen v0.2.74`
... which is depended on by `js-sys v0.3.51`
... which is depended on by `getrandom v0.2.3`
... which is depended on by `ahash v0.7.4`
This only happens when I activate the json feature flag on sqlx. How do I troubleshoot this kind of problem? Are there any workarounds to make these libs/features work together? What are the alternatives?
After trying a few things back and forth, the only solution I found, was to update the lockfile to the latest version, using:
cargo update
After that, cargo clean && cargo build worked like a charm! Seems like some older patch versions seem to have conflicts, but the changes in the Cargo.lock were too big to track down, which crate combination it was. I hope that helps anybody else!
EDIT: After more communication and searching, I got referred to an issue directly at the ahash github project: https://github.com/tkaitchuck/aHash/issues/95.
According to that, the actual official "workaround" was / is, to pin the indexmap crate to:
indexmap = "=1.6.2"
However when looking into my Cargo.lock file, it seems to work with now:
indexmap = "1.7"

How can I find the latest stable version of a crate using cargo?

I want to know the latest actix-web version, so I executed cargo search actix-web. The result is actix-web = "4.0.0-beta.1", showing the beta version number.
I want to know the latest stable version number; how do I get it?
Usually, I only care to know about the version number of a crate when I'm going to add the crate to my Cargo.toml. In those cases, I use two extra Cargo subcommands from the cargo-edit project:
cargo add — adds the current stable version of a crate to Cargo.toml. Options exist for allowing prerelease versions or marking it as a build / dev dependency.
cargo upgrade — updates the version of a crate already in Cargo.toml. Similar to cargo update, but also changes Cargo.toml in addition to Cargo.lock.
cargo show --json $1 | python -m json.tool | jq ".versions[].num"

Unable to build rust's Rocket project because of framework dependency error

I'm following this tutorial here and have also looked into Rocket's official guide of setting up a web server.
I've set as default the nightly builds. But I get the following error:
error: failed to select a version for the requirement `ring = "^0.11.0"`
candidate versions found which didn't match: 0.16.11, 0.16.10, 0.16.9, ...
location searched: crates.io index
required by package `cookie v0.9.1`
... which is depended on by `rocket v0.3.6`
... which is depended on by `my-project`
Obviously there's some mismatch with the dependencies, but since ring is something required by the framework itself, I'm not sure how to debug this... furthermore, I'm using the latest versions of cargo and rust:
cargo 1.43.0-nightly (... 2020-02-18)
rustc 1.43.0-nightly (... 2020-02-21)
ring v0.11.0 was yanked from crates.io (see this issue for some background). Since some versions rocket depended on versions of ring that were yanked, those versions of rocket will no longer work.
Upgrading to rocket v0.4.0 (or the latest v0.4.2) should solve this issue.

native library `glib` is being linked to by more than one package, and can only be linked to by one package [duplicate]

I'm facing this problem when I try to cargo build:
error: native library openssl is being linked to by more than one version of the same package, but it can only be linked once; try updating or pinning your dependencies to ensure that this package only shows up once
openssl-sys v0.6.7
openssl-sys v0.7.13
Cargo and Rust versions:
$ cargo --version
cargo 0.11.0-nightly (3ff108a 2016-05-24)
$ rustc --version
rustc 1.11.0-nightly (7746a334d 2016-05-28)
Files:
Cargo.toml
Cargo.lock
can't get why this doesn't compile and how to solve this problem.
Thank you!
The way that linking works, you can only have a single version of a native library linked, otherwise you end up with duplicate symbols. Cargo's links manifest key helps prevent you from accidentally linking to the same set of symbols twice.
To solve it, you need to read through your Cargo.lock (it's not a difficult file format to understand). Find the crates that have the offending library as a dependency and note which ones have conflicting versions.
Then you have to manually resolve your dependencies so that their dependencies use the same version of the native library.
In this case, the important aspects of the dependency chain are:
server (0.0.1) => cookie (0.2.4) => openssl (0.7.13)
=> hyper (0.6.16) => cookie (0.1.21) => openssl (0.6.7)
To fix it, modify your Cargo.toml to use the same version of cookie as hyper. Then you will implicitly get the same version of openssl.
To be honest, this is one of the roughest parts of Rust at the moment. At least this version of the "multiple different versions of the same crate" strangeness provides a straight-forward Cargo error.

Resources