Your First Program
Scope: creating a Rust project with Cargo, building it, running it, and reading the files Cargo made. All commands below were run and verified.
Make a project
cargo new hello
cd hello
Cargo created a folder with this inside:
hello/
├── Cargo.toml # project settings: name, version, libraries
└── src/
└── main.rs # your code
Look at src/main.rs:
fn main() {
println!("Hello, world!");
}
fn main()— the function that runs when the program starts.println!— prints a line. The!means it's a macro (a code-writing shortcut), not a regular function. You'll see!on a few built-in helpers; for now, just read it as "print line."
Cargo.toml holds the project's name, version, and edition:
[package]
name = "hello"
version = "0.1.0"
edition = "2021"
You won't touch this file much at first.
Build and run
cargo run
Check: you should see something like:
Compiling hello v0.1.0 (/path/to/hello)
Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.42s
Running `target/debug/hello`
Hello, world!
cargo run compiles and runs. Two related commands:
| Command | Does | Use when |
|---|---|---|
cargo build |
Compiles only | You want the binary without running it |
cargo run |
Compiles (if needed) and runs | Normal development |
cargo check |
Checks for errors without building | Fast error-check while editing |
cargo check is the one you'll use most while learning — it's much
faster than a full build because it skips generating machine code.
Change it and re-run
Edit src/main.rs:
fn main() {
println!("Hello, world!");
println!("Rust is watching my memory.");
}
Run cargo run again.
Check: both lines print. Notice Cargo only recompiled what changed — the second run is faster.
Where the binary went
After cargo build, the compiled program lives at
target/debug/hello (or hello.exe on Windows). You can run it
directly:
./target/debug/hello
cargo run is just a shortcut for build-then-run-this-file.
A first taste of the compiler watching you
Try this (it will fail — that's the lesson):
fn main() {
let x = 5;
println!("x is {}", x);
x = 6;
println!("x is now {}", x);
}
Run cargo check.
Check: the compiler refuses, with an error about "cannot assign
twice to immutable variable." In Rust, variables are immutable by
default — you can't change them unless you ask for mutability with
let mut. This feels annoying on day one and wonderful by month
two: an entire class of "wait, who changed this?" bugs can't happen.
The fix, for the curious:
fn main() {
let mut x = 5;
println!("x is {}", x);
x = 6;
println!("x is now {}", x);
}
Check
- [ ]
cargo new,cargo run,cargo checkall work - [ ] You can say where the compiled binary lives
- [ ] You can explain why
let x = 5; x = 6;fails
Next: Variables and Types.