Cargo and Package Management

Cargo Fundamentals

Cargo is Rust's official build system, package manager, dependency resolver, and test/documentation orchestrator. Instead of invoking rustc manually with long lists of --extern library paths and compiler flags, developers interact with cargo, which reads a declarative manifest (Cargo.toml), downloads and compiles dependencies in topological order, and caches build artifacts inside the target/ directory.

+-------------------------------------------------------------------+
|                        Cargo Workflow                             |
|                                                                   |
|  Cargo.toml (Manifest) + Cargo.lock (Exact Versions)              |
|               |                                                   |
|               v                                                   |
|     [ Dependency Resolver ] ---> Downloads crates from crates.io  |
|               |                                                   |
|               v                                                   |
|     [ Build Graph Planner ] ---> Invokes `rustc` / `rustdoc`      |
|               |                                                   |
|               v                                                   |
|     target/debug/ or target/release/ (Cached Artifacts)           |
+-------------------------------------------------------------------+

Standard Cargo Package Layout

When you run cargo new my_app (or cargo new --lib my_lib), Cargo scaffolds a standardized directory layout that follows convention over configuration:

my_package/
├── .gitignore
├── Cargo.toml               <-- Package manifest (metadata, dependencies, profiles)
├── Cargo.lock               <-- Exact resolved dependency versions (generated by Cargo)
├── build.rs                 <-- Optional custom pre-build script
├── src/
│   ├── lib.rs               <-- Default library crate root (at most 1 per package)
│   ├── main.rs              <-- Default binary crate root
│   └── bin/                 <-- Additional binary crate roots (`src/bin/*.rs`)
├── examples/                <-- Runnable example programs (`cargo run --example <name>`)
├── tests/                   <-- Integration test suites (`cargo test`)
└── benches/                 <-- Benchmark suites (`cargo bench`)

Core Responsibilities of Cargo

Responsibility What Cargo Does Automatically
Project Scaffolding Creates a new package (cargo new) or initializes an existing directory (cargo init) with Git configuration.
Dependency Resolution Resolves SemVer-compatible crate graphs (using the MSRV-aware Resolver v3 in edition = "2024"), downloads archives, and records exact SHA-256 checksums in Cargo.lock.
Incremental Compilation Tracks source file modification timestamps, feature flags, and environment variables so cargo check and cargo build only recompile changed crates.
Target Orchestration Passes exact --crate-type, --edition, -C opt-level, and --cfg flags to rustc and rustdoc.

Inspecting Metadata Injected by Cargo at Compile Time

Whenever Cargo invokes rustc, it injects compile-time CARGO_* environment variables that code can inspect via env!:

fn main() {
    let pkg_name = option_env!("CARGO_PKG_NAME").unwrap_or("standalone_bin");
    let pkg_version = option_env!("CARGO_PKG_VERSION").unwrap_or("0.1.0");

    println!("Package: {pkg_name} v{pkg_version}");
}
Package: standalone_bin v0.1.0