Setting Up Rust
Install Rust with rustup, configure your editor, and write your first program.
Installing Rust with rustup
The official and recommended way to install Rust is through rustup, a toolchain manager that handles installation, updates, and switching between stable/beta/nightly channels. Installing via rustup is strongly preferred over OS package managers — it gives you the latest stable release and makes updating trivially easy, while system packages often lag months behind.
Linux / macOS
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
Follow the prompts and choose the default installation. Then reload your shell so the cargo and rustc binaries are on your PATH:
source ~/.cargo/env
Windows
Download and run rustup-init.exe from https://rustup.rs. The installer also prompts you to install the MSVC C++ build tools, which are required on Windows because the Rust compiler links against the system C runtime.
Verify the Installation
After installation, confirm all three tools are available and check their versions:
rustc --version # rustc 1.78.0 (9b00956e5 2024-04-29)
cargo --version # cargo 1.78.0 (54d8815d0 2024-03-26)
rustup --version # rustup 1.27.0 (bbb9276d2 2024-03-08)
Understanding the Toolchain
Rust ships as an integrated toolchain where each component has a specific role. Understanding what each tool does will save you confusion as your projects grow.
rustup — manages Rust versions (like nvm for Node)
rustc — the Rust compiler
cargo — build system + package manager + test runner
rustfmt — code formatter (cargo fmt)
clippy — linter (cargo clippy)
rust-docs — offline docs (rustup doc)
Keeping Rust Up to Date
Rust follows a six-week release cycle. Updating takes one command:
rustup update # update all installed toolchains
rustup update stable # update only stable
Installing Nightly (optional)
Some features (like certain proc-macro APIs or experimental syntax) require nightly. You can install it alongside stable and use it only in specific directories:
rustup toolchain install nightly
rustup override set nightly # use nightly in current directory only
Setting Up VS Code
A good editor setup pays dividends immediately — real-time error feedback from rust-analyzer catches mistakes before you run cargo build, which speeds up the learning loop significantly.
- Install VS Code
- Install the rust-analyzer extension (extension id:
rust-lang.rust-analyzer) - Optionally install Even Better TOML for
Cargo.tomlsupport - Optionally install CodeLLDB for a native debugger
rust-analyzer provides:
- Real-time error highlighting
- Auto-complete and signature help
- Go-to-definition and find-references
- Inline type hints
- Automatic imports
A minimal VS Code settings.json for Rust that runs Clippy on save and enables helpful inlay hints:
{
"rust-analyzer.checkOnSave.command": "clippy",
"rust-analyzer.inlayHints.parameterHints.enable": true,
"rust-analyzer.inlayHints.typeHints.enable": true,
"[rust]": {
"editor.formatOnSave": true,
"editor.defaultFormatter": "rust-lang.rust-analyzer"
}
}
Creating Your First Project with Cargo
Cargo is not just a build tool — it is the central hub of the Rust development experience. Every Rust project is a Cargo project. It handles dependencies, compilation, testing, documentation, and publishing to crates.io.
cargo new hello_rust
cd hello_rust
Cargo generates a ready-to-use project structure:
hello_rust/
├── Cargo.toml # project manifest — name, version, dependencies
└── src/
└── main.rs # entry point — where execution begins
Cargo.toml — the project manifest. This is where you declare your package metadata and dependencies:
[package]
name = "hello_rust"
version = "0.1.0"
edition = "2021"
[dependencies]
src/main.rs — the generated starter code:
fn main() {
println!("Hello, world!");
}
Building and Running
Cargo provides a handful of commands you will use constantly. The distinction between debug and release builds matters — debug builds compile fast but include no optimisations, while release builds are slower to compile but produce fast, production-ready binaries.
cargo run # compile + run (debug build) — fastest compile time
cargo build # compile only (debug)
cargo build --release # optimised release build — always benchmark with this
cargo check # type-check without producing a binary (fastest feedback)
Always benchmark and profile with --release — debug binaries can be 10-100x slower for compute-heavy code.
A Slightly More Interesting First Program
This example reads your name from stdin and greets you. It introduces a few real concepts: user input, shadowing, and the format! macro. Replace src/main.rs with:
use std::io::{self, Write};
// Returns a formatted greeting string — note the &str parameter type
fn greet(name: &str) -> String {
format!("Hello, {}! Welcome to Rust.", name)
}
fn main() {
print!("Enter your name: ");
io::stdout().flush().unwrap(); // flush so prompt appears before we wait
let mut name = String::new();
io::stdin().read_line(&mut name).unwrap(); // read into a mutable String
let name = name.trim(); // shadow with trimmed version — drops leading/trailing whitespace
println!("{}", greet(name));
}
cargo run
# Enter your name: Alice
# Hello, Alice! Welcome to Rust.
Adding Dependencies
One of Cargo’s biggest strengths is how easy it is to add third-party libraries. Dependencies are declared in Cargo.toml and downloaded automatically from crates.io on the next build.
[dependencies]
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
Or use the cargo add command directly from the terminal — it updates Cargo.toml for you:
cargo add serde --features derive
cargo add serde_json
Then run cargo build to fetch and compile them. Cargo.lock records the exact resolved versions so builds are reproducible across machines.
Useful Cargo Commands
These commands cover the full day-to-day development cycle. Becoming fluent with them will make you significantly more productive.
cargo test # run all tests
cargo doc --open # build and open documentation
cargo fmt # format all source files
cargo clippy # run the linter — catches common mistakes
cargo clean # remove build artifacts
cargo tree # show dependency tree
cargo update # update dependencies within semver bounds
Offline Documentation
One underappreciated feature of the Rust toolchain is that the entire documentation set is available offline after installation. No internet required, and the docs are always in sync with your installed version.
rustup doc # open the Rust book, std library docs, etc.
rustup doc --std # open standard library docs only
rustup doc --book # open The Rust Programming Language book
Project Structure for Larger Projects
As projects grow, Cargo supports a conventional layout for tests, benchmarks, and examples. Knowing this structure upfront helps you organise code from the start.
my_project/
├── Cargo.toml
├── Cargo.lock # committed for binaries, gitignored for libraries
├── src/
│ ├── main.rs # binary entry point
│ ├── lib.rs # library root (optional)
│ └── modules/
│ └── mod.rs
├── tests/
│ └── integration_test.rs
├── benches/
│ └── my_bench.rs
└── examples/
└── demo.rs
Run a specific example:
cargo run --example demo
You are now ready to write Rust. The next tutorial covers variables, mutability, and constants.