Manage Dependencies Cargo
Need to manage dependencies in your Rust project? This guide covers adding dependencies, version management, workspaces, and common Cargo operations.
Problem: Adding a Dependency
Scenario
You need to use an external crate in your project.
Solution 1: Edit Cargo.toml Manually
Add dependency to [dependencies] section.
[package]
name = "my_project"
version = "0.1.0"
edition = "2021"
[dependencies]
serde = "1.0"
tokio = { version = "1.0", features = ["full"] }Then run:
cargo buildHow it works: Cargo downloads and compiles dependencies during build.
Solution 2: Use cargo-edit
Install cargo-edit for command-line dependency management.
cargo install cargo-editAdd dependency:
cargo add serde
cargo add tokio --features fullBenefits: Automatically updates Cargo.toml with latest compatible version.
Problem: Specifying Version Requirements
Scenario
You need to control which versions of a dependency are acceptable.
Version Specifications
Caret (default):
serde = "^1.2.3" # Same as "1.2.3"Allows: >=1.2.3, <2.0.0 (compatible updates)
Tilde:
serde = "~1.2.3"Allows: >=1.2.3, <1.3.0 (patch updates only)
Exact version:
serde = "=1.2.3"Allows: Only 1.2.3
Wildcard:
serde = "1.*"Allows: >=1.0.0, <2.0.0
Range:
serde = ">=1.2, <1.5"Multiple requirements:
serde = ">=1.2.3, <1.8.0"Recommendation
Use default caret requirements for flexibility within SemVer compatibility.
serde = "1.0" # Allows 1.0.0 through 1.x.xProblem: Development and Build Dependencies
Scenario
You need dependencies only for tests or build scripts.
Solution: Use [dev-dependencies] and [build-dependencies]
[dependencies]
serde = "1.0"
[dev-dependencies]
criterion = "0.5" # Benchmarking, not needed in production
[build-dependencies]
cc = "1.0" # Build script dependencyHow it works:
[dependencies]: Required at runtime[dev-dependencies]: Only for tests, examples, benchmarks[build-dependencies]: Only forbuild.rsscripts
cargo build # Doesn't include dev-dependencies
cargo test # Includes dev-dependenciesProblem: Optional Dependencies and Features
Scenario
You want users to opt into certain features.
Solution: Define Features
[dependencies]
serde = { version = "1.0", optional = true }
tokio = { version = "1.0", optional = true }
[features]
default = ["serde"]
async = ["tokio"]
full = ["serde", "async"]Usage:
cargo build # Just "serde" (default)
cargo build --features async # Include tokio
cargo build --features full # Include everything
cargo build --no-default-features # Nothing optionalIn code:
#[cfg(feature = "serde")]
use serde::{Serialize, Deserialize};
#[cfg(feature = "async")]
pub async fn async_function() {
// ...
}Problem: Managing Workspace with Multiple Crates
Scenario
You have multiple related crates in one repository.
Solution: Create a Workspace
Root Cargo.toml:
[workspace]
members = [
"crate-a",
"crate-b",
"crate-c",
]
[workspace.dependencies]
serde = "1.0"
tokio = "1.0"Member crate Cargo.toml:
[package]
name = "crate-a"
version = "0.1.0"
edition = "2021"
[dependencies]
serde = { workspace = true }
crate-b = { path = "../crate-b" }Benefits:
- Shared
Cargo.lockensures consistent versions - Shared
target/directory - Build all crates with
cargo build --workspace - Centralized dependency versions
Commands:
cargo build --workspace # Build all crates
cargo test --workspace # Test all crates
cargo build -p crate-a # Build specific crateProblem: Updating Dependencies
Scenario
You need to update to newer versions of dependencies.
Solution 1: Update to Latest Compatible
cargo updateUpdates dependencies to latest versions compatible with Cargo.toml specifications. Updates Cargo.lock.
Solution 2: Update Specific Dependency
cargo update -p serdeSolution 3: Update to Latest SemVer
Use cargo-edit:
cargo upgradeUpdates version specifications in Cargo.toml to latest SemVer-compatible versions.
Problem: Using Git Dependencies
Scenario
You need a dependency from a Git repository.
Solution: Specify Git Source
[dependencies]
my_crate = { git = "https://github.com/user/my_crate" }Specific branch:
my_crate = { git = "https://github.com/user/my_crate", branch = "main" }Specific tag:
my_crate = { git = "https://github.com/user/my_crate", tag = "v1.0.0" }Specific commit:
my_crate = { git = "https://github.com/user/my_crate", rev = "abc123" }Warning: Git dependencies are not published to crates.io. Only use for development or private crates.
Problem: Local Path Dependencies
Scenario
You’re developing two crates together and want to link them.
Solution: Use Path Dependencies
[dependencies]
my_lib = { path = "../my_lib" }For published crates: Combine with version for publishing.
[dependencies]
my_lib = { version = "0.1", path = "../my_lib" }When published, only version is used. During local development, path is used.
Problem: Platform-Specific Dependencies
Scenario
Dependency is only needed on certain platforms.
Solution: Use Target-Specific Dependencies
[target.'cfg(windows)'.dependencies]
winapi = "0.3"
[target.'cfg(unix)'.dependencies]
libc = "0.2"
[target.'cfg(target_os = "macos")'.dependencies]
core-foundation = "0.9"Only compiled on matching platforms.
Problem: Checking for Outdated Dependencies
Scenario
You want to see which dependencies have newer versions available.
Solution: Use cargo-outdated
cargo install cargo-outdated
cargo outdatedOutput:
Name Project Compat Latest Kind Platform
---- ------- ------ ------ ---- --------
serde 1.0.100 1.0.152 1.0.152 Normal ---
tokio 1.20.0 1.32.0 1.32.0 Normal ---Problem: Auditing Dependencies for Security
Scenario
You want to check for known security vulnerabilities.
Solution: Use cargo-audit
cargo install cargo-audit
cargo auditOutput:
Crate: time
Version: 0.1.43
Warning: Potential segfault in `time` crate
ID: RUSTSEC-2020-0071Fix:
cargo audit fixAutomatically updates vulnerable dependencies where possible.
Problem: Viewing Dependency Tree
Scenario
You want to understand your dependency graph.
Solution: Use cargo tree
cargo treeOutput:
my_project v0.1.0
├── serde v1.0.152
│ └── serde_derive v1.0.152
└── tokio v1.32.0
├── bytes v1.4.0
└── pin-project-lite v0.2.13Show specific dependency:
cargo tree -p serdeShow duplicates:
cargo tree --duplicatesProblem: Reducing Build Times
Scenario
Dependency compilation is slow.
Solution 1: Use sccache
Cache compiled dependencies across projects.
cargo install sccache
export RUSTC_WRAPPER=sccache
cargo buildSolution 2: Reduce Features
Only include needed features.
tokio = { version = "1.0", features = ["full"] }
tokio = { version = "1.0", features = ["rt-multi-thread", "macros"] }Solution 3: Use Workspaces
Share dependencies across multiple crates.
Problem: Publishing to crates.io
Scenario
You want to publish your crate.
Solution: Publish with Cargo
1. Login:
cargo login <your-api-token>2. Package and verify:
cargo package
cargo package --list # See what will be included3. Publish:
cargo publish4. Dry run first:
cargo publish --dry-runCargo.toml requirements:
[package]
name = "my_crate"
version = "0.1.0"
edition = "2021"
authors = ["Your Name <you@example.com>"]
license = "MIT OR Apache-2.0"
description = "A short description"
repository = "https://github.com/user/my_crate"Common Pitfalls
Pitfall 1: Not Committing Cargo.lock
Problem: For applications, Cargo.lock should be committed.
Solution:
- Applications/binaries: Commit
Cargo.lockfor reproducible builds - Libraries: Don’t commit
Cargo.lock(users should resolve versions)
Pitfall 2: Using Full Feature Sets
Problem: Including features = ["full"] increases compile time.
tokio = { version = "1.0", features = ["full"] }Solution: Only include needed features.
tokio = { version = "1.0", features = ["rt-multi-thread", "net"] }Pitfall 3: Not Pinning Versions
Problem: Using * or no version allows breaking changes.
serde = "*"Solution: Use specific version requirements.
serde = "1.0"Related Commands
Essential Cargo commands:
cargo new my_project # Create new project
cargo build # Build project
cargo build --release # Optimized build
cargo run # Build and run
cargo test # Run tests
cargo doc --open # Generate and view docs
cargo clean # Remove build artifacts
cargo check # Fast compilation check
cargo clippy # Linter
cargo fmt # Format codeRelated Resources
- Official Cargo Book
- Tutorials: Initial Setup - Getting started with Cargo
- Best Practices - Dependency management patterns
- Resources - Cargo tools and extensions
Master Cargo to efficiently manage your Rust projects!