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