Lesson 3
Your first Cargo project
Create a binary package with cargo new, understand Cargo.toml and Cargo.lock, and walk through the check, build, run, test and doc cycle.
From an installed toolchain to your first package
In the previous lesson you installed rustup, rustc, Cargo and the rest of
the ecosystem’s tooling. Now it is time to use them: instead of compiling a
single file with rustc, you will create a package managed by Cargo, the
way virtually all real Rust code gets built.
This lesson walks through the full cycle: creating the package, understanding what each generated file describes, and running the commands you will use every day while you write code.
Create the package
cargo new project_name
cd project_nameCargo generates this structure:
project_name/
- Cargo.toml
- .gitignore
src/
- main.rs
And src/main.rs already contains a program that compiles and runs:
fn main() {
println!("Hello, Rust!");
}Read the manifest
[package]
name = "project_name"
version = "0.1.0"
edition = "2024"
# Filled in with `cargo add`, not by hand.
[dependencies]Cargo.toml is the single source of truth for what your package depends on
and which versions. Cargo.lock, generated alongside it on the first
build, pins the exact resolved versions so the build is reproducible on any
machine; never edit it by hand.
The check → build → run cycle
cargo check
cargo build
cargo runcargo check is the fastest because it does not produce final machine
code. cargo build leaves an unoptimized binary at target/debug/.
cargo run recompiles only if something changed and runs the result.
For an optimized build:
cargo build --releaseThe optimized binary ends up at target/release/, at the cost of a slower
compile than debug mode.
Test and document
cargo test
cargo doc --opencargo test discovers and runs any function marked #[test] in the crate;
there is nothing extra to configure. cargo doc --open generates an HTML
site from the /// comments on the public API and opens it in your
browser.
What this lesson does not cover
- It does not go deep into the full difference between debug and release profiles (optimizations, debug symbols, compile times).
- It does not explain how to read a compiler error when something fails to build: that is the next lesson.
- It does not cover real external dependencies beyond
cargo add/cargo rm, already seen in the previous lesson.
What’s next
With a package that builds, runs, tests and documents itself, the next lesson teaches you how to read the compiler’s messages when something fails: what each part of an error means and how Rust guides you toward a fix.
Summary
cargo newcreates the minimum package structure (Cargo.toml,src/main.rs,.gitignore);--libgenerates a library instead.Cargo.tomldeclares the package and its dependencies;Cargo.lockpins the exact resolved versions and is never hand-edited.cargo checkchecks types without producing a binary;cargo buildproduces one attarget/debug/;cargo runcompiles if needed and runs;--releaseoptimizes and compiles more slowly.cargo testruns any#[test]function;cargo doc --opengenerates and opens HTML documentation from///comments.