Cargo and Package Management

Build Profiles

Build profiles ([profile.*] in Cargo.toml) configure how rustc optimizes code, generates debug symbols, handles panics, and links compilation units across different workflows such as fast local development (dev) and maximum-performance production builds (release).

Built-In Cargo Profiles:
  [profile.dev]      --> Used by `cargo build`, `cargo check`, `cargo run`
      |--- inherits ---> [profile.test]   (Used by `cargo test`)
  [profile.release]  --> Used by `cargo build --release`, `cargo run --release`
      |--- inherits ---> [profile.bench]  (Used by `cargo bench`)

Comparing Built-In dev and release Defaults

Setting [profile.dev] Default [profile.release] Default Description
opt-level 0 (No optimizations) 3 (Full speed optimizations) Optimization level (0, 1, 2, 3, "s" for size, "z" for minimal size).
debug true (2 / full DWARF/PDB) false (0 / no debuginfo) Controls debug info level (false, "line-tables-only", 1, true).
debug-assertions true false Enables debug_assert! and cfg(debug_assertions).
overflow-checks true (panics on overflow) false (two's-complement wrap) Controls runtime integer overflow checks on +, -, *.
lto false false Link-Time Optimization across crates (false, "thin", "fat" / true).
panic "unwind" "unwind" Stack unwinding ("unwind") vs immediate termination ("abort").
incremental true false Caches incremental compilation graphs on disk.
codegen-units 256 16 Splits each crate into parallel LLVM codegen units (1 maximizes optimization).
strip "none" "none" Strips debug info or symbol tables ("none", "debuginfo", "symbols").

Production-Tuned Profiles and Per-Dependency Overrides

Two powerful profile customizations in Cargo.toml are:

  1. Optimizing slow dependencies in dev mode ([profile.dev.package."*"]): Image decoders, compression libraries, or cryptography crates can be slow at opt-level = 0. Compiling dependencies at opt-level = 2 while keeping your own crate at opt-level = 0 gives near-release runtime speed in cargo run and cargo test with fast incremental rebuilds!
  2. Defining custom profiles ([profile.profiling] or [profile.dist]): Custom profiles inherit from release or dev via inherits = "release" and are invoked with cargo build --profile <name>.
# 1. Speed up all third-party dependencies in `cargo run` and `cargo test`
[profile.dev.package."*"]
opt-level = 2

# 2. High-performance, compact production release binary
[profile.release]
lto = "thin"
codegen-units = 1
strip = "symbols"

# 3. Custom profile for CPU flamegraphs (`cargo build --profile profiling`)
[profile.profiling]
inherits = "release"
debug = "line-tables-only"
strip = "none"

Detecting Profile Settings in Code via cfg(debug_assertions)

fn active_profile_mode() -> &'static str {
    if cfg!(debug_assertions) {
        "dev/debug (overflow checks & debug_assert! enabled)"
    } else {
        "release (optimized)"
    }
}

fn main() {
    println!("Compiled with profile: {}", active_profile_mode());
}
Compiled with profile: dev/debug (overflow checks & debug_assert! enabled)