Getting Started: Cargo and the Toolchain

Rust's tooling is one of its quiet superpowers — a single tool, Cargo, handles building, dependencies, testing, and more, and it's good enough that Rust developers rarely think about build systems at all. Before the language's hard ideas, meet the tooling that makes working in Rust pleasant.

Before ownership and borrowing, let’s get productive: the Rust toolchain and its centerpiece, Cargo. Rust is famous for a steep language learning curve, but its tooling curve is the opposite — Cargo is widely considered one of the best build-and-package tools in any language, and it removes a whole category of friction. This post covers the toolchain, Cargo, and your first project, so the rest of the series has a foundation to run on.

The toolchain: rustup, rustc, cargo

Rust’s toolchain has a few pieces, and you mostly interact with just one:

The practical takeaway: install with rustup, then live in cargo. You almost never invoke rustc directly — Cargo is the interface to building and managing Rust projects, and it’s designed so that the common tasks are single commands.

Cargo: one tool for everything

Cargo is Rust’s build system and package manager combined, and its integration is what makes Rust tooling so pleasant. In many languages, building, dependency management, and testing are separate tools you assemble; in Rust, Cargo does all of it with a consistent interface:

That one tool covers the entire workflow with a uniform interface is a genuine quality-of-life advantage. You don’t choose and configure a build system, a package manager, a test runner, and a formatter separately — Cargo is all of them, and they work together out of the box. This is part of why Rust, despite its hard language, feels organized to work in.

Your first project

Creating and running a Rust project is three commands:

cargo new hello
cd hello
cargo run

cargo new hello generates a project with this structure:

hello/
├── Cargo.toml     # project manifest: name, version, dependencies
└── src/
    └── main.rs    # the entry point
fn main() {
    println!("Hello, world!");
}

cargo run compiles and runs it, printing Hello, world!. A few things to note in even this tiny program: fn declares a function, main is the entry point (like Go and C), println! is a macro (the ! marks it — Rust distinguishes macros from functions), and statements end with semicolons. We’ll unpack the language from here, but you now have a working project and the loop — edit src/main.rs, run cargo run (or cargo check to just verify it compiles) — that you’ll use throughout.

Crates and the ecosystem

Rust’s package ecosystem is worth knowing early:

So adding a library is: cargo add serde (or edit Cargo.toml), and Cargo handles fetching, version resolution, and building it into your project. The dependency experience is smooth and reproducible — another piece of Rust’s strong tooling story. As you build real Rust, you’ll draw on crates.io’s large ecosystem through this simple mechanism.

Tooling as a foundation

The point of starting here: Rust’s tooling is a genuine strength that makes learning its language more bearable. Cargo gives you one consistent tool for building, running, testing, formatting, linting, and dependency management, with a fast cargo check for the tight edit-compile loop you’ll need as the strict compiler (from the last post) pushes back on your code. So while the language ahead is demanding, the environment around it is smooth — you’ll spend your energy on ownership and borrowing, not on fighting a build system. With a working project and the Cargo workflow in hand, the next post starts the language itself: variables, types, and Rust’s immutability-by-default stance.

Key takeaways

Further reading

Sources & References

Cargo, Rust's build tool