0.8Compiling your first program
Toolchain installed, editor ready. In this lesson you create a project, compile it, and run it: the full loop you'll repeat thousands of times from here on, presented once in slow motion.
By ancient tradition, a programmer's first program prints "Hello, world!" onto the screen. The tradition goes back to the 1970s, it spans every language, and skipping it is widely considered bad luck. We don't make the rules.
A home for your projects
First, decide where your projects will live. We suggest a folder named projects in your home directory. Per the warning in lesson 0.9, make it somewhere no cloud-sync service watches (on many Windows and Mac machines, Desktop and Documents are synced; a plain home-directory folder isn't).
Open a terminal and run:
mkdir projects
cd projectsTip
If the terminal is new territory: it's a place to type commands at your computer, and for this course you need embarrassingly few of them. cd somewhere moves you into a folder, cd .. backs out of one, and ls (Windows: dir) lists what's in the current one. That, plus the cargo commands you're about to learn, covers the entire course.
cargo new
Now ask Cargo to create a project named hello_world:
cargo new hello_world Creating binary (application) `hello_world` package
note: see more `Cargo.toml` keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
(Project names are lowercase with underscores between words, by convention: hello_world, not HelloWorld.)
Cargo has built a little nest of files:
hello_world/
├── Cargo.toml
└── src/
└── main.rs
(It also tucked in a .gitignore file and a hidden .git folder: version control, a professional habit Cargo assumes by default. They're harmless and ignorable until you want them; more on that in a later chapter.)
Cargo.toml is the project's paperwork: its name, version, and eventually its dependencies, in a plain-text format called TOML.
[package]
name = "hello_world"
version = "0.1.0"
edition = "2024"
[dependencies]
You'll recognize the edition line as the one lesson 0.12 explains. The empty [dependencies] section is where crates from crates.io will go, starting in chapter 7.
The real cargo (sorry) is src/main.rs: your program's source code. Cargo starts every new project with the same one:
fn main() {
println!("Hello, world!");
}
What do fn, the exclamation mark, and the braces mean? We're not telling you yet. That's the opening lesson of chapter 1, where this program gets taken apart word by word. Today is strictly about proving your plumbing works end to end. (It also means that for one shining moment, you have a program you haven't had a chance to break.)
cargo run
Move into the project and run it:
cd hello_world
cargo run Compiling hello_world v0.1.0 (/Users/you/projects/hello_world)
Finished `dev` profile [unoptimized + debuginfo] target(s) in 2.56s
Running `target/debug/hello_world`
Hello, world!
Take the lines one at a time. Compiling is Cargo invoking rustc on your source code: the checking-then-translating from lesson 0.5. Finished reports that a dev profile build completed (dev as in development; that's a build configuration, explained in 0.10). Running shows the executable being started; note the path. And the last line is your program itself, alive and talking.
It's worth pausing on what just happened: text you could read became machine code your CPU could execute, and then it executed. The output on your screen was produced by a program that did not exist a minute ago.
Run it again:
cargo run Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.00s
Running `target/debug/hello_world`
Hello, world!
No Compiling line this time. Cargo noticed nothing in your source had changed and skipped straight to running the executable it already built. You get the rebuild only when you've edited something; Cargo keeps track so you don't have to.
cargo build, and where the executable lives
cargo run is really two steps, and you can do the first alone:
cargo build
This compiles (if needed) but doesn't run. The executable sits at target/debug/hello_world (hello_world.exe on Windows). The target folder is Cargo's workshop, where the program and all the intermediate build files live. You can run the executable directly, like any other program:
./target/debug/hello_worldHello, world!
No Cargo lines this time: that's the program itself, with no scaffolding around it. The file is yours: copy it, rename it, send it to a friend with the same kind of computer, and it prints its line without Rust installed anywhere in sight. (Why the path says debug, and what the alternative is, is precisely lesson 0.10's business.)
In day-to-day work, though, cargo run is the muscle-memory command: it builds when needed and runs, in one keystroke of history-recall.
Q: What if it didn't work?
If the compile failed, the overwhelmingly likely cause this early is a typo, and the compiler's error message will point at it with surprising precision. For instance, here's what typing println without its ! gets you:
error[E0423]: expected function, found macro `println`
--> src/main.rs:2:5
|
2 | println("Hello, world!");
| ^^^^^^^ not a function
|
help: use `!` to invoke the macro
|
2 | println!("Hello, world!");
| +
The help: section is the fix, written out for you. Reading these messages properly is a skill we build deliberately in chapter 1; this early, just know the answer is usually printed right there. (If you pasted code from somewhere and the quotes turned curly, that's the word-processor trap from lesson 0.7.) For anything stranger, 0.9 is the checklist.
If Hello, world! appeared: congratulations, sincerely. You've set up a development environment and shipped your first build. By volume of new tools and concepts, that was the steepest lesson in the course; from here, we mostly build on what's now installed.
The rest of this chapter is short lessons that round out what you've just seen: a reference for common problems, build configurations, the compiler's warning system, and editions. You've now met all the machinery they describe.