cargo build
cargo build (aliased as cargo b) compiles your package and all of its dependencies, producing native binary executables and/or library artifacts inside the target/ directory without executing them.
Debug vs Release Builds
By default, running cargo build with no flags compiles using the dev profile (unoptimized, fast compile time, full debug symbols). Passing --release (or -r) compiles using the release profile (full LLVM optimizations, stripped of runtime overflow checks):
# 1. Build in debug mode (`dev` profile) -> outputs to `target/debug/<name>`
cargo build
# 2. Build in release mode (`release` profile) -> outputs to `target/release/<name>`
cargo build --release
Compiling my_project v0.1.0 (/Users/username/my_project)
Finished `release` profile [optimized] target(s) in 0.42s
Directory Layout of target/
When cargo build runs, it places all intermediate files, dependency caches, and final executables inside target/ at the root of the package (or workspace):
target/
├── CACHEDIR.TAG <-- Marks `target/` so backup tools ignore it
├── debug/ <-- Output of `cargo build` (`dev` profile)
│ ├── <package_name> <-- Final compiled executable binary!
│ ├── lib<package_name>.rlib <-- Compiled library (if `src/lib.rs` exists)
│ ├── build/ <-- Output of custom `build.rs` scripts
│ ├── deps/ <-- Compiled `.rlib` and `.rmeta` files for dependencies
│ ├── examples/ <-- Compiled binaries from `examples/*.rs`
│ └── incremental/ <-- Query cache for fast incremental recompilation
└── release/ <-- Output of `cargo build --release` (`release` profile)
├── <package_name> <-- Optimized production executable binary!
└── deps/
Because target/ can grow to hundreds of megabytes or several gigabytes as dependencies and incremental caches accumulate, it is always listed in .gitignore and can be safely deleted at any time using cargo clean.
Common cargo build Flags
| Flag | Example | Description |
|---|---|---|
--release / -r |
cargo build --release |
Builds with optimizations (opt-level = 3) in target/release/ |
--profile <name> |
cargo build --profile bench |
Builds using a specific custom profile defined in Cargo.toml |
--bin <name> |
cargo build --bin server |
Builds only the specified binary target |
--bins |
cargo build --bins |
Builds all binary targets (src/main.rs and src/bin/*.rs) |
--lib |
cargo build --lib |
Builds only the package's library target (src/lib.rs) |
--examples |
cargo build --examples |
Builds all standalone examples in examples/*.rs |
--tests |
cargo build --tests |
Compiles unit and integration test binaries without running them |
--all-targets |
cargo build --all-targets |
Builds libraries, binaries, examples, tests, and benchmarks |
--workspace |
cargo build --workspace |
Builds all member packages in a Cargo workspace |
-p <pkg> / --package |
cargo build -p core_api |
Builds a specific package inside a workspace |
--features "<list>" |
cargo build --features "tls,json" |
Enables optional Cargo feature flags |
--all-features |
cargo build --all-features |
Enables every optional feature defined in Cargo.toml |
--no-default-features |
cargo build --no-default-features |
Disables the default = [...] feature set in Cargo.toml |
--target <triple> |
cargo build --target wasm32-unknown-unknown |
Cross-compiles for <triple> (outputs to target/<triple>/debug/) |
-j <N> / --jobs <N> |
cargo build -j 4 |
Limits the number of parallel rustc processes (defaults to CPU core count) |
--timings |
cargo build --timings |
Generates an HTML report (cargo-timing.html) showing per-crate build duration and CPU parallelism |
--offline |
cargo build --offline |
Builds using only locally cached crates in ~/.cargo/ without touching the network |
--locked |
cargo build --locked |
Fails if Cargo.lock would need to be updated (recommended in CI and Docker builds) |
Cross-Compilation Output Path (--target)
When you pass --target <triple>, Cargo places the build artifacts in a target-specific subdirectory target/<triple>/debug/ (or target/<triple>/release/) so host and cross-compiled artifacts never overwrite each other:
cargo build --target aarch64-apple-darwin --release
target/
└── aarch64-apple-darwin/
└── release/
└── my_project
Profiling Build Times (cargo build --timings)
On large projects, passing --timings records when each crate starts compilation, when its .rmeta metadata finishes (unlocking downstream crates to begin type-checking in parallel!), and when LLVM codegen finishes:
cargo clean
cargo build --timings
Timing report saved to /Users/username/my_project/target/cargo-timings/cargo-timing-20261021T180000Z.html