Rust Cargo Dependencies
A dependency is a crate a project uses but does not contain. A dependency can come from crates.io, from a folder on a local disk, or from a git repository.
Add a crate from the terminal
cargo add finds the newest compatible version on crates.io and writes the line into Cargo.toml for you, with the full version it picked:
cargo add itoaThe short form, written by hand
The version text is a semver range, not an exact pin: rand = "0.10" takes the crate from crates.io and allows the 0.10 line of releases. Cargo.lock pins the exact versions Cargo chose:
[dependencies]
itoa = "1"The table form sets more at once
Version, features and source all live inside the { }:
[dependencies]
serde = { version = "1", features = ["derive"] }From your own disk, or from git
A path dependency involves no registry, so it suits a workspace member or a library you are still writing. A git dependency names a repository instead. Pin it with rev, tag or branch. An unpinned git dependency can change under you.
[dependencies]
tools = { path = "../tools" }
charts = { git = "https://github.com/charts/charts" }Test-only and build-only crates
Crates under [dev-dependencies] are built for tests, examples and benchmarks, and code in src/ cannot use them at all. Crates under [build-dependencies] are for the build script alone: only build.rs can use them โ your program itself cannot.
[dev-dependencies]
helpers = { path = "../helpers" }
[build-dependencies]
tools = { path = "../tools" }Switchable and renamed crates
optional = true makes a dependency switchable. It stays out of the build until a feature of the same name is turned on. An example is cargo run --features charts. A renamed dependency changes the name your code uses. Your code writes use helpers. Cargo fetches the tools crate.
[dependencies]
charts = { path = "../charts", optional = true }
helpers = { package = "tools", path = "../tools" }Example
// Cargo.toml
// [dependencies]
// rand = "0.10" (from crates.io)
// tools = { path = "../tools" } (from your disk)
// [dev-dependencies]
// helpers = { path = "../helpers" } (tests only)
fn main() {
println!("shipped code can use: rand, tools");
println!("only tests can use: helpers");
println!("Cargo.lock pins the exact versions");
}Key points
- Dependency: a crate your project uses but does not contain.
- Cargo downloads it and builds it.
- Then it makes it available to your code
In this example, the comments show one Cargo.toml with two sections. Under [dependencies], rand comes from crates.io with a version promise, and tools comes from a folder on the same disk with a path. Under [dev-dependencies], helpers is listed for tests only โ code in src/ that tried to use it would not compile. The runnable code prints the three facts in order. First, what shipped code can use. Second, what only tests can use. Last, the reminder: Cargo.lock pins the exact versions Cargo chose.
Note
[dependencies] is for the code you ship.
The three sections keep test tools and build tools out of your finished program.
All three still live in the same Cargo.toml.
Try it Yourself
Edit the code, then press Run.
Running is simulated ยท Rust Playground
Exercise
Your tests need a crate that your shipped program must never include. Where does it go?