Cargo and Package Management
Dependencies
Dependencies are external crates declared in Cargo.toml that Cargo downloads, compiles, and links into your targets. Cargo distinguishes three dependency scopes—runtime [dependencies], test-only [dev-dependencies], and pre-build [build-dependencies]—and supports fetching crates from crates.io, Git repositories, local filesystem paths, and private registries.
Dependency Scopes in Cargo.toml:
[dependencies] --> Linked into `src/lib.rs`, `src/main.rs`, tests, & examples
[dev-dependencies] --> Linked ONLY into `#[cfg(test)]`, `tests/`, `examples/`, `benches/`
[build-dependencies] --> Linked ONLY into `build.rs` (runs on host during compilation)
[target.'cfg(...)'.dependencies] --> Linked only when target platform matches `cfg(...)`
Comparing Dependency Scopes
| Section | Propagated to Downstream Consumers? | Available in src/lib.rs (Normal Build)? |
Available in tests/ & #[cfg(test)]? |
Available in build.rs? |
|---|---|---|---|---|
[dependencies] |
Yes | Yes | Yes | No |
[dev-dependencies] |
No | No | Yes | No |
[build-dependencies] |
Yes (when building your crate) | No | No | Yes |
Dependency Sources: Registry, Git, and Local Path
[dependencies]
# 1. Registry dependency from crates.io
itoa = "1.0"
# 2. Registry dependency with custom features and disabled default features
serde = { version = "1.0", default-features = false, features = ["alloc", "derive"] }
# 3. Git repository dependency (pinned to a tag, branch, or exact commit rev)
my_internal_proto = { git = "https://github.com/example/proto.git", tag = "v0.4.2" }
# 4. Local filesystem path dependency (used in workspaces or local development)
shared_domain = { path = "../shared_domain", version = "0.2.0" }
# 5. Renamed dependency (`package = "..."`): import two major versions side by side!
rand_v8 = { package = "rand", version = "0.8" }
rand_v9 = { package = "rand", version = "0.9" }
# 6. Platform-specific dependency: compiled and linked only on Unix targets
[target.'cfg(unix)'.dependencies]
libc = "0.2"
# 7. Platform-specific dependency: compiled and linked only on Windows targets
[target.'cfg(windows)'.dependencies]
windows-sys = { version = "0.59", features = ["Win32_Foundation"] }
Using cargo add and cargo remove
Rather than looking up the latest crate versions manually, use cargo add to edit Cargo.toml directly from the terminal:
# Add a runtime dependency with specific features
cargo add serde --features derive
# Add a test-only dev-dependency
cargo add --dev proptest
# Add a build.rs dependency
cargo add --build cc
# Remove an unused dependency
cargo remove serde
Overriding Dependencies Locally with [patch]
When debugging or fixing a bug inside an upstream transitive dependency without modifying intermediate crates' Cargo.toml files, add a [patch.crates-io] section to the workspace root Cargo.toml:
[patch.crates-io]
# Redirect all uses of `itoa` anywhere in the dependency graph to a local checkout
itoa = { path = "../local-itoa-fix" }
fn main() {
println!("Dependency scopes and sources configured");
}
Dependency scopes and sources configured