In the previous tutorial, we learned why Rust matters. Now let’s install it and write our first program.
By the end of this tutorial, you will have Rust installed, your editor set up, and a working program that you built and ran yourself.
Step 1: Install Rust with rustup
Rust uses a tool called rustup to manage installations. One command installs everything:
macOS / Linux
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
Follow the prompts — choose the default installation (option 1).
After it finishes, restart your terminal or run:
source $HOME/.cargo/env
Windows
Download and run the installer from rustup.rs. Follow the prompts. You may need to install the Visual Studio C++ Build Tools if prompted.
Verify Installation
rustc --version
# rustc 1.87.0 (or newer)
cargo --version
# cargo 1.87.0 (or newer)
If you see version numbers, Rust is installed.
What You Just Installed
rustup installs three tools:
| Tool | What It Does |
|---|---|
| rustc | The Rust compiler — turns .rs files into executables |
| cargo | The package manager AND build system — creates projects, manages dependencies, builds, tests |
| rustup | The version manager — updates Rust, switches between versions |
You will almost never call rustc directly. You will use cargo for everything.
Useful rustup Commands
# Update Rust to the latest version
rustup update
# Check which version you have
rustup show
# Add a component (like the formatter)
rustup component add rustfmt
rustup component add clippy
Step 2: Set Up Your Editor
VS Code (Recommended)
- Install VS Code
- Install these extensions:
- rust-analyzer — the main Rust extension (autocomplete, errors, go-to-definition)
- Even Better TOML — syntax highlighting for
Cargo.toml - Error Lens — shows errors inline (optional but helpful)
That is the complete setup. rust-analyzer gives you:
- Autocomplete as you type
- Error highlighting before you compile
- Type hints on hover
- Go to definition (Cmd+Click)
- Auto-formatting on save
IntelliJ / RustRover
JetBrains makes RustRover — a dedicated Rust IDE. It is free for non-commercial use and has excellent Rust support. If you already use IntelliJ, this is a great choice.
Other Editors
Any editor works with Rust. rust-analyzer supports VS Code, Neovim, Helix, Emacs, and Sublime Text. But VS Code has the smoothest setup for beginners.
Step 3: Create Your First Project
Open your terminal and run:
# Create a new project called "hello"
cargo new hello
cd hello
This creates a folder with this structure:
hello/
├── Cargo.toml ← Project config (dependencies, version, etc.)
└── src/
└── main.rs ← Your code goes here
What is Cargo.toml?
[package]
name = "hello"
version = "0.1.0"
edition = "2024"
[dependencies]
- name — your project name
- version — your project version
- edition — which Rust edition to use (2024 is the latest)
- [dependencies] — external libraries (empty for now)
Note about editions: Rust has “editions” (2015, 2018, 2021, 2024). Each edition adds new features and syntax. New projects use the latest edition. If you see older tutorials using edition = "2021", the code still works — Rust is backwards compatible.
What is main.rs?
fn main() {
println!("Hello, world!");
}
This is a complete Rust program:
fn main()— the entry point (every Rust program starts here)println!()— prints text to the terminal (the!means it is a macro, not a function — we will cover macros later)
Step 4: Run Your Program
cargo run
Output:
Compiling hello v0.1.0 (/path/to/hello)
Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.5s
Running `target/debug/hello`
Hello, world!
That’s it. Your first Rust program runs.
What cargo run Does
- Compiles your code (turns
.rsinto a binary executable) - Runs the compiled binary
The compiled binary is at target/debug/hello. You can run it directly:
./target/debug/hello
# Hello, world!
Step 5: Understand the Cargo Commands
| Command | What It Does | When to Use |
|---|---|---|
cargo new name | Create a new project | Starting a project |
cargo run | Compile + run | During development |
cargo build | Compile only (don’t run) | When you just want to check if it compiles |
cargo check | Check for errors (fastest, no binary) | Quick error checking while coding |
cargo test | Run tests | Testing your code |
cargo fmt | Format your code | Before committing |
cargo clippy | Lint your code (suggests improvements) | Finding common mistakes |
cargo doc --open | Generate and open documentation | Reading docs for your dependencies |
The ones you will use most: cargo run (during development) and cargo check (quick error checking).
cargo check vs cargo build
# Fast — only checks for errors, doesn't produce a binary
cargo check # Takes ~0.5 seconds
# Slower — compiles everything, produces a binary
cargo build # Takes ~2-10 seconds
# Even slower — compiles with optimizations for release
cargo build --release # Takes ~10-60 seconds
Use cargo check while developing — it is much faster because it skips the code generation step. Use cargo build or cargo run when you actually need to run the program.
Step 6: Let’s Write Something More
Let’s make the program interactive:
use std::io;
fn main() {
println!("What is your name?");
let mut name = String::new();
io::stdin()
.read_line(&mut name)
.expect("Failed to read input");
// trim() removes the newline character from the input
let name = name.trim();
println!("Hello, {}! Welcome to Rust.", name);
}
Run it:
cargo run
What is your name?
Alex
Hello, Alex! Welcome to Rust.
What is Happening Here?
use std::io;
// Import the io (input/output) module from the standard library
let mut name = String::new();
// Create a mutable variable called "name"
// "mut" means we can change it later
// String::new() creates an empty String
io::stdin().read_line(&mut name).expect("Failed to read input");
// Read a line from the terminal into "name"
// &mut name — pass a mutable reference (we'll cover this in Tutorial #5)
// .expect() — crash with this message if reading fails
let name = name.trim();
// Create a new "name" that shadows the old one
// .trim() removes whitespace and newlines from both ends
Don’t worry if &mut, expect(), and String::new() seem confusing. We will cover every concept in detail in the next tutorials. For now, just know:
letcreates a variablemutmakes it changeableString::new()creates an empty stringprintln!("{}", variable)prints a variable
Step 7: Add a Dependency
Let’s use an external library (called a “crate” in Rust). We will add colored to print colorful text:
cargo add colored
This updates Cargo.toml:
[dependencies]
colored = "3.0.0"
Now use it:
use colored::*;
fn main() {
println!("{}", "Hello from Rust!".green().bold());
println!("{}", "This text is red.".red());
println!("{}", "This text is blue and italic.".blue().italic());
println!("{}", "Warning!".yellow().on_black());
}
Run it:
cargo run
You will see colorful text in your terminal. That’s how easy it is to use external libraries in Rust — cargo add, import, use.
Finding Crates
- crates.io — the official crate registry (like npm for JavaScript)
- lib.rs — a nicer interface for browsing crates
- Search:
cargo search keyword
Bonus: Live Reloading with bacon
When developing, it is annoying to type cargo check or cargo run every time you change a file. bacon watches your files and runs the compiler automatically:
# Install bacon
cargo install --locked bacon
# Run it — it watches your files and shows errors live
bacon
Every time you save a file, bacon re-runs cargo check and shows the results instantly. This makes the edit-compile cycle much faster.
An alternative is cargo-watch:
cargo install cargo-watch
cargo watch -x check
Both tools do the same thing. bacon has a nicer interface. Try both and pick the one you prefer.
Project Structure Deep Dive
After running and building, your project looks like this:
hello/
├── Cargo.toml ← Project config
├── Cargo.lock ← Exact dependency versions (auto-generated)
├── src/
│ └── main.rs ← Your source code
└── target/ ← Build output (compiled binaries, don't commit)
├── debug/
│ └── hello ← Debug binary (unoptimized, fast compile)
└── release/
└── hello ← Release binary (optimized, slow compile)
.gitignore
Cargo automatically creates a .gitignore that excludes target/:
/target
Never commit the target/ folder — it contains compiled binaries that can be rebuilt.
Debug vs Release
Debug (cargo build) | Release (cargo build --release) | |
|---|---|---|
| Compile speed | Fast (~2 seconds) | Slow (~10-60 seconds) |
| Binary speed | Slower (no optimizations) | Fast (fully optimized) |
| Binary size | Larger | Smaller |
| Use for | Development | Production / benchmarking |
Always develop with debug builds. Only use --release when shipping or benchmarking.
Common Mistakes
Mistake 1: Forgetting to Restart Terminal
After installing Rust, your terminal doesn’t know about cargo yet:
# If you get "command not found: cargo"
source $HOME/.cargo/env
# Or just restart your terminal
Mistake 2: Missing Semicolons
// BAD — missing semicolons
fn main() {
let x = 5
println!("{}", x)
}
// GOOD — Rust requires semicolons at the end of statements
fn main() {
let x = 5;
println!("{}", x);
}
Rust requires semicolons. If you forget one, the compiler will tell you exactly where.
Mistake 3: Wrong Quotes
// BAD — single quotes are for characters, not strings
let name = 'Alex'; // ERROR: too many characters
// GOOD — double quotes for strings
let name = "Alex";
// Single quotes are for single characters
let letter = 'A'; // OK — one character
Mistake 4: Not Reading Compiler Errors
The Rust compiler has the best error messages of any language. When something goes wrong, read the error carefully — it usually tells you exactly what to fix and often suggests the correction.
error[E0384]: cannot assign twice to immutable variable `x`
--> src/main.rs:3:5
|
2 | let x = 5;
| - first assignment
3 | x = 10;
| ^^^^^^ cannot assign twice to immutable variable
|
help: consider making this binding mutable
|
2 | let mut x = 5;
| +++
The compiler says: “You need mut to change this variable.” It even shows you where to add it. Trust the compiler.
Quick Reference
| Action | Command |
|---|---|
| Install Rust | curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh |
| Update Rust | rustup update |
| New project | cargo new project_name |
| Run | cargo run |
| Build | cargo build |
| Quick check | cargo check |
| Add dependency | cargo add crate_name |
| Format code | cargo fmt |
| Lint code | cargo clippy |
| Run tests | cargo test |
Source Code
The Rust tutorial project is on GitHub:
Related Tutorials
- Rust Tutorial #1: Why Learn Rust — why Rust matters
- Cursor vs Claude Code vs Copilot — AI tools that help you learn Rust faster
What’s Next?
In the next tutorial, we will learn about variables, types, and functions — the building blocks of every Rust program. You will learn about let, mut, type inference, and how functions work differently in Rust.