mirror of
https://github.com/rust-lang/book.git
synced 2026-06-12 14:50:45 -04:00
Merge pull request #1175 from rust-lang/introduction
Introduction/Chapter 1 edits
This commit is contained in:
@@ -1,169 +1,51 @@
|
||||
|
||||
[TOC]
|
||||
|
||||
# Introduction
|
||||
# Getting Started
|
||||
|
||||
Welcome to “The Rust Programming Language,” an introductory book about Rust.
|
||||
<!-- If you want to use this paragraph in the Introduction, can you replace it
|
||||
with some other introductory text for the chapter here? Maybe just lay out
|
||||
what's in this chapter so they know it's important not to skip it. -->
|
||||
<!-- Yep, done! /Carol -->
|
||||
|
||||
Rust is a programming language that helps you write faster, more reliable
|
||||
software. High-level ergonomics and low-level control are often at odds with
|
||||
each other in programming language design; Rust stands to challenge that.
|
||||
Through balancing powerful technical capacity and a great developer experience,
|
||||
Rust gives you the option to control low-level details (such as memory usage)
|
||||
without all the hassle traditionally associated with such control.
|
||||
Let’s get your Rust journey started! In this chapter, we’ll discuss:
|
||||
|
||||
## Who Rust is For
|
||||
|
||||
Rust is great for many people for a variety of reasons. Let’s discuss a few of
|
||||
the most important groups.
|
||||
|
||||
### Teams of Developers
|
||||
|
||||
Rust is proving to be a productive tool for collaborating among large teams of
|
||||
developers with varying levels of systems programming knowledge. Low-level code
|
||||
is prone to a variety of subtle bugs, which in most other languages can only be
|
||||
caught through extensive testing and careful code review by experienced
|
||||
developers. In Rust, the compiler plays a gatekeeper role by refusing to
|
||||
compile code with these kinds of bugs--including concurrency bugs. By working
|
||||
alongside the compiler, the team can spend more time focusing on the logic of
|
||||
the program rather than chasing down bugs.
|
||||
|
||||
Rust also brings contemporary developer tools to the systems programming world:
|
||||
|
||||
* Cargo, the included dependency manager and build tool, makes adding,
|
||||
compiling, and managing dependencies painless and consistent across the Rust
|
||||
ecosystem.
|
||||
* Rustfmt ensures a consistent coding style across developers.
|
||||
* The Rust Language Server powers IDE integration for code completion and
|
||||
inline error messages.
|
||||
|
||||
By using these and other tools in the Rust ecosystem, developers can be
|
||||
productive while writing systems-level code.
|
||||
|
||||
### Students
|
||||
|
||||
Rust is for students and people who are interested in learning about systems
|
||||
concepts. Many people have learned about topics like operating systems
|
||||
development through Rust. The community is happy to answer student questions.
|
||||
Through efforts such as this book, the Rust teams want to make systems concepts
|
||||
more accessible to more people, especially those getting started with
|
||||
programming.
|
||||
|
||||
### Companies
|
||||
|
||||
Rust is used in production by hundreds of companies, large and small, for a
|
||||
variety of tasks, such as command line tools, web services, DevOps tooling,
|
||||
embedded devices, audio and video analysis and transcoding, cryptocurrencies,
|
||||
bioinformatics, search engines, internet of things applications, machine
|
||||
learning, and even major parts of the Firefox web browser.
|
||||
|
||||
### Open Source Developers
|
||||
|
||||
Rust is for people who want to build the Rust programming language, community,
|
||||
developer tools, and libraries. We’d love for you to contribute to the Rust
|
||||
language.
|
||||
|
||||
### People Who Value Speed and Stability
|
||||
|
||||
By speed, we mean both the speed of the programs that Rust lets you create and
|
||||
the speed at which Rust lets you write them. The Rust compiler’s checks ensure
|
||||
stability through feature additions and refactoring, as opposed to brittle
|
||||
legacy code in languages without these checks that developers are afraid to
|
||||
modify. By striving for zero-cost abstractions, higher level features that
|
||||
compile to lower level code as fast as code written manually, Rust endeavors to
|
||||
make safe code be fast code as well.
|
||||
|
||||
This isn’t a complete list of everyone the Rust language hopes to support, but
|
||||
these are some of the biggest stakeholders. Overall, Rust’s greatest ambition
|
||||
is to take trade-offs that have been accepted by programmers for decades and
|
||||
eliminate the dichotomy. Safety *and* productivity. Speed *and* ergonomics.
|
||||
Give Rust a try, and see if its choices work for you.
|
||||
|
||||
## Who This Book is For
|
||||
|
||||
This book assumes that you’ve written code in some other programming language,
|
||||
but doesn’t make any assumptions about which one. We’ve tried to make the
|
||||
material broadly accessible to those from a wide variety of programming
|
||||
backgrounds. We don’t spend a lot of time talking about what programming *is*
|
||||
or how to think about it; someone new to programming entirely would be better
|
||||
served by reading a book specifically providing an introduction to programming.
|
||||
|
||||
## How to Use This Book
|
||||
|
||||
This book generally assumes that you’re reading it front-to-back, that is,
|
||||
later chapters build on top of concepts in earlier chapters, and earlier
|
||||
chapters may not dig into details on a topic, revisiting the topic in a later
|
||||
chapter.
|
||||
|
||||
There are two kinds of chapters in this book: concept chapters, and project
|
||||
chapters. In concept chapters, you’ll learn about an aspect of Rust. In the
|
||||
project chapters, we’ll build small programs together, applying what we’ve
|
||||
learned so far. Chapters 2, 12, and 20 are project chapters; the rest are
|
||||
concept chapters.
|
||||
|
||||
Additionally, Chapter 2 is a hands-on introduction to Rust as a language. We’ll
|
||||
cover concepts at a high level, and later chapters will go into them in detail.
|
||||
If you’re the kind of person who likes to get their hands dirty right away,
|
||||
Chapter 2 is great for that. If you’re *really* that kind of person, you may
|
||||
even wish to skip over Chapter 3, which covers features that are very similar
|
||||
to other programming languages, and go straight to Chapter 4 to learn about
|
||||
Rust’s ownership system. By contrast, if you’re a particularly meticulous
|
||||
learner who prefers to learn every detail before moving onto the next, you may
|
||||
want to skip Chapter 2 and go straight to Chapter 3.
|
||||
|
||||
In the end, there’s no wrong way to read a book: if you want to skip ahead, go
|
||||
for it! You may have to jump back if you find things confusing. Do whatever
|
||||
works for you.
|
||||
|
||||
An important part of the process of learning Rust is learning how to read the
|
||||
error messages that the compiler gives you. As such, we’ll be showing a lot of
|
||||
code that doesn’t compile, and the error message the compiler will show you in
|
||||
that situation. As such, if you pick a random example, it may not compile!
|
||||
Please read the surrounding text to make sure that you didn’t happen to pick
|
||||
one of the in-progress examples.
|
||||
|
||||
Finally, there are some appendices. These contain useful information about the
|
||||
language in a more reference-like format.
|
||||
|
||||
## Contributing to the Book
|
||||
|
||||
This book is open source. If you find an error, please don’t hesitate to file
|
||||
an issue or send a pull request on GitHub at
|
||||
*https://github.com/rust-lang/book*. Please see CONTRIBUTING.md at
|
||||
*https://github.com/rust-lang/book/blob/master/CONTRIBUTING.md* for more
|
||||
details.
|
||||
- Installing Rust on Linux, Mac, or Windows
|
||||
- Writing a program that prints “Hello, world!”
|
||||
- Using `cargo`, Rust’s package manager and build system
|
||||
|
||||
## Installation
|
||||
|
||||
The first step to using Rust is to install it. You’ll need an internet
|
||||
connection to run the commands in this chapter, as we’ll be downloading Rust
|
||||
from the internet. We’ll actually be installing Rust using `rustup`, a
|
||||
command-line tool for managing Rust versions and associated tools.
|
||||
The first step to using Rust is to install it. We’ll download Rust through
|
||||
`rustup`, a command-line tool for managing Rust versions and associated tools.
|
||||
For this you’ll need an internet connection.
|
||||
|
||||
The following steps will install the latest stable version of the Rust
|
||||
compiler. The examples and output shown in this book used stable Rust 1.21.0.
|
||||
Due to Rust’s stability guarantees, which we’ll discuss further in the “How
|
||||
Rust is Made” section later in this chapter, all of the examples that compile
|
||||
will continue to compile with newer versions of Rust. The output may differ
|
||||
slightly as error messages and warnings are often improved. In other words, the
|
||||
newer, stable version of Rust you will install with these steps should work as
|
||||
expected with the content of this book.
|
||||
compiler. The examples and output shown in this book all use stable Rust
|
||||
1.21.0. Rust’s stability guarantees ensure that all of the examples in the book
|
||||
that compile will continue to compile with newer versions of Rust. The output
|
||||
may differ slightly between versions, as error messages and warnings are often
|
||||
improved. In other words, any newer, stable version of Rust you will install
|
||||
with these steps should work as expected with the content of this book.
|
||||
|
||||
<!-- PROD: Start Box -->
|
||||
|
||||
> #### Command Line Notation
|
||||
>
|
||||
> We’ll be showing off a number of commands using a terminal, and those lines
|
||||
> all start with `$`. You don’t need to type in the `$` character; they are
|
||||
> there to indicate the start of each command. You’ll see many tutorials and
|
||||
> examples around the web that follow this convention: `$` for commands run as
|
||||
> a regular user, and `#` for commands you should be running as an
|
||||
> administrator. Lines that don’t start with `$` are typically showing the
|
||||
> output of the previous command. Additionally, PowerShell specific examples
|
||||
> will use `>` rather than `$`.
|
||||
> In this chapter and throughout the book we’ll be showing some commands used
|
||||
> in the terminal. Lines that should be entered in a terminal all start with
|
||||
> `$`. You don’t need to type in the `$` character, it is simply there to
|
||||
> indicate the start of each command. Many tutorials use this convention: `$`
|
||||
> for commands run as a regular user, and `#` for commands you should be
|
||||
> running as an administrator. Lines that don’t start with `$` are typically
|
||||
> showing the output of the previous command. Additionally, PowerShell specific
|
||||
> examples will use `>` rather than `$`.
|
||||
|
||||
<!-- PROD: End box -->
|
||||
|
||||
### Installing Rustup on Linux or Mac
|
||||
|
||||
If you’re on Linux or a Mac, 99% of what you need to do is open a terminal and
|
||||
type this:
|
||||
If you’re on Linux or a Mac, open a terminal and enter the following command:
|
||||
|
||||
```
|
||||
$ curl https://sh.rustup.rs -sSf | sh
|
||||
@@ -181,38 +63,43 @@ Of course, if you distrust using `curl URL | sh` to install software, you can
|
||||
download, inspect, and run the script however you like.
|
||||
|
||||
The installation script automatically adds Rust to your system PATH after your
|
||||
next login. If you want to start using Rust right away, run the following
|
||||
command in your shell:
|
||||
next login. If you want to start using Rust right away instead of restarting
|
||||
your terminal, run the following command in your shell to add Rust to your
|
||||
system PATH manually:
|
||||
|
||||
<!-- what does this command do? Do you mean instead of logging out and logging
|
||||
in, enter the following? -->
|
||||
<!-- It runs a script that adds Rust to your system PATH manually. I've
|
||||
clarified that yes, this is instead of logging out and back in to your
|
||||
terminal. /Carol -->
|
||||
|
||||
```
|
||||
$ source $HOME/.cargo/env
|
||||
```
|
||||
|
||||
Alternatively, add the following line to your `~/.bash_profile`:
|
||||
Alternatively, you can add the following line to your `~/.bash_profile`:
|
||||
|
||||
```
|
||||
$ export PATH="$HOME/.cargo/bin:$PATH"
|
||||
```
|
||||
|
||||
Finally, you’ll need a linker of some kind. You likely have one installed. If
|
||||
not, when you compile a Rust program, you’ll get errors that a linker could not
|
||||
be executed. Check your platform’s documentation for how to install a C
|
||||
compiler; they usually come with the correct linker as well, given that C needs
|
||||
one. You may want to install a C compiler regardless of your need for only a
|
||||
linker; some common Rust packages depend on C code and will need a C compiler
|
||||
too.
|
||||
Finally, you’ll need a linker of some kind. It’s likely you already have one
|
||||
installed, but if you try to compile a Rust program and get errors telling you
|
||||
that a linker could not be executed, you’ll need to install one. You can
|
||||
install a C compiler, as that will usually come with the correct linker. Check
|
||||
your platform’s documentation for how to install a C compiler. Some common Rust
|
||||
packages depend on C code and will need a C compiler too, so it may be worth
|
||||
installing one now regardless.
|
||||
|
||||
### Installing Rustup on Windows
|
||||
|
||||
On Windows, go to https://www.rust-lang.org/en-US/install.html at
|
||||
*https://www.rust-lang.org/en-US/install.html* and follow the instructions.
|
||||
You’ll also need the C++ build tools for Visual Studio 2013 or later. The
|
||||
easiest way to acquire the build tools is by installing Build Tools for Visual
|
||||
Studio 2017 at *https://www.visualstudio.com/downloads/* which provides only
|
||||
the Visual C++ build tools. Alternately, you can install at
|
||||
*https://www.visualstudio.com/downloads/* Visual Studio 2017, Visual Studio
|
||||
2015, or Visual Studio 2013 and during installation select the desktop
|
||||
development with C++ workload.
|
||||
On Windows, go to *https://www.rust-lang.org/en-US/install.html* and follow the
|
||||
instructions for installing Rust. At some point in the installation you’ll
|
||||
receive a message telling you you’ll also need the C++ build tools for Visual
|
||||
Studio 2013 or later. The easiest way to acquire the build tools is to install
|
||||
Build Tools for Visual Studio 2017 at
|
||||
*https://www.visualstudio.com/downloads/*, found in the Other Tools and
|
||||
Frameworks section.
|
||||
|
||||
The rest of this book will use commands that work in both `cmd.exe` and
|
||||
PowerShell. If there are specific differences, we’ll explain which to use.
|
||||
@@ -222,7 +109,7 @@ PowerShell. If there are specific differences, we’ll explain which to use.
|
||||
If you have reasons for preferring not to use `rustup`, please see the Rust
|
||||
installation page at *https://www.rust-lang.org/install.html* for other options.
|
||||
|
||||
### Updating
|
||||
### Updating and Uninstalling
|
||||
|
||||
Once you have Rust installed via `rustup`, updating to the latest version is
|
||||
easy. From your shell, run the update script:
|
||||
@@ -231,10 +118,7 @@ easy. From your shell, run the update script:
|
||||
$ rustup update
|
||||
```
|
||||
|
||||
### Uninstalling
|
||||
|
||||
Uninstalling Rust and Rustup is as easy as installing them. From your shell,
|
||||
run the uninstall script:
|
||||
To uninstall Rust and `rustup`, from your shell, run the uninstall script:
|
||||
|
||||
```
|
||||
$ rustup self uninstall
|
||||
@@ -242,14 +126,14 @@ $ rustup self uninstall
|
||||
|
||||
### Troubleshooting
|
||||
|
||||
To check that you have Rust installed, you can open up a shell and type this:
|
||||
To check whether you have Rust installed correctly, open up a shell and enter:
|
||||
|
||||
```
|
||||
$ rustc --version
|
||||
```
|
||||
|
||||
You should see the version number, commit hash, and commit date in a format
|
||||
similar to this for the latest stable version at the time you install:
|
||||
You should see the version number, commit hash, and commit date for the latest
|
||||
stable version at the time you install in the following format:
|
||||
|
||||
```
|
||||
rustc x.y.z (abcabcabc yyyy-mm-dd)
|
||||
@@ -260,9 +144,9 @@ If you see this, Rust has been installed successfully! Congrats!
|
||||
If you don’t and you’re on Windows, check that Rust is in your `%PATH%` system
|
||||
variable.
|
||||
|
||||
If it still isn’t working, there are a number of places where you can get help.
|
||||
The easiest is the #rust IRC channel on irc.mozilla.org, which you can access
|
||||
through Mibbit at
|
||||
If that’s all correct and Rust still isn’t working, there are a number of
|
||||
places you can get help. The easiest is the #rust IRC channel on
|
||||
irc.mozilla.org, which you can access through Mibbit at
|
||||
*http://chat.mibbit.com/?server=irc.mozilla.org&channel=%23rust*. Go to that
|
||||
address, and you’ll be chatting with other Rustaceans (a silly nickname we call
|
||||
ourselves) who can help you out. Other great resources include the Users forum
|
||||
@@ -283,8 +167,7 @@ Interface) documentation to find out!
|
||||
|
||||
Now that you have Rust installed, let’s write your first Rust program. It’s
|
||||
traditional when learning a new language to write a little program to print the
|
||||
text “Hello, world!” to the screen, and in this section, we’ll follow that
|
||||
tradition.
|
||||
text “Hello, world!” to the screen, so we’ll do the same here!
|
||||
|
||||
> Note: This book assumes basic familiarity with the command line. Rust itself
|
||||
> makes no specific demands about your editing, tooling, or where your code
|
||||
@@ -297,10 +180,12 @@ tradition.
|
||||
### Creating a Project Directory
|
||||
|
||||
First, make a directory to put your Rust code in. Rust doesn’t care where your
|
||||
code lives, but for this book, we’d suggest making a *projects* directory in
|
||||
your home directory and keeping all your projects there. Open a terminal and
|
||||
enter the following commands to make a *projects* directory and a directory
|
||||
inside that for the “Hello, world!” project:
|
||||
code lives, but for the exercises and projects in this book, we’d suggest
|
||||
making a *projects* directory in your home directory and keeping all your
|
||||
projects there.
|
||||
|
||||
Open a terminal and enter the following commands to make a *projects* directory
|
||||
and, inside that, a directory for this “Hello, world!” project:
|
||||
|
||||
Linux and Mac:
|
||||
|
||||
@@ -331,7 +216,7 @@ Windows PowerShell:
|
||||
|
||||
### Writing and Running a Rust Program
|
||||
|
||||
Next, make a new source file and call it *main.rs*. Rust files always end with
|
||||
Next, make a new source file and call it *main.rs*---Rust files always end with
|
||||
the *.rs* extension. If you’re using more than one word in your filename, use
|
||||
an underscore to separate them. For example, you’d use *hello_world.rs* rather
|
||||
than *helloworld.rs*.
|
||||
@@ -350,7 +235,7 @@ fn main() {
|
||||
Listing 1-1: A program that prints “Hello, world!”
|
||||
|
||||
Save the file, and go back to your terminal window. On Linux or macOS, enter
|
||||
the following commands:
|
||||
the following commands to compile and run the file:
|
||||
|
||||
```
|
||||
$ rustc main.rs
|
||||
@@ -367,9 +252,17 @@ Hello, world!
|
||||
```
|
||||
|
||||
Regardless of your operating system, you should see the string `Hello, world!`
|
||||
print to the terminal. If you did, then congratulations! You’ve officially
|
||||
print to the terminal. If you don’t see this output, see the “Troubleshooting”
|
||||
section earlier for ways to get help.
|
||||
|
||||
If you did see `Hello, world!` printed, then congratulations! You’ve officially
|
||||
written a Rust program. That makes you a Rust programmer! Welcome!
|
||||
|
||||
<!-- Any quick words of advice for if they didn't? (Disclosure: I tried
|
||||
following this using Bash on windows and couldn't get it working) -->
|
||||
<!-- Added a pointer to the previous troubleshooting section which also applies
|
||||
here /Carol -->
|
||||
|
||||
### Anatomy of a Rust Program
|
||||
|
||||
Now, let’s go over what just happened in your “Hello, world!” program in
|
||||
@@ -381,14 +274,15 @@ fn main() {
|
||||
}
|
||||
```
|
||||
|
||||
These lines define a *function* in Rust. The `main` function is special: it’s
|
||||
the first code that is run for every executable Rust program. The first line
|
||||
declares a function named `main` that has no parameters and returns nothing. If
|
||||
there were parameters, their names would go inside the parentheses, `(` and `)`.
|
||||
These lines define a *function* in Rust. The `main` function is special: it is
|
||||
always the first code that is run for every executable Rust program. The first
|
||||
line declares a function named `main` that has no parameters and returns
|
||||
nothing. If there were parameters, their names would go inside the parentheses,
|
||||
`(` and `)`.
|
||||
|
||||
Also note that the function body is wrapped in curly brackets, `{` and `}`.
|
||||
Rust requires these around all function bodies. It’s considered good style to
|
||||
put the opening curly bracket on the same line as the function declaration,
|
||||
place the opening curly bracket on the same line as the function declaration,
|
||||
with one space in between.
|
||||
|
||||
> At the time of writing, an automatic formatter, `rustfmt`, is under
|
||||
@@ -408,46 +302,35 @@ This line does all of the work in this little program: it prints text to the
|
||||
screen. There are a number of details to notice here. The first is that Rust
|
||||
style is to indent with four spaces, not a tab.
|
||||
|
||||
The second important part is `println!`. This is calling a Rust *macro*, which
|
||||
is how metaprogramming is done in Rust. If it were calling a function instead,
|
||||
it would look like this: `println` (without the `!`). We’ll discuss Rust macros
|
||||
in more detail in Appendix D, but for now you just need to know that when you
|
||||
see a `!` that means that you’re calling a macro instead of a normal function.
|
||||
The second important detail is the `println!` call. This code is calling a Rust
|
||||
*macro*. If it were calling a function instead, it would be entered as
|
||||
`println` (without the `!`). We’ll discuss Rust macros in more detail in
|
||||
Appendix D, but for now you just need to know that when you see a `!` that
|
||||
means that you’re calling a macro instead of a normal function.
|
||||
|
||||
> ### Why `println!` is a Macro
|
||||
>
|
||||
> There are multiple reasons why `println!` is a macro rather than a function,
|
||||
> and we haven’t really explained Rust yet, so it’s not exactly obvious. Here
|
||||
> are the reasons:
|
||||
>
|
||||
> * The string passed to `println!` can have formatting specifiers in it,
|
||||
> and those are checked at compile-time.
|
||||
> * Rust functions can only have a fixed number of arguments, but `println!`
|
||||
> (and macros generally) can take a variable number.
|
||||
> * The formatting specifiers can have named arguments, which Rust functions
|
||||
> cannot.
|
||||
> * It implicitly takes its arguments by reference even when they’re passed
|
||||
> by value.
|
||||
>
|
||||
> If none of this makes sense, don’t worry about it. We’ll cover these concepts
|
||||
> in more detail later.
|
||||
<!-- I might suggest just cutting this next macro section -- for the sake of
|
||||
the intro, we don't really need this info, and I feel like this first exercise
|
||||
should be short and sweet and simple -->
|
||||
<!-- I'm ok with cutting this; it's a fairly common question that some folks
|
||||
have at this point, but I'm ok with those people having to do some research
|
||||
online if they're curious /Carol -->
|
||||
|
||||
Next is `"Hello, world!"` which is a *string*. We pass this string as an
|
||||
argument to `println!`, which prints the string to the screen. Easy enough!
|
||||
Next comes`"Hello, world!"` which is a *string*. We pass this string as an
|
||||
argument to `println!` and the total effect is that the string is printed to
|
||||
the screen. Easy enough!
|
||||
|
||||
The line ends with a semicolon (`;`). The `;` indicates that this expression is
|
||||
We end the line with a semicolon `;`, which indicates that this expression is
|
||||
over, and the next one is ready to begin. Most lines of Rust code end with a
|
||||
`;`.
|
||||
|
||||
### Compiling and Running Are Separate Steps
|
||||
|
||||
In the “Writing and Running a Rust Program” section on page XX, we showed you
|
||||
how to run a newly created program. We’ll break that process down and examine
|
||||
each step now.
|
||||
You’ve just seen how to run a newly created program, so now let’s break that
|
||||
process down and examine each step.
|
||||
|
||||
Before running a Rust program, you have to compile it. You can use the Rust
|
||||
compiler by entering the `rustc` command and passing it the name of your source
|
||||
file, like this:
|
||||
Before running a Rust program, you have to compile it using the Rust compiler
|
||||
by entering the `rustc` command and passing it the name of your source file,
|
||||
like this:
|
||||
|
||||
```
|
||||
$ rustc main.rs
|
||||
@@ -495,30 +378,29 @@ hand, they need to have a Ruby, Python, or JavaScript implementation installed
|
||||
program. Everything is a tradeoff in language design.
|
||||
|
||||
Just compiling with `rustc` is fine for simple programs, but as your project
|
||||
grows, you’ll want to be able to manage all of the options your project has and
|
||||
make it easy to share your code with other people and projects. Next, we’ll
|
||||
introduce you to a tool called Cargo, which will help you write real-world Rust
|
||||
programs.
|
||||
grows, you’ll want to be able to manage all of the options and make it easy to
|
||||
share your code. Next, we’ll introduce you to a tool called Cargo, which will
|
||||
help you write real-world Rust programs.
|
||||
|
||||
## Hello, Cargo!
|
||||
|
||||
Cargo is Rust’s build system and package manager, and Rustaceans use Cargo to
|
||||
manage their Rust projects because it makes a lot of tasks easier. For example,
|
||||
Cargo takes care of building your code, downloading the libraries your code
|
||||
depends on, and building those libraries. We call libraries your code needs
|
||||
*dependencies*.
|
||||
Cargo is Rust’s build system and package manager. Most Rustaceans will use this
|
||||
tool to manage their Rust projects because Cargo takes care of a lot of tasks
|
||||
for you, such as building your code, downloading the libraries your code
|
||||
depends on, and building those libraries. (We call libraries your code needs
|
||||
*dependencies*.)
|
||||
|
||||
The simplest Rust programs, like the one we’ve written so far, don’t have any
|
||||
dependencies, so right now, you’d only be using the part of Cargo that can take
|
||||
care of building your code. As you write more complex Rust programs, you’ll
|
||||
want to add dependencies, and if you start off using Cargo, that will be a lot
|
||||
easier to do.
|
||||
dependencies, so if we had built the Hello World project with Cargo, it would
|
||||
only be using the part of Cargo that takes care of building your code. As you
|
||||
write more complex Rust programs, you’ll want to add dependencies, and if you
|
||||
start the project off using Cargo, that will be a lot easier to do.
|
||||
|
||||
As the vast, vast majority of Rust projects use Cargo, we will assume that
|
||||
you’re using it for the rest of the book. Cargo comes installed with Rust
|
||||
itself, if you used the official installers as covered in the “Installation”
|
||||
section. If you installed Rust through some other means, you can check if you
|
||||
have Cargo installed by typing the following into your terminal:
|
||||
As the vast majority of Rust projects use Cargo, the rest of this book will
|
||||
assume that you’re using Cargo too. Cargo comes installed with Rust itself, if
|
||||
you used the official installers as covered in the “Installation” section. If
|
||||
you installed Rust through some other means, you can check if you have Cargo
|
||||
installed by entering the following into your terminal:
|
||||
|
||||
```
|
||||
$ cargo --version
|
||||
@@ -531,41 +413,39 @@ installation to determine how to install Cargo separately.
|
||||
### Creating a Project with Cargo
|
||||
|
||||
Let’s create a new project using Cargo and look at how it differs from our
|
||||
project in `hello_world`. Go back to your projects directory (or wherever you
|
||||
decided to put your code):
|
||||
|
||||
Linux, Mac, and PowerShell:
|
||||
|
||||
```
|
||||
$ cd ~/projects
|
||||
```
|
||||
|
||||
CMD for Windows:
|
||||
|
||||
```
|
||||
> cd \d "%USERPROFILE%\projects"
|
||||
```
|
||||
|
||||
And then on any operating system run:
|
||||
original Hello World project. Navigate back to your *projects* directory (or
|
||||
wherever you decided to put your code) and then on any operating system run:
|
||||
|
||||
```
|
||||
$ cargo new hello_cargo --bin
|
||||
$ cd hello_cargo
|
||||
```
|
||||
|
||||
We passed the `--bin` argument to `cargo new` because our goal is to make an
|
||||
executable application, as opposed to a library. Executables are binary
|
||||
executable files often called just *binaries*. We’ve given `hello_cargo` as the
|
||||
name for our project, and Cargo creates its files in a directory of the same
|
||||
name that we can then go into.
|
||||
<!-- Below -- so we always have to start a cargo project with the --bin option
|
||||
if we want it to be something we can execute and not just a library, is that
|
||||
right? It might be worth laying that out -->
|
||||
<!-- As of Rust 1.21.0 (the version we're using for the book), yes, you must
|
||||
always specify `--bin`. In a version of Rust in the near future (1.25 or 1.26),
|
||||
binary crates will become the default kind of crate that `cargo new` makes, so
|
||||
you won't have to specify `--bin` (but you can if you want and the behavior
|
||||
will be the same). We'd rather not go into any more detail than we have here
|
||||
because of this change; I think "The `--bin` argument to passed to `cargo new`
|
||||
makes an executable application (often just called a *binary*), as opposed to a
|
||||
library." lays this out enough. /Carol -->
|
||||
|
||||
If we list the files in the *hello_cargo* directory, we can see that Cargo has
|
||||
generated two files and one directory for us: a *Cargo.toml* and a *src*
|
||||
directory with a *main.rs* file inside. It has also initialized a new git
|
||||
repository in the *hello_cargo* directory for us, along with a *.gitignore*
|
||||
file. Git is a common version control system. You can change `cargo new` to use
|
||||
a different version control system, or no version control system, by using the
|
||||
`--vcs` flag. Run `cargo new --help` to see the available options.
|
||||
This creates a new binary executable called `hello_cargo`. The `--bin` argument
|
||||
to passed to `cargo new` makes an executable application (often just called a
|
||||
*binary*), as opposed to a library. We’ve given `hello_cargo` as the name for
|
||||
our project, and Cargo creates its files in a directory of the same name.
|
||||
|
||||
Go into the *hello_cargo* directory and list the files, and you should see that
|
||||
Cargo has generated two files and one directory for us: a *Cargo.toml* and a
|
||||
*src* directory with a *main.rs* file inside. It has also initialized a new git
|
||||
repository, along with a *.gitignore* file.
|
||||
|
||||
> Note: Git is a common version control system. You can change `cargo new` to
|
||||
> use a different version control system, or no version control system, by
|
||||
> using the `--vcs` flag. Run `cargo new --help` to see the available options.
|
||||
|
||||
Open up *Cargo.toml* in your text editor of choice. It should look similar to
|
||||
the code in Listing 1-2:
|
||||
@@ -583,26 +463,24 @@ authors = ["Your Name <you@example.com>"]
|
||||
|
||||
Listing 1-2: Contents of *Cargo.toml* generated by `cargo new`
|
||||
|
||||
This file is in the *TOML* (Tom’s Obvious, Minimal Language) format. TOML is
|
||||
used as Cargo’s configuration format.
|
||||
This file is in the *TOML* (Tom’s Obvious, Minimal Language) format, which is
|
||||
what Cargo uses as its configuration format.
|
||||
|
||||
The first line, `[package]`, is a section heading that indicates that the
|
||||
following statements are configuring a package. As we add more information to
|
||||
this file, we’ll add other sections.
|
||||
|
||||
The next three lines set the three bits of configuration that Cargo needs to
|
||||
see in order to know that it should compile your program: its name, what
|
||||
version it is, and who wrote it. Cargo gets your name and email information
|
||||
from your environment. If it’s not correct, go ahead and fix that and save the
|
||||
file.
|
||||
The next three lines set the configuration information Cargo needs in order to
|
||||
know that it should compile your program: the name, the version, and who wrote
|
||||
it. Cargo gets your name and email information from your environment, so if
|
||||
that’s not correct, go ahead and fix that and save the file.
|
||||
|
||||
The last line, `[dependencies]`, is the start of a section for you to list any
|
||||
*crates* (which is what we call packages of Rust code) that your project will
|
||||
depend on so that Cargo knows to download and compile those too. We won’t need
|
||||
any other crates for this project, but we will in the guessing game tutorial in
|
||||
Chapter 2.
|
||||
of your project’s dependencies. In Rust, packages of code are referred to as
|
||||
*crates*. We won’t need any other crates for this project, but we will in the
|
||||
first project in Chapter 2, so we’ll use this dependencies section then.
|
||||
|
||||
Now let’s look at *src/main.rs*:
|
||||
Now open up *src/main.rs* and take a look:
|
||||
|
||||
Filename: src/main.rs
|
||||
|
||||
@@ -613,11 +491,9 @@ fn main() {
|
||||
```
|
||||
|
||||
Cargo has generated a “Hello World!” for you, just like the one we wrote in
|
||||
Listing 1-1! So that part is the same. The differences between our previous
|
||||
project and the project generated by Cargo that we’ve seen so far are:
|
||||
|
||||
- Our code goes in the *src* directory
|
||||
- The top level contains a *Cargo.toml* configuration file
|
||||
Listing 1-1! So far, the differences between our previous project and the
|
||||
project generated by Cargo are that with Cargo our code goes in the *src*
|
||||
directory, and we have a *Cargo.toml* configuration file in the top directory.
|
||||
|
||||
Cargo expects your source files to live inside the *src* directory so that the
|
||||
top-level project directory is just for READMEs, license information,
|
||||
@@ -627,13 +503,14 @@ everything, and everything is in its place.
|
||||
|
||||
If you started a project that doesn’t use Cargo, as we did with our project in
|
||||
the *hello_world* directory, you can convert it to a project that does use
|
||||
Cargo by moving your code into the *src* directory and creating an appropriate
|
||||
*Cargo.toml*.
|
||||
Cargo by moving the project code into the *src* directory and creating an
|
||||
appropriate *Cargo.toml*.
|
||||
|
||||
### Building and Running a Cargo Project
|
||||
|
||||
Now let’s look at what’s different about building and running your Hello World
|
||||
program through Cargo! To do so, enter the following commands:
|
||||
program through Cargo! From your project directory, build your project by
|
||||
entering the following commands:
|
||||
|
||||
```
|
||||
$ cargo build
|
||||
@@ -651,16 +528,15 @@ Hello, world!
|
||||
```
|
||||
|
||||
Bam! If all goes well, `Hello, world!` should print to the terminal once more.
|
||||
|
||||
Running `cargo build` for the first time also causes Cargo to create a new file
|
||||
at the top level called *Cargo.lock*. Cargo uses *Cargo.lock* to keep track of
|
||||
the exact versions of dependencies used to build your project. This project
|
||||
doesn’t have dependencies, so the file is a bit sparse. You won’t ever need to
|
||||
touch this file yourself; Cargo will manage its contents for you.
|
||||
at the top level called *Cargo.lock*, which is used to keep track of the exact
|
||||
versions of dependencies in your project. This project doesn’t have
|
||||
dependencies, so the file is a bit sparse. You won’t ever need to touch this
|
||||
file yourself; Cargo will manage its contents for you.
|
||||
|
||||
We just built a project with `cargo build` and ran it with
|
||||
`./target/debug/hello_cargo`, but we can also use `cargo run` to compile and
|
||||
then run:
|
||||
then run all in one go:
|
||||
|
||||
```
|
||||
$ cargo run
|
||||
@@ -672,8 +548,7 @@ Hello, world!
|
||||
Notice that this time, we didn’t see the output telling us that Cargo was
|
||||
compiling `hello_cargo`. Cargo figured out that the files haven’t changed, so
|
||||
it just ran the binary. If you had modified your source code, Cargo would have
|
||||
rebuilt the project before running it, and you would have seen output like
|
||||
this:
|
||||
rebuilt the project before running it, and you would have seen output like this:
|
||||
|
||||
```
|
||||
$ cargo run
|
||||
@@ -683,8 +558,8 @@ $ cargo run
|
||||
Hello, world!
|
||||
```
|
||||
|
||||
Finally, there’s `cargo check`. This will quickly check your code to make sure
|
||||
that it compiles, but not bother producing an executable:
|
||||
Finally, there’s `cargo check`. This command will quickly check your code to
|
||||
make sure that it compiles, but not bother producing an executable:
|
||||
|
||||
```
|
||||
$ cargo check
|
||||
@@ -693,20 +568,20 @@ $ cargo check
|
||||
```
|
||||
|
||||
Why would you not want an executable? `cargo check` is often much faster than
|
||||
`cargo build`, because Cargo can skip the entire step of producing the
|
||||
executable. If we’re checking our work throughout the process of writing the
|
||||
code, this will speed things up! As such, many Rustaceans run `cargo check` as
|
||||
they write their program to make sure that it compiles, and then run `cargo
|
||||
build` once they’re ready to give it a spin themselves.
|
||||
`cargo build`, because it skips the entire step of producing the executable. If
|
||||
you’re checking your work throughout the process of writing the code, using
|
||||
`cargo check` will speed things up! As such, many Rustaceans run `cargo check`
|
||||
periodically as they write their program to make sure that it compiles, and
|
||||
then run `cargo build` once they’re ready to give it a spin themselves.
|
||||
|
||||
So a few more differences we’ve now seen:
|
||||
So to recap, using Cargo:
|
||||
|
||||
- Instead of using `rustc`, build a project using `cargo build` or
|
||||
`cargo check` (or build and run it in one step with `cargo run`).
|
||||
- We can build a project using `cargo build` or `cargo check`
|
||||
- We can build and run the project in one step with `cargo run`
|
||||
- Instead of the result of the build being put in the same directory as our
|
||||
code, Cargo will put it in the *target/debug* directory.
|
||||
|
||||
The other advantage of using Cargo is that the commands are the same no matter
|
||||
A final advantage of using Cargo is that the commands are the same no matter
|
||||
what operating system you’re on, so at this point we will no longer be
|
||||
providing specific instructions for Linux and Mac versus Windows.
|
||||
|
||||
@@ -718,24 +593,22 @@ executable in *target/release* instead of *target/debug*. These optimizations
|
||||
make your Rust code run faster, but turning them on makes your program take
|
||||
longer to compile. This is why there are two different profiles: one for
|
||||
development when you want to be able to rebuild quickly and often, and one for
|
||||
building the final program you’ll give to a user that won’t be rebuilt and that
|
||||
we want to run as fast as possible. If you’re benchmarking the running time of
|
||||
your code, be sure to run `cargo build --release` and benchmark with the
|
||||
executable in *target/release*.
|
||||
building the final program you’ll give to a user that won’t be rebuilt
|
||||
repeatedly and that will run as fast as possible. If you’re benchmarking the
|
||||
running time of your code, be sure to run `cargo build --release` and benchmark
|
||||
with the executable in *target/release*.
|
||||
|
||||
### Cargo as Convention
|
||||
|
||||
With simple projects, Cargo doesn’t provide a whole lot of value over just
|
||||
using `rustc`, but it will prove its worth as you continue. With complex
|
||||
projects composed of multiple crates, it’s much easier to let Cargo coordinate
|
||||
the build. With Cargo, you can just run `cargo build`, and it should work the
|
||||
right way.
|
||||
the build.
|
||||
|
||||
Even though the `hello_cargo` project is simple, it now uses much of the real
|
||||
tooling you’ll use for the rest of your Rust career. In fact, you can get
|
||||
started with virtually all Rust projects you want to work on with the following
|
||||
commands to check out the code using Git, change into the project directory,
|
||||
and build:
|
||||
tooling you’ll use for the rest of your Rust career. In fact, to work on any
|
||||
existing projects you can use the following commands to check out the code
|
||||
using Git, change into the project directory, and build:
|
||||
|
||||
```
|
||||
$ git clone someurl.com/someproject
|
||||
@@ -744,228 +617,27 @@ $ cargo build
|
||||
```
|
||||
|
||||
If you want to look at Cargo in more detail, check out its documentation at
|
||||
*https://doc.rust-lang.org/cargo/*, which covers all of its features.
|
||||
*https://doc.rust-lang.org/cargo/*.
|
||||
|
||||
## How Rust is Made and “Nightly Rust”
|
||||
|
||||
Before we dive into the language itself, we’d like to finish up the
|
||||
introductory chapter by talking about how Rust is made, and how that affects
|
||||
you as a Rust developer. We mentioned in the “Installation” section that the
|
||||
output in this book was generated by stable Rust 1.21.0, but any examples that
|
||||
compile should continue to compile in any stable version of Rust greater than
|
||||
that. This section is to explain how we ensure this is true!
|
||||
|
||||
### Stability Without Stagnation
|
||||
|
||||
As a language, Rust cares a *lot* about the stability of your code. We want
|
||||
Rust to be a rock-solid foundation you can build on, and if things were
|
||||
constantly changing, that would be impossible. At the same time, if we can’t
|
||||
experiment with new features, we may not find out important flaws until after
|
||||
their release, when we can no longer change things.
|
||||
|
||||
Our solution to this problem is what we call “stability without stagnation” and
|
||||
is the way we can change and improve Rust while making sure that using Rust
|
||||
stays nice, stable, and boring.
|
||||
|
||||
Our guiding principle for Rust releases is this: you should never have to fear
|
||||
upgrading to a new version of stable Rust. Each upgrade should be painless. At
|
||||
the same time, the upgrade should bring you new features, fewer bugs, and
|
||||
faster compile times.
|
||||
|
||||
### Choo, Choo! Release Channels and Riding the Trains
|
||||
|
||||
Rust development operates on a *train schedule*. That is, all development is
|
||||
done on the `master` branch of the Rust repository. Releases follow a software
|
||||
release train model, which has been used by Cisco IOS and other software
|
||||
projects. There are three *release channels* for Rust:
|
||||
|
||||
* Nightly
|
||||
* Beta
|
||||
* Stable
|
||||
|
||||
Most Rust developers primarily use the stable channel, but those who want to
|
||||
try out experimental new features may use nightly or beta.
|
||||
|
||||
Here’s an example of how the development and release process works: let’s
|
||||
assume that the Rust team is working on the release of Rust 1.5. That release
|
||||
happened in December of 2015, but it will provide us with realistic version
|
||||
numbers. A new feature is added to Rust: a new commit lands on the `master`
|
||||
branch. Each night, a new nightly version of Rust is produced. Every day is a
|
||||
release day, and these releases are created by our release infrastructure
|
||||
automatically. So as time passes, our releases look like this, once a night:
|
||||
|
||||
```
|
||||
nightly: * - - * - - *
|
||||
```
|
||||
|
||||
Every six weeks, it’s time to prepare a new release! The `beta` branch of the
|
||||
Rust repository branches off from the `master` branch used by nightly. Now,
|
||||
there are two releases:
|
||||
|
||||
```
|
||||
nightly: * - - * - - *
|
||||
|
|
||||
beta: *
|
||||
```
|
||||
|
||||
Most Rust users do not use beta releases actively, but test against beta in
|
||||
their CI system to help Rust discover possible regressions. In the meantime,
|
||||
there’s still a nightly release every night:
|
||||
|
||||
```
|
||||
nightly: * - - * - - * - - * - - *
|
||||
|
|
||||
beta: *
|
||||
```
|
||||
|
||||
Let’s say a regression is found. Good thing we had some time to test the beta
|
||||
release before the regression snuck into a stable release! The fix is applied
|
||||
to `master`, so that nightly is fixed, and then the fix is backported to the
|
||||
`beta` branch, and a new release of beta is produced:
|
||||
|
||||
```
|
||||
nightly: * - - * - - * - - * - - * - - *
|
||||
|
|
||||
beta: * - - - - - - - - *
|
||||
```
|
||||
|
||||
Six weeks after the first beta was created, it’s time for a stable release! The
|
||||
`stable` branch is produced from the `beta` branch:
|
||||
|
||||
```
|
||||
nightly: * - - * - - * - - * - - * - - * - * - *
|
||||
|
|
||||
beta: * - - - - - - - - *
|
||||
|
|
||||
stable: *
|
||||
```
|
||||
|
||||
Hooray! Rust 1.5 is done! However, we’ve forgotten one thing: because the six
|
||||
weeks have gone by, we also need a new beta of the *next* version of Rust, 1.6.
|
||||
So after `stable` branches off of `beta`, the next version of `beta` branches
|
||||
off of `nightly` again:
|
||||
|
||||
```
|
||||
nightly: * - - * - - * - - * - - * - - * - * - *
|
||||
| |
|
||||
beta: * - - - - - - - - * *
|
||||
|
|
||||
stable: *
|
||||
```
|
||||
|
||||
This is called the “train model” because every six weeks, a release “leaves the
|
||||
station”, but still has to take a journey through the beta channel before it
|
||||
arrives as a stable release.
|
||||
|
||||
Rust releases every six weeks, like clockwork. If you know the date of one Rust
|
||||
release, you can know the date of the next one: it’s six weeks later. A nice
|
||||
aspect of having releases scheduled every six weeks is that the next train is
|
||||
coming soon. If a feature happens to miss a particular release, there’s no need
|
||||
to worry: another one is happening in a short time! This helps reduce pressure
|
||||
to sneak possibly unpolished features in close to the release deadline.
|
||||
|
||||
Thanks to this process, you can always check out the next build of Rust and
|
||||
verify for yourself that it’s easy to upgrade to: if a beta release doesn’t
|
||||
work as expected, you can report it to the team and get it fixed before the
|
||||
next stable release happens! Breakage in a beta release is relatively rare, but
|
||||
`rustc` is still a piece of software, and bugs do exist.
|
||||
|
||||
### Unstable Features
|
||||
|
||||
There’s one more catch with this release model: unstable features. Rust uses a
|
||||
technique called “feature flags” to determine what features are enabled in a
|
||||
given release. If a new feature is under active development, it lands on
|
||||
`master`, and therefore, in nightly, but behind a *feature flag*. If you, as a
|
||||
user, wish to try out the work-in-progress feature, you can, but you must be
|
||||
using a nightly release of Rust and annotate your source code with the
|
||||
appropriate flag to opt in.
|
||||
|
||||
If you’re using a beta or stable release of Rust, you can’t use any feature
|
||||
flags. This is the key that allows us to get practical use with new features
|
||||
before we declare them stable forever. Those who wish to opt into the bleeding
|
||||
edge can do so, and those who want a rock-solid experience can stick with
|
||||
stable and know that their code won’t break. Stability without stagnation.
|
||||
|
||||
This book only contains information about stable features, as in-progress
|
||||
features are still changing, and surely they’ll be different between when this
|
||||
book was written and when they get enabled in stable builds. You can find
|
||||
documentation for nightly-only features online.
|
||||
|
||||
### Rustup and the Role of Rust Nightly
|
||||
|
||||
Rustup makes it easy to change between different release channels of Rust, on a
|
||||
global or per-project basis. By default, you’ll have stable Rust installed. To
|
||||
install nightly, for example:
|
||||
|
||||
```
|
||||
$ rustup install nightly
|
||||
```
|
||||
|
||||
You can see all of the *toolchains* (releases of Rust and associated
|
||||
components) you have installed with `rustup` as well. Here’s an example on one
|
||||
of your authors’ computers:
|
||||
|
||||
```
|
||||
> rustup toolchain list
|
||||
stable-x86_64-pc-windows-msvc (default)
|
||||
beta-x86_64-pc-windows-msvc
|
||||
nightly-x86_64-pc-windows-msvc
|
||||
```
|
||||
|
||||
As you can see, the stable toolchain is the default. Most Rust users use stable
|
||||
most of the time. You might want to use stable most of the time, but use
|
||||
nightly on a specific project, because you care about a cutting-edge feature.
|
||||
To do so, you can use `rustup override` in that project’s directory to set the
|
||||
nightly toolchain as the one `rustup` should use when you’re in that directory:
|
||||
|
||||
```
|
||||
$ cd ~/projects/needs-nightly
|
||||
$ rustup override add nightly
|
||||
```
|
||||
|
||||
Now, every time you call `rustc` or `cargo` inside of
|
||||
*~/projects/needs-nightly*, `rustup` will make sure that you are using nightly
|
||||
Rust, rather than your default of stable Rust. This comes in handy when you
|
||||
have a lot of Rust projects!
|
||||
|
||||
### The RFC Process and Teams
|
||||
|
||||
So how do you learn about these new features? Rust’s development model follows
|
||||
a *Request For Comments (RFC) process*. If you’d like an improvement in Rust,
|
||||
you can write up a proposal, called an RFC.
|
||||
|
||||
Anyone can write RFCs to improve Rust, and the proposals are reviewed and
|
||||
discussed by the Rust team, which is comprised of many topic subteams. There’s
|
||||
a full list of the teams on Rust’s
|
||||
website at *https://www.rust-lang.org/en-US/team.html*, which includes teams for
|
||||
each area of the project: language design, compiler implementation,
|
||||
infrastructure, documentation, and more. The appropriate team reads the
|
||||
proposal and the comments, writes some comments of their own, and eventually,
|
||||
there’s consensus to accept or reject the feature.
|
||||
|
||||
If the feature is accepted, an issue is opened on the Rust repository, and
|
||||
someone can implement it. The person who implements it very well may not be the
|
||||
person who proposed the feature in the first place! When the implementation is
|
||||
ready, it lands on the `master` branch behind a feature gate, as we discussed
|
||||
in the “Unstable Features” section.
|
||||
|
||||
After some time, once Rust developers who use nightly releases have been able
|
||||
to try out the new feature, team members will discuss the feature, how it’s
|
||||
worked out on nightly, and decide if it should make it into stable Rust or not.
|
||||
If the decision is to move forward, the feature gate is removed, and the
|
||||
feature is now considered stable! It rides the trains into a new stable release
|
||||
of Rust.
|
||||
<!--Below -- I`m not sure this is the place for this conversation, it seems too
|
||||
deep into the weeds for the "getting started" chapter. I know we discussed
|
||||
Nightly Rust as an appendix previously, but honestly I think this is more
|
||||
suited somewhere online, perhaps in the extended docs. I like the idea of
|
||||
finishing the chapter here, on this practical note, and I think at this point
|
||||
readers will want to get stuck in anyway and may skip this and never come back
|
||||
because it's buried at the end of a chapter that's not really related to it. If
|
||||
it's online somewhere separate they can come to it when they're ready. What do
|
||||
you think?-->
|
||||
<!-- Ok, I can see that. /Carol -->
|
||||
|
||||
## Summary
|
||||
|
||||
You’re already off to a great start on your Rust journey! In this chapter,
|
||||
you’ve:
|
||||
|
||||
* Learned what makes Rust unique
|
||||
* Installed the latest stable version of Rust
|
||||
* Written a “Hello, world!” program using both `rustc` directly and using
|
||||
the conventions of `cargo`
|
||||
* Found out about how Rust is developed
|
||||
|
||||
This is a great time to build a more substantial program, to get used to
|
||||
reading and writing Rust code. In the next chapter, we’ll build a guessing game
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
|
||||
[TOC]
|
||||
|
||||
# Introduction
|
||||
|
||||
Welcome to “The Rust Programming Language,” an introductory book about Rust.
|
||||
@@ -125,8 +128,6 @@ language in a more reference-like format.
|
||||
## Contributing to the Book
|
||||
|
||||
This book is open source. If you find an error, please don’t hesitate to file
|
||||
an issue or send a pull request [on GitHub]. Please see [CONTRIBUTING.md] for
|
||||
an issue or send a pull request on GitHub at *https://github.com/rust-lang/book*. Please see CONTRIBUTING.md at *https://github.com/rust-lang/book/blob/master/CONTRIBUTING.md* for
|
||||
more details.
|
||||
|
||||
[on GitHub]: https://github.com/rust-lang/book
|
||||
[CONTRIBUTING.md]: https://github.com/rust-lang/book/blob/master/CONTRIBUTING.md
|
||||
@@ -1,11 +1,13 @@
|
||||
# The Rust Programming Language
|
||||
|
||||
[Introduction](ch00-00-introduction.md)
|
||||
|
||||
## Getting started
|
||||
|
||||
- [Introduction](ch01-00-introduction.md)
|
||||
- [Getting Started](ch01-00-getting-started.md)
|
||||
- [Installation](ch01-01-installation.md)
|
||||
- [Hello, World!](ch01-02-hello-world.md)
|
||||
- [How Rust is Made and “Nightly Rust”](ch01-03-how-rust-is-made-and-nightly-rust.md)
|
||||
- [Hello, Cargo!](ch01-03-hello-cargo.md)
|
||||
|
||||
- [Guessing Game Tutorial](ch02-00-guessing-game-tutorial.md)
|
||||
|
||||
@@ -129,3 +131,4 @@
|
||||
- [D - Macros](appendix-04-macros.md)
|
||||
- [E - Translations](appendix-05-translation.md)
|
||||
- [F - Newest Features](appendix-06-newest-features.md)
|
||||
- [G - How Rust is Made and “Nightly Rust”](appendix-07-nightly-rust.md)
|
||||
|
||||
@@ -1,11 +1,10 @@
|
||||
## How Rust is Made and “Nightly Rust”
|
||||
# Appendix G - How Rust is Made and “Nightly Rust”
|
||||
|
||||
Before we dive into the language itself, we’d like to finish up the
|
||||
introductory chapter by talking about how Rust is made, and how that affects
|
||||
you as a Rust developer. We mentioned in the “Installation” section that the
|
||||
output in this book was generated by stable Rust 1.21.0, but any examples that
|
||||
compile should continue to compile in any stable version of Rust greater than
|
||||
that. This section is to explain how we ensure this is true!
|
||||
This appendix is about how Rust is made and how that affects you as a Rust
|
||||
developer. We mentioned that the output in this book was generated by stable
|
||||
Rust 1.21.0, but any examples that compile should continue to compile in any
|
||||
stable version of Rust greater than that. This section is to explain how we
|
||||
ensure this is true!
|
||||
|
||||
### Stability Without Stagnation
|
||||
|
||||
@@ -15,14 +14,10 @@ constantly changing, that would be impossible. At the same time, if we can’t
|
||||
experiment with new features, we may not find out important flaws until after
|
||||
their release, when we can no longer change things.
|
||||
|
||||
Our solution to this problem is what we call “stability without stagnation” and
|
||||
is the way we can change and improve Rust while making sure that using Rust
|
||||
stays nice, stable, and boring.
|
||||
|
||||
Our guiding principle for Rust releases is this: you should never have to fear
|
||||
upgrading to a new version of stable Rust. Each upgrade should be painless. At
|
||||
the same time, the upgrade should bring you new features, fewer bugs, and
|
||||
faster compile times.
|
||||
Our solution to this problem is what we call “stability without stagnation”,
|
||||
and our guiding principle is this: you should never have to fear upgrading to a
|
||||
new version of stable Rust. Each upgrade should be painless, but should also
|
||||
bring you new features, fewer bugs, and faster compile times.
|
||||
|
||||
### Choo, Choo! Release Channels and Riding the Trains
|
||||
|
||||
@@ -207,20 +202,3 @@ worked out on nightly, and decide if it should make it into stable Rust or not.
|
||||
If the decision is to move forward, the feature gate is removed, and the
|
||||
feature is now considered stable! It rides the trains into a new stable release
|
||||
of Rust.
|
||||
|
||||
## Summary
|
||||
|
||||
You’re already off to a great start on your Rust journey! In this chapter,
|
||||
you’ve:
|
||||
|
||||
* Learned what makes Rust unique
|
||||
* Installed the latest stable version of Rust
|
||||
* Written a “Hello, world!” program using both `rustc` directly and using
|
||||
the conventions of `cargo`
|
||||
* Found out about how Rust is developed
|
||||
|
||||
This is a great time to build a more substantial program, to get used to
|
||||
reading and writing Rust code. In the next chapter, we’ll build a guessing game
|
||||
program. If you’d rather start by learning about how common programming
|
||||
concepts work in Rust, see Chapter 3.
|
||||
|
||||
168
second-edition/src/ch00-00-introduction.md
Normal file
168
second-edition/src/ch00-00-introduction.md
Normal file
@@ -0,0 +1,168 @@
|
||||
# Introduction
|
||||
|
||||
Welcome to “The Rust Programming Language,” an introductory book about Rust.
|
||||
|
||||
Rust is a programming language that helps you write faster, more reliable
|
||||
software. High-level ergonomics and low-level control are often at odds with
|
||||
each other in programming language design; Rust stands to challenge that.
|
||||
Through balancing powerful technical capacity and a great developer experience,
|
||||
Rust gives you the option to control low-level details (such as memory usage)
|
||||
without all the hassle traditionally associated with such control.
|
||||
|
||||
## Who Rust is For
|
||||
|
||||
Rust is great for many people for a variety of reasons. Let’s discuss a few of
|
||||
the most important groups.
|
||||
|
||||
### Teams of Developers
|
||||
|
||||
Rust is proving to be a productive tool for collaborating among large teams of
|
||||
developers with varying levels of systems programming knowledge. Low-level code
|
||||
is prone to a variety of subtle bugs, which in most other languages can only be
|
||||
caught through extensive testing and careful code review by experienced
|
||||
developers. In Rust, the compiler plays a gatekeeper role by refusing to
|
||||
compile code with these kinds of bugs--including concurrency bugs. By working
|
||||
alongside the compiler, the team can spend more time focusing on the logic of
|
||||
the program rather than chasing down bugs.
|
||||
|
||||
Rust also brings contemporary developer tools to the systems programming world:
|
||||
|
||||
* Cargo, the included dependency manager and build tool, makes adding,
|
||||
compiling, and managing dependencies painless and consistent across the Rust
|
||||
ecosystem.
|
||||
* Rustfmt ensures a consistent coding style across developers.
|
||||
* The Rust Language Server powers IDE integration for code completion and
|
||||
inline error messages.
|
||||
|
||||
By using these and other tools in the Rust ecosystem, developers can be
|
||||
productive while writing systems-level code.
|
||||
|
||||
### Students
|
||||
|
||||
Rust is for students and people who are interested in learning about systems
|
||||
concepts. Many people have learned about topics like operating systems
|
||||
development through Rust. The community is happy to answer student questions.
|
||||
Through efforts such as this book, the Rust teams want to make systems concepts
|
||||
more accessible to more people, especially those getting started with
|
||||
programming.
|
||||
|
||||
### Companies
|
||||
|
||||
Rust is used in production by hundreds of companies, large and small, for a
|
||||
variety of tasks, such as command line tools, web services, DevOps tooling,
|
||||
embedded devices, audio and video analysis and transcoding, cryptocurrencies,
|
||||
bioinformatics, search engines, internet of things applications, machine
|
||||
learning, and even major parts of the Firefox web browser.
|
||||
|
||||
### Open Source Developers
|
||||
|
||||
Rust is for people who want to build the Rust programming language, community,
|
||||
developer tools, and libraries. We’d love for you to contribute to the Rust
|
||||
language.
|
||||
|
||||
### People Who Value Speed and Stability
|
||||
|
||||
By speed, we mean both the speed of the programs that Rust lets you create and
|
||||
the speed at which Rust lets you write them. The Rust compiler’s checks ensure
|
||||
stability through feature additions and refactoring, as opposed to brittle
|
||||
legacy code in languages without these checks that developers are afraid to
|
||||
modify. By striving for zero-cost abstractions, higher level features that
|
||||
compile to lower level code as fast as code written manually, Rust endeavors to
|
||||
make safe code be fast code as well.
|
||||
|
||||
This isn’t a complete list of everyone the Rust language hopes to support, but
|
||||
these are some of the biggest stakeholders. Overall, Rust’s greatest ambition
|
||||
is to take trade-offs that have been accepted by programmers for decades and
|
||||
eliminate the dichotomy. Safety *and* productivity. Speed *and* ergonomics.
|
||||
Give Rust a try, and see if its choices work for you.
|
||||
|
||||
## Who This Book is For
|
||||
|
||||
This book assumes that you’ve written code in some other programming language,
|
||||
but doesn’t make any assumptions about which one. We’ve tried to make the
|
||||
material broadly accessible to those from a wide variety of programming
|
||||
backgrounds. We don’t spend a lot of time talking about what programming *is*
|
||||
or how to think about it; someone new to programming entirely would be better
|
||||
served by reading a book specifically providing an introduction to programming.
|
||||
|
||||
## How to Use This Book
|
||||
|
||||
This book generally assumes that you’re reading it front-to-back, that is,
|
||||
later chapters build on top of concepts in earlier chapters, and earlier
|
||||
chapters may not dig into details on a topic, revisiting the topic in a later
|
||||
chapter.
|
||||
|
||||
There are two kinds of chapters in this book: concept chapters, and project
|
||||
chapters. In concept chapters, you’ll learn about an aspect of Rust. In the
|
||||
project chapters, we’ll build small programs together, applying what we’ve
|
||||
learned so far. Chapters 2, 12, and 20 are project chapters; the rest are
|
||||
concept chapters.
|
||||
|
||||
Additionally, Chapter 2 is a hands-on introduction to Rust as a language. We’ll
|
||||
cover concepts at a high level, and later chapters will go into them in detail.
|
||||
If you’re the kind of person who likes to get their hands dirty right away,
|
||||
Chapter 2 is great for that. If you’re *really* that kind of person, you may
|
||||
even wish to skip over Chapter 3, which covers features that are very similar
|
||||
to other programming languages, and go straight to Chapter 4 to learn about
|
||||
Rust’s ownership system. By contrast, if you’re a particularly meticulous
|
||||
learner who prefers to learn every detail before moving onto the next, you may
|
||||
want to skip Chapter 2 and go straight to Chapter 3.
|
||||
|
||||
Chapter 5 discusses structs and methods, and Chapter 6 covers enums, `match`
|
||||
expressions, and the `if let` control flow construct. Structs and enums are the
|
||||
ways to make custom types in Rust.
|
||||
|
||||
In Chapter 7, you'll learn about Rust's module system and privacy for
|
||||
organizing your code and its public API. Chapter 8 discusses some common
|
||||
collection data structures provided by the standard library: vectors, strings,
|
||||
and hash maps. Chapter 9 is all about Rust's error handling philosophy and
|
||||
techniques.
|
||||
|
||||
Chapter 10 digs into generics, traits, and lifetimes, which give you the power
|
||||
to define code that applies to multiple types. Chapter 11 is all about testing,
|
||||
which is still necessary even with Rust's safety guarantees to ensure your
|
||||
program's logic is correct. In Chapter 12, we'll build a subset of the
|
||||
functionality of the `grep` command line tool that searches for text within
|
||||
files and we'll use many of the concepts we discussed in the previous chapters.
|
||||
|
||||
Chapter 13 explores closures and iterators: features of Rust that come from
|
||||
functional programming languages. In Chapter 14, we'll explore more about Cargo
|
||||
and talk about best practices for sharing your libraries with others. Chapter
|
||||
15 discusses smart pointers provided by the standard library and the traits
|
||||
that enable their functionality.
|
||||
|
||||
In Chapter 16, we'll go through different models of concurrent programming and
|
||||
how Rust helps you to program using multiple threads fearlessly. Chapter 17
|
||||
looks at how Rust idioms compare to Object Oriented Programming principles you
|
||||
may be familiar with.
|
||||
|
||||
Chapter 18 is a reference on patterns and pattern matching, which are powerful
|
||||
ways of expressing ideas throughout Rust programs. Chapter 19 is a smorgasbord
|
||||
of advanced topics that you might be interested in, including unsafe Rust and
|
||||
more about lifetimes, traits, types, functions, and closures.
|
||||
|
||||
In Chapter 20, we'll finish up with a project where we'll implement a low-level
|
||||
multithreaded web server!
|
||||
|
||||
Finally, there are some appendices. These contain useful information about the
|
||||
language in a more reference-like format.
|
||||
|
||||
In the end, there’s no wrong way to read a book: if you want to skip ahead, go
|
||||
for it! You may have to jump back if you find things confusing. Do whatever
|
||||
works for you.
|
||||
|
||||
An important part of the process of learning Rust is learning how to read the
|
||||
error messages that the compiler gives you. As such, we’ll be showing a lot of
|
||||
code that doesn’t compile, and the error message the compiler will show you in
|
||||
that situation. As such, if you pick a random example, it may not compile!
|
||||
Please read the surrounding text to make sure that you didn’t happen to pick
|
||||
one of the in-progress examples.
|
||||
|
||||
## Contributing to the Book
|
||||
|
||||
This book is open source. If you find an error, please don’t hesitate to file
|
||||
an issue or send a pull request [on GitHub]. Please see [CONTRIBUTING.md] for
|
||||
more details.
|
||||
|
||||
[on GitHub]: https://github.com/rust-lang/book
|
||||
[CONTRIBUTING.md]: https://github.com/rust-lang/book/blob/master/CONTRIBUTING.md
|
||||
12
second-edition/src/ch01-00-getting-started.md
Normal file
12
second-edition/src/ch01-00-getting-started.md
Normal file
@@ -0,0 +1,12 @@
|
||||
# Getting Started
|
||||
|
||||
<!-- If you want to use this paragraph in the Introduction, can you replace it
|
||||
with some other introductory text for the chapter here? Maybe just lay out
|
||||
what's in this chapter so they know it's important not to skip it. -->
|
||||
<!-- Yep, done! /Carol -->
|
||||
|
||||
Let’s get your Rust journey started! In this chapter, we’ll discuss:
|
||||
|
||||
- Installing Rust on Linux, Mac, or Windows
|
||||
- Writing a program that prints “Hello, world!”
|
||||
- Using `cargo`, Rust’s package manager and build system
|
||||
@@ -1,34 +1,35 @@
|
||||
## Installation
|
||||
|
||||
The first step to using Rust is to install it. You’ll need an internet
|
||||
connection to run the commands in this chapter, as we’ll be downloading Rust
|
||||
from the internet. We’ll actually be installing Rust using `rustup`, a
|
||||
command-line tool for managing Rust versions and associated tools.
|
||||
The first step to using Rust is to install it. We’ll download Rust through
|
||||
`rustup`, a command-line tool for managing Rust versions and associated tools.
|
||||
For this you’ll need an internet connection.
|
||||
|
||||
The following steps will install the latest stable version of the Rust
|
||||
compiler. The examples and output shown in this book used stable Rust 1.21.0.
|
||||
Due to Rust’s stability guarantees, which we’ll discuss further in the “How
|
||||
Rust is Made” section later in this chapter, all of the examples that compile
|
||||
will continue to compile with newer versions of Rust. The output may differ
|
||||
slightly as error messages and warnings are often improved. In other words, the
|
||||
newer, stable version of Rust you will install with these steps should work as
|
||||
expected with the content of this book.
|
||||
compiler. The examples and output shown in this book all use stable Rust
|
||||
1.21.0. Rust’s stability guarantees ensure that all of the examples in the book
|
||||
that compile will continue to compile with newer versions of Rust. The output
|
||||
may differ slightly between versions, as error messages and warnings are often
|
||||
improved. In other words, any newer, stable version of Rust you will install
|
||||
with these steps should work as expected with the content of this book.
|
||||
|
||||
<!-- PROD: Start Box -->
|
||||
|
||||
> #### Command Line Notation
|
||||
>
|
||||
> We’ll be showing off a number of commands using a terminal, and those lines
|
||||
> all start with `$`. You don’t need to type in the `$` character; they are
|
||||
> there to indicate the start of each command. You’ll see many tutorials and
|
||||
> examples around the web that follow this convention: `$` for commands run as
|
||||
> a regular user, and `#` for commands you should be running as an
|
||||
> administrator. Lines that don’t start with `$` are typically showing the
|
||||
> output of the previous command. Additionally, PowerShell specific examples
|
||||
> will use `>` rather than `$`.
|
||||
> In this chapter and throughout the book we’ll be showing some commands used
|
||||
> in the terminal. Lines that should be entered in a terminal all start with
|
||||
> `$`. You don’t need to type in the `$` character, it is simply there to
|
||||
> indicate the start of each command. Many tutorials use this convention: `$`
|
||||
> for commands run as a regular user, and `#` for commands you should be
|
||||
> running as an administrator. Lines that don’t start with `$` are typically
|
||||
> showing the output of the previous command. Additionally, PowerShell specific
|
||||
> examples will use `>` rather than `$`.
|
||||
|
||||
<!-- PROD: End box -->
|
||||
|
||||
### Installing Rustup on Linux or Mac
|
||||
|
||||
If you’re on Linux or a Mac, 99% of what you need to do is open a terminal and
|
||||
type this:
|
||||
If you’re on Linux or a Mac, open a terminal and enter the following command:
|
||||
|
||||
```text
|
||||
$ curl https://sh.rustup.rs -sSf | sh
|
||||
@@ -46,36 +47,42 @@ Of course, if you distrust using `curl URL | sh` to install software, you can
|
||||
download, inspect, and run the script however you like.
|
||||
|
||||
The installation script automatically adds Rust to your system PATH after your
|
||||
next login. If you want to start using Rust right away, run the following
|
||||
command in your shell:
|
||||
next login. If you want to start using Rust right away instead of restarting
|
||||
your terminal, run the following command in your shell to add Rust to your
|
||||
system PATH manually:
|
||||
|
||||
<!-- what does this command do? Do you mean instead of logging out and logging
|
||||
in, enter the following? -->
|
||||
<!-- It runs a script that adds Rust to your system PATH manually. I've
|
||||
clarified that yes, this is instead of logging out and back in to your
|
||||
terminal. /Carol -->
|
||||
|
||||
```text
|
||||
$ source $HOME/.cargo/env
|
||||
```
|
||||
|
||||
Alternatively, add the following line to your `~/.bash_profile`:
|
||||
Alternatively, you can add the following line to your `~/.bash_profile`:
|
||||
|
||||
```text
|
||||
$ export PATH="$HOME/.cargo/bin:$PATH"
|
||||
```
|
||||
|
||||
Finally, you’ll need a linker of some kind. You likely have one installed. If
|
||||
not, when you compile a Rust program, you’ll get errors that a linker could not
|
||||
be executed. Check your platform’s documentation for how to install a C
|
||||
compiler; they usually come with the correct linker as well, given that C needs
|
||||
one. You may want to install a C compiler regardless of your need for only a
|
||||
linker; some common Rust packages depend on C code and will need a C compiler
|
||||
too.
|
||||
Finally, you’ll need a linker of some kind. It’s likely you already have one
|
||||
installed, but if you try to compile a Rust program and get errors telling you
|
||||
that a linker could not be executed, you’ll need to install one. You can
|
||||
install a C compiler, as that will usually come with the correct linker. Check
|
||||
your platform’s documentation for how to install a C compiler. Some common Rust
|
||||
packages depend on C code and will need a C compiler too, so it may be worth
|
||||
installing one now regardless.
|
||||
|
||||
### Installing Rustup on Windows
|
||||
|
||||
On Windows, go to [https://www.rust-lang.org/en-US/install.html][install] and
|
||||
follow the instructions. You’ll also need the C++ build tools for Visual Studio
|
||||
2013 or later. The easiest way to acquire the build tools is by installing
|
||||
[Build Tools for Visual Studio 2017][visualstudio] which provides only the
|
||||
Visual C++ build tools. Alternately, you can [install][visualstudio] Visual
|
||||
Studio 2017, Visual Studio 2015, or Visual Studio 2013 and during installation
|
||||
select the desktop development with C++ workload.
|
||||
follow the instructions for installing Rust. At some point in the installation
|
||||
you’ll receive a message telling you you’ll also need the C++ build tools for
|
||||
Visual Studio 2013 or later. The easiest way to acquire the build tools is to
|
||||
install [Build Tools for Visual Studio 2017][visualstudio], found in the Other
|
||||
Tools and Frameworks section.
|
||||
|
||||
[install]: https://www.rust-lang.org/en-US/install.html
|
||||
[visualstudio]: https://www.visualstudio.com/downloads/
|
||||
@@ -88,7 +95,7 @@ PowerShell. If there are specific differences, we’ll explain which to use.
|
||||
If you have reasons for preferring not to use `rustup`, please see [the Rust
|
||||
installation page](https://www.rust-lang.org/install.html) for other options.
|
||||
|
||||
### Updating
|
||||
### Updating and Uninstalling
|
||||
|
||||
Once you have Rust installed via `rustup`, updating to the latest version is
|
||||
easy. From your shell, run the update script:
|
||||
@@ -97,10 +104,7 @@ easy. From your shell, run the update script:
|
||||
$ rustup update
|
||||
```
|
||||
|
||||
### Uninstalling
|
||||
|
||||
Uninstalling Rust and Rustup is as easy as installing them. From your shell,
|
||||
run the uninstall script:
|
||||
To uninstall Rust and `rustup`, from your shell, run the uninstall script:
|
||||
|
||||
```text
|
||||
$ rustup self uninstall
|
||||
@@ -108,14 +112,14 @@ $ rustup self uninstall
|
||||
|
||||
### Troubleshooting
|
||||
|
||||
To check that you have Rust installed, you can open up a shell and type this:
|
||||
To check whether you have Rust installed correctly, open up a shell and enter:
|
||||
|
||||
```text
|
||||
$ rustc --version
|
||||
```
|
||||
|
||||
You should see the version number, commit hash, and commit date in a format
|
||||
similar to this for the latest stable version at the time you install:
|
||||
You should see the version number, commit hash, and commit date for the latest
|
||||
stable version at the time you install in the following format:
|
||||
|
||||
```text
|
||||
rustc x.y.z (abcabcabc yyyy-mm-dd)
|
||||
@@ -126,11 +130,12 @@ If you see this, Rust has been installed successfully! Congrats!
|
||||
If you don’t and you’re on Windows, check that Rust is in your `%PATH%` system
|
||||
variable.
|
||||
|
||||
If it still isn’t working, there are a number of places where you can get help.
|
||||
The easiest is [the #rust IRC channel on irc.mozilla.org][irc]<!-- ignore -->,
|
||||
which you can access through [Mibbit][mibbit]. Go to that address, and you’ll
|
||||
be chatting with other Rustaceans (a silly nickname we call ourselves) who can
|
||||
help you out. Other great resources include [the Users forum][users] and [Stack
|
||||
If that’s all correct and Rust still isn’t working, there are a number of
|
||||
places you can get help. The easiest is [the #rust IRC channel on
|
||||
irc.mozilla.org][irc]<!-- ignore -->, which you can access through
|
||||
[Mibbit][mibbit]. Go to that address, and you’ll be chatting with other
|
||||
Rustaceans (a silly nickname we call ourselves) who can help you out. Other
|
||||
great resources include [the Users forum][users] and [Stack
|
||||
Overflow][stackoverflow].
|
||||
|
||||
[irc]: irc://irc.mozilla.org/#rust
|
||||
|
||||
@@ -2,8 +2,7 @@
|
||||
|
||||
Now that you have Rust installed, let’s write your first Rust program. It’s
|
||||
traditional when learning a new language to write a little program to print the
|
||||
text “Hello, world!” to the screen, and in this section, we’ll follow that
|
||||
tradition.
|
||||
text “Hello, world!” to the screen, so we’ll do the same here!
|
||||
|
||||
> Note: This book assumes basic familiarity with the command line. Rust itself
|
||||
> makes no specific demands about your editing, tooling, or where your code
|
||||
@@ -16,10 +15,12 @@ tradition.
|
||||
### Creating a Project Directory
|
||||
|
||||
First, make a directory to put your Rust code in. Rust doesn’t care where your
|
||||
code lives, but for this book, we’d suggest making a *projects* directory in
|
||||
your home directory and keeping all your projects there. Open a terminal and
|
||||
enter the following commands to make a *projects* directory and a directory
|
||||
inside that for the “Hello, world!” project:
|
||||
code lives, but for the exercises and projects in this book, we’d suggest
|
||||
making a *projects* directory in your home directory and keeping all your
|
||||
projects there.
|
||||
|
||||
Open a terminal and enter the following commands to make a *projects* directory
|
||||
and, inside that, a directory for this “Hello, world!” project:
|
||||
|
||||
Linux and Mac:
|
||||
|
||||
@@ -50,7 +51,7 @@ Windows PowerShell:
|
||||
|
||||
### Writing and Running a Rust Program
|
||||
|
||||
Next, make a new source file and call it *main.rs*. Rust files always end with
|
||||
Next, make a new source file and call it *main.rs*---Rust files always end with
|
||||
the *.rs* extension. If you’re using more than one word in your filename, use
|
||||
an underscore to separate them. For example, you’d use *hello_world.rs* rather
|
||||
than *helloworld.rs*.
|
||||
@@ -69,7 +70,7 @@ fn main() {
|
||||
<span class="caption">Listing 1-1: A program that prints “Hello, world!”</span>
|
||||
|
||||
Save the file, and go back to your terminal window. On Linux or macOS, enter
|
||||
the following commands:
|
||||
the following commands to compile and run the file:
|
||||
|
||||
```text
|
||||
$ rustc main.rs
|
||||
@@ -86,9 +87,17 @@ Hello, world!
|
||||
```
|
||||
|
||||
Regardless of your operating system, you should see the string `Hello, world!`
|
||||
print to the terminal. If you did, then congratulations! You’ve officially
|
||||
print to the terminal. If you don’t see this output, see the “Troubleshooting”
|
||||
section earlier for ways to get help.
|
||||
|
||||
If you did see `Hello, world!` printed, then congratulations! You’ve officially
|
||||
written a Rust program. That makes you a Rust programmer! Welcome!
|
||||
|
||||
<!-- Any quick words of advice for if they didn't? (Disclosure: I tried
|
||||
following this using Bash on windows and couldn't get it working) -->
|
||||
<!-- Added a pointer to the previous troubleshooting section which also applies
|
||||
here /Carol -->
|
||||
|
||||
### Anatomy of a Rust Program
|
||||
|
||||
Now, let’s go over what just happened in your “Hello, world!” program in
|
||||
@@ -100,14 +109,15 @@ fn main() {
|
||||
}
|
||||
```
|
||||
|
||||
These lines define a *function* in Rust. The `main` function is special: it’s
|
||||
the first code that is run for every executable Rust program. The first line
|
||||
declares a function named `main` that has no parameters and returns nothing. If
|
||||
there were parameters, their names would go inside the parentheses, `(` and `)`.
|
||||
These lines define a *function* in Rust. The `main` function is special: it is
|
||||
always the first code that is run for every executable Rust program. The first
|
||||
line declares a function named `main` that has no parameters and returns
|
||||
nothing. If there were parameters, their names would go inside the parentheses,
|
||||
`(` and `)`.
|
||||
|
||||
Also note that the function body is wrapped in curly brackets, `{` and `}`.
|
||||
Rust requires these around all function bodies. It’s considered good style to
|
||||
put the opening curly bracket on the same line as the function declaration,
|
||||
place the opening curly bracket on the same line as the function declaration,
|
||||
with one space in between.
|
||||
|
||||
> At the time of writing, an automatic formatter, `rustfmt`, is under
|
||||
@@ -127,45 +137,35 @@ This line does all of the work in this little program: it prints text to the
|
||||
screen. There are a number of details to notice here. The first is that Rust
|
||||
style is to indent with four spaces, not a tab.
|
||||
|
||||
The second important part is `println!`. This is calling a Rust *macro*, which
|
||||
is how metaprogramming is done in Rust. If it were calling a function instead,
|
||||
it would look like this: `println` (without the `!`). We’ll discuss Rust macros
|
||||
in more detail in Appendix D, but for now you just need to know that when you
|
||||
see a `!` that means that you’re calling a macro instead of a normal function.
|
||||
The second important detail is the `println!` call. This code is calling a Rust
|
||||
*macro*. If it were calling a function instead, it would be entered as
|
||||
`println` (without the `!`). We’ll discuss Rust macros in more detail in
|
||||
Appendix D, but for now you just need to know that when you see a `!` that
|
||||
means that you’re calling a macro instead of a normal function.
|
||||
|
||||
> ### Why `println!` is a Macro
|
||||
>
|
||||
> There are multiple reasons why `println!` is a macro rather than a function,
|
||||
> and we haven’t really explained Rust yet, so it’s not exactly obvious. Here
|
||||
> are the reasons:
|
||||
>
|
||||
> * The string passed to `println!` can have formatting specifiers in it,
|
||||
> and those are checked at compile-time.
|
||||
> * Rust functions can only have a fixed number of arguments, but `println!`
|
||||
> (and macros generally) can take a variable number.
|
||||
> * The formatting specifiers can have named arguments, which Rust functions
|
||||
> cannot.
|
||||
> * It implicitly takes its arguments by reference even when they’re passed
|
||||
> by value.
|
||||
>
|
||||
> If none of this makes sense, don’t worry about it. We’ll cover these concepts
|
||||
> in more detail later.
|
||||
<!-- I might suggest just cutting this next macro section -- for the sake of
|
||||
the intro, we don't really need this info, and I feel like this first exercise
|
||||
should be short and sweet and simple -->
|
||||
<!-- I'm ok with cutting this; it's a fairly common question that some folks
|
||||
have at this point, but I'm ok with those people having to do some research
|
||||
online if they're curious /Carol -->
|
||||
|
||||
Next is `"Hello, world!"` which is a *string*. We pass this string as an
|
||||
argument to `println!`, which prints the string to the screen. Easy enough!
|
||||
Next comes`"Hello, world!"` which is a *string*. We pass this string as an
|
||||
argument to `println!` and the total effect is that the string is printed to
|
||||
the screen. Easy enough!
|
||||
|
||||
The line ends with a semicolon (`;`). The `;` indicates that this expression is
|
||||
We end the line with a semicolon `;`, which indicates that this expression is
|
||||
over, and the next one is ready to begin. Most lines of Rust code end with a
|
||||
`;`.
|
||||
|
||||
### Compiling and Running Are Separate Steps
|
||||
|
||||
In the “Writing and Running a Rust Program” section, we showed you how to run a
|
||||
newly created program. We’ll break that process down and examine each step now.
|
||||
You’ve just seen how to run a newly created program, so now let’s break that
|
||||
process down and examine each step.
|
||||
|
||||
Before running a Rust program, you have to compile it. You can use the Rust
|
||||
compiler by entering the `rustc` command and passing it the name of your source
|
||||
file, like this:
|
||||
Before running a Rust program, you have to compile it using the Rust compiler
|
||||
by entering the `rustc` command and passing it the name of your source file,
|
||||
like this:
|
||||
|
||||
```text
|
||||
$ rustc main.rs
|
||||
@@ -213,258 +213,6 @@ hand, they need to have a Ruby, Python, or JavaScript implementation installed
|
||||
program. Everything is a tradeoff in language design.
|
||||
|
||||
Just compiling with `rustc` is fine for simple programs, but as your project
|
||||
grows, you’ll want to be able to manage all of the options your project has and
|
||||
make it easy to share your code with other people and projects. Next, we’ll
|
||||
introduce you to a tool called Cargo, which will help you write real-world Rust
|
||||
programs.
|
||||
|
||||
## Hello, Cargo!
|
||||
|
||||
Cargo is Rust’s build system and package manager, and Rustaceans use Cargo to
|
||||
manage their Rust projects because it makes a lot of tasks easier. For example,
|
||||
Cargo takes care of building your code, downloading the libraries your code
|
||||
depends on, and building those libraries. We call libraries your code needs
|
||||
*dependencies*.
|
||||
|
||||
The simplest Rust programs, like the one we’ve written so far, don’t have any
|
||||
dependencies, so right now, you’d only be using the part of Cargo that can take
|
||||
care of building your code. As you write more complex Rust programs, you’ll
|
||||
want to add dependencies, and if you start off using Cargo, that will be a lot
|
||||
easier to do.
|
||||
|
||||
As the vast majority of Rust projects use Cargo, we will assume that
|
||||
you’re using it for the rest of the book. Cargo comes installed with Rust
|
||||
itself, if you used the official installers as covered in the “Installation”
|
||||
section. If you installed Rust through some other means, you can check if you
|
||||
have Cargo installed by typing the following into your terminal:
|
||||
|
||||
```text
|
||||
$ cargo --version
|
||||
```
|
||||
|
||||
If you see a version number, great! If you see an error like `command not
|
||||
found`, then you should look at the documentation for your method of
|
||||
installation to determine how to install Cargo separately.
|
||||
|
||||
### Creating a Project with Cargo
|
||||
|
||||
Let’s create a new project using Cargo and look at how it differs from our
|
||||
project in `hello_world`. Go back to your projects directory (or wherever you
|
||||
decided to put your code):
|
||||
|
||||
Linux, Mac, and PowerShell:
|
||||
|
||||
```text
|
||||
$ cd ~/projects
|
||||
```
|
||||
|
||||
CMD for Windows:
|
||||
|
||||
```cmd
|
||||
> cd \d "%USERPROFILE%\projects"
|
||||
```
|
||||
|
||||
And then on any operating system run:
|
||||
|
||||
```text
|
||||
$ cargo new hello_cargo --bin
|
||||
$ cd hello_cargo
|
||||
```
|
||||
|
||||
We passed the `--bin` argument to `cargo new` because our goal is to make an
|
||||
executable application, as opposed to a library. Executables are binary
|
||||
executable files often called just *binaries*. We’ve given `hello_cargo` as the
|
||||
name for our project, and Cargo creates its files in a directory of the same
|
||||
name that we can then go into.
|
||||
|
||||
If we list the files in the *hello_cargo* directory, we can see that Cargo has
|
||||
generated two files and one directory for us: a *Cargo.toml* and a *src*
|
||||
directory with a *main.rs* file inside. It has also initialized a new git
|
||||
repository in the *hello_cargo* directory for us, along with a *.gitignore*
|
||||
file. Git is a common version control system. You can change `cargo new` to use
|
||||
a different version control system, or no version control system, by using the
|
||||
`--vcs` flag. Run `cargo new --help` to see the available options.
|
||||
|
||||
Open up *Cargo.toml* in your text editor of choice. It should look similar to
|
||||
the code in Listing 1-2:
|
||||
|
||||
<span class="filename">Filename: Cargo.toml</span>
|
||||
|
||||
```toml
|
||||
[package]
|
||||
name = "hello_cargo"
|
||||
version = "0.1.0"
|
||||
authors = ["Your Name <you@example.com>"]
|
||||
|
||||
[dependencies]
|
||||
```
|
||||
|
||||
<span class="caption">Listing 1-2: Contents of *Cargo.toml* generated by `cargo
|
||||
new`</span>
|
||||
|
||||
This file is in the [*TOML*][toml]<!-- ignore --> (Tom’s Obvious, Minimal
|
||||
Language) format. TOML is used as Cargo’s configuration format.
|
||||
|
||||
[toml]: https://github.com/toml-lang/toml
|
||||
|
||||
The first line, `[package]`, is a section heading that indicates that the
|
||||
following statements are configuring a package. As we add more information to
|
||||
this file, we’ll add other sections.
|
||||
|
||||
The next three lines set the three bits of configuration that Cargo needs to
|
||||
see in order to know that it should compile your program: its name, what
|
||||
version it is, and who wrote it. Cargo gets your name and email information
|
||||
from your environment. If it’s not correct, go ahead and fix that and save the
|
||||
file.
|
||||
|
||||
The last line, `[dependencies]`, is the start of a section for you to list any
|
||||
*crates* (which is what we call packages of Rust code) that your project will
|
||||
depend on so that Cargo knows to download and compile those too. We won’t need
|
||||
any other crates for this project, but we will in the guessing game tutorial in
|
||||
Chapter 2.
|
||||
|
||||
Now let’s look at *src/main.rs*:
|
||||
|
||||
<span class="filename">Filename: src/main.rs</span>
|
||||
|
||||
```rust
|
||||
fn main() {
|
||||
println!("Hello, world!");
|
||||
}
|
||||
```
|
||||
|
||||
Cargo has generated a “Hello World!” for you, just like the one we wrote in
|
||||
Listing 1-1! So that part is the same. The differences between our previous
|
||||
project and the project generated by Cargo that we’ve seen so far are:
|
||||
|
||||
- Our code goes in the *src* directory
|
||||
- The top level contains a *Cargo.toml* configuration file
|
||||
|
||||
Cargo expects your source files to live inside the *src* directory so that the
|
||||
top-level project directory is just for READMEs, license information,
|
||||
configuration files, and anything else not related to your code. In this way,
|
||||
using Cargo helps you keep your projects nice and tidy. There’s a place for
|
||||
everything, and everything is in its place.
|
||||
|
||||
If you started a project that doesn’t use Cargo, as we did with our project in
|
||||
the *hello_world* directory, you can convert it to a project that does use
|
||||
Cargo by moving your code into the *src* directory and creating an appropriate
|
||||
*Cargo.toml*.
|
||||
|
||||
### Building and Running a Cargo Project
|
||||
|
||||
Now let’s look at what’s different about building and running your Hello World
|
||||
program through Cargo! To do so, enter the following commands:
|
||||
|
||||
```text
|
||||
$ cargo build
|
||||
Compiling hello_cargo v0.1.0 (file:///projects/hello_cargo)
|
||||
Finished dev [unoptimized + debuginfo] target(s) in 2.85 secs
|
||||
```
|
||||
|
||||
This creates an executable file in *target/debug/hello_cargo* (or
|
||||
*target\\debug\\hello_cargo.exe* on Windows), which you can run with this
|
||||
command:
|
||||
|
||||
```text
|
||||
$ ./target/debug/hello_cargo # or .\target\debug\hello_cargo.exe on Windows
|
||||
Hello, world!
|
||||
```
|
||||
|
||||
Bam! If all goes well, `Hello, world!` should print to the terminal once more.
|
||||
|
||||
Running `cargo build` for the first time also causes Cargo to create a new file
|
||||
at the top level called *Cargo.lock*. Cargo uses *Cargo.lock* to keep track of
|
||||
the exact versions of dependencies used to build your project. This project
|
||||
doesn’t have dependencies, so the file is a bit sparse. You won’t ever need to
|
||||
touch this file yourself; Cargo will manage its contents for you.
|
||||
|
||||
We just built a project with `cargo build` and ran it with
|
||||
`./target/debug/hello_cargo`, but we can also use `cargo run` to compile and
|
||||
then run:
|
||||
|
||||
```text
|
||||
$ cargo run
|
||||
Finished dev [unoptimized + debuginfo] target(s) in 0.0 secs
|
||||
Running `target/debug/hello_cargo`
|
||||
Hello, world!
|
||||
```
|
||||
|
||||
Notice that this time, we didn’t see the output telling us that Cargo was
|
||||
compiling `hello_cargo`. Cargo figured out that the files haven’t changed, so
|
||||
it just ran the binary. If you had modified your source code, Cargo would have
|
||||
rebuilt the project before running it, and you would have seen output like
|
||||
this:
|
||||
|
||||
```text
|
||||
$ cargo run
|
||||
Compiling hello_cargo v0.1.0 (file:///projects/hello_cargo)
|
||||
Finished dev [unoptimized + debuginfo] target(s) in 0.33 secs
|
||||
Running `target/debug/hello_cargo`
|
||||
Hello, world!
|
||||
```
|
||||
|
||||
Finally, there’s `cargo check`. This will quickly check your code to make sure
|
||||
that it compiles, but not bother producing an executable:
|
||||
|
||||
```text
|
||||
$ cargo check
|
||||
Compiling hello_cargo v0.1.0 (file:///projects/hello_cargo)
|
||||
Finished dev [unoptimized + debuginfo] target(s) in 0.32 secs
|
||||
```
|
||||
|
||||
Why would you not want an executable? `cargo check` is often much faster than
|
||||
`cargo build`, because Cargo can skip the entire step of producing the
|
||||
executable. If we’re checking our work throughout the process of writing the
|
||||
code, this will speed things up! As such, many Rustaceans run `cargo check` as
|
||||
they write their program to make sure that it compiles, and then run `cargo
|
||||
build` once they’re ready to give it a spin themselves.
|
||||
|
||||
So a few more differences we’ve now seen:
|
||||
|
||||
- Instead of using `rustc`, build a project using `cargo build` or
|
||||
`cargo check` (or build and run it in one step with `cargo run`).
|
||||
- Instead of the result of the build being put in the same directory as our
|
||||
code, Cargo will put it in the *target/debug* directory.
|
||||
|
||||
The other advantage of using Cargo is that the commands are the same no matter
|
||||
what operating system you’re on, so at this point we will no longer be
|
||||
providing specific instructions for Linux and Mac versus Windows.
|
||||
|
||||
### Building for Release
|
||||
|
||||
When your project is finally ready for release, you can use `cargo build
|
||||
--release` to compile your project with optimizations. This will create an
|
||||
executable in *target/release* instead of *target/debug*. These optimizations
|
||||
make your Rust code run faster, but turning them on makes your program take
|
||||
longer to compile. This is why there are two different profiles: one for
|
||||
development when you want to be able to rebuild quickly and often, and one for
|
||||
building the final program you’ll give to a user that won’t be rebuilt and that
|
||||
we want to run as fast as possible. If you’re benchmarking the running time of
|
||||
your code, be sure to run `cargo build --release` and benchmark with the
|
||||
executable in *target/release*.
|
||||
|
||||
### Cargo as Convention
|
||||
|
||||
With simple projects, Cargo doesn’t provide a whole lot of value over just
|
||||
using `rustc`, but it will prove its worth as you continue. With complex
|
||||
projects composed of multiple crates, it’s much easier to let Cargo coordinate
|
||||
the build. With Cargo, you can just run `cargo build`, and it should work the
|
||||
right way.
|
||||
|
||||
Even though the `hello_cargo` project is simple, it now uses much of the real
|
||||
tooling you’ll use for the rest of your Rust career. In fact, you can get
|
||||
started with virtually all Rust projects you want to work on with the following
|
||||
commands to check out the code using Git, change into the project directory,
|
||||
and build:
|
||||
|
||||
```text
|
||||
$ git clone someurl.com/someproject
|
||||
$ cd someproject
|
||||
$ cargo build
|
||||
```
|
||||
|
||||
If you want to look at Cargo in more detail, check out [its documentation],
|
||||
which covers all of its features.
|
||||
|
||||
[its documentation]: https://doc.rust-lang.org/cargo/
|
||||
grows, you’ll want to be able to manage all of the options and make it easy to
|
||||
share your code. Next, we’ll introduce you to a tool called Cargo, which will
|
||||
help you write real-world Rust programs.
|
||||
|
||||
265
second-edition/src/ch01-03-hello-cargo.md
Normal file
265
second-edition/src/ch01-03-hello-cargo.md
Normal file
@@ -0,0 +1,265 @@
|
||||
## Hello, Cargo!
|
||||
|
||||
Cargo is Rust’s build system and package manager. Most Rustaceans will use this
|
||||
tool to manage their Rust projects because Cargo takes care of a lot of tasks
|
||||
for you, such as building your code, downloading the libraries your code
|
||||
depends on, and building those libraries. (We call libraries your code needs
|
||||
*dependencies*.)
|
||||
|
||||
The simplest Rust programs, like the one we’ve written so far, don’t have any
|
||||
dependencies, so if we had built the Hello World project with Cargo, it would
|
||||
only be using the part of Cargo that takes care of building your code. As you
|
||||
write more complex Rust programs, you’ll want to add dependencies, and if you
|
||||
start the project off using Cargo, that will be a lot easier to do.
|
||||
|
||||
As the vast majority of Rust projects use Cargo, the rest of this book will
|
||||
assume that you’re using Cargo too. Cargo comes installed with Rust itself, if
|
||||
you used the official installers as covered in the “Installation” section. If
|
||||
you installed Rust through some other means, you can check if you have Cargo
|
||||
installed by entering the following into your terminal:
|
||||
|
||||
```text
|
||||
$ cargo --version
|
||||
```
|
||||
|
||||
If you see a version number, great! If you see an error like `command not
|
||||
found`, then you should look at the documentation for your method of
|
||||
installation to determine how to install Cargo separately.
|
||||
|
||||
### Creating a Project with Cargo
|
||||
|
||||
Let’s create a new project using Cargo and look at how it differs from our
|
||||
original Hello World project. Navigate back to your *projects* directory (or
|
||||
wherever you decided to put your code) and then on any operating system run:
|
||||
|
||||
```text
|
||||
$ cargo new hello_cargo --bin
|
||||
$ cd hello_cargo
|
||||
```
|
||||
|
||||
<!-- Below -- so we always have to start a cargo project with the --bin option
|
||||
if we want it to be something we can execute and not just a library, is that
|
||||
right? It might be worth laying that out -->
|
||||
<!-- As of Rust 1.21.0 (the version we're using for the book), yes, you must
|
||||
always specify `--bin`. In a version of Rust in the near future (1.25 or 1.26),
|
||||
binary crates will become the default kind of crate that `cargo new` makes, so
|
||||
you won't have to specify `--bin` (but you can if you want and the behavior
|
||||
will be the same). We'd rather not go into any more detail than we have here
|
||||
because of this change; I think "The `--bin` argument to passed to `cargo new`
|
||||
makes an executable application (often just called a *binary*), as opposed to a
|
||||
library." lays this out enough. /Carol -->
|
||||
|
||||
This creates a new binary executable called `hello_cargo`. The `--bin` argument
|
||||
to passed to `cargo new` makes an executable application (often just called a
|
||||
*binary*), as opposed to a library. We’ve given `hello_cargo` as the name for
|
||||
our project, and Cargo creates its files in a directory of the same name.
|
||||
|
||||
Go into the *hello_cargo* directory and list the files, and you should see that
|
||||
Cargo has generated two files and one directory for us: a *Cargo.toml* and a
|
||||
*src* directory with a *main.rs* file inside. It has also initialized a new git
|
||||
repository, along with a *.gitignore* file.
|
||||
|
||||
> Note: Git is a common version control system. You can change `cargo new` to
|
||||
> use a different version control system, or no version control system, by
|
||||
> using the `--vcs` flag. Run `cargo new --help` to see the available options.
|
||||
|
||||
Open up *Cargo.toml* in your text editor of choice. It should look similar to
|
||||
the code in Listing 1-2:
|
||||
|
||||
<span class="filename">Filename: Cargo.toml</span>
|
||||
|
||||
```toml
|
||||
[package]
|
||||
name = "hello_cargo"
|
||||
version = "0.1.0"
|
||||
authors = ["Your Name <you@example.com>"]
|
||||
|
||||
[dependencies]
|
||||
```
|
||||
|
||||
<span class="caption">Listing 1-2: Contents of *Cargo.toml* generated by `cargo
|
||||
new`</span>
|
||||
|
||||
This file is in the [*TOML*][toml]<!-- ignore --> (Tom’s Obvious, Minimal
|
||||
Language) format, which is what Cargo uses as its configuration format.
|
||||
|
||||
[toml]: https://github.com/toml-lang/toml
|
||||
|
||||
The first line, `[package]`, is a section heading that indicates that the
|
||||
following statements are configuring a package. As we add more information to
|
||||
this file, we’ll add other sections.
|
||||
|
||||
The next three lines set the configuration information Cargo needs in order to
|
||||
know that it should compile your program: the name, the version, and who wrote
|
||||
it. Cargo gets your name and email information from your environment, so if
|
||||
that’s not correct, go ahead and fix that and save the file.
|
||||
|
||||
The last line, `[dependencies]`, is the start of a section for you to list any
|
||||
of your project’s dependencies. In Rust, packages of code are referred to as
|
||||
*crates*. We won’t need any other crates for this project, but we will in the
|
||||
first project in Chapter 2, so we’ll use this dependencies section then.
|
||||
|
||||
Now open up *src/main.rs* and take a look:
|
||||
|
||||
<span class="filename">Filename: src/main.rs</span>
|
||||
|
||||
```rust
|
||||
fn main() {
|
||||
println!("Hello, world!");
|
||||
}
|
||||
```
|
||||
|
||||
Cargo has generated a “Hello World!” for you, just like the one we wrote in
|
||||
Listing 1-1! So far, the differences between our previous project and the
|
||||
project generated by Cargo are that with Cargo our code goes in the *src*
|
||||
directory, and we have a *Cargo.toml* configuration file in the top directory.
|
||||
|
||||
Cargo expects your source files to live inside the *src* directory so that the
|
||||
top-level project directory is just for READMEs, license information,
|
||||
configuration files, and anything else not related to your code. In this way,
|
||||
using Cargo helps you keep your projects nice and tidy. There’s a place for
|
||||
everything, and everything is in its place.
|
||||
|
||||
If you started a project that doesn’t use Cargo, as we did with our project in
|
||||
the *hello_world* directory, you can convert it to a project that does use
|
||||
Cargo by moving the project code into the *src* directory and creating an
|
||||
appropriate *Cargo.toml*.
|
||||
|
||||
### Building and Running a Cargo Project
|
||||
|
||||
Now let’s look at what’s different about building and running your Hello World
|
||||
program through Cargo! From your project directory, build your project by
|
||||
entering the following commands:
|
||||
|
||||
```text
|
||||
$ cargo build
|
||||
Compiling hello_cargo v0.1.0 (file:///projects/hello_cargo)
|
||||
Finished dev [unoptimized + debuginfo] target(s) in 2.85 secs
|
||||
```
|
||||
|
||||
This creates an executable file in *target/debug/hello_cargo* (or
|
||||
*target\\debug\\hello_cargo.exe* on Windows), which you can run with this
|
||||
command:
|
||||
|
||||
```text
|
||||
$ ./target/debug/hello_cargo # or .\target\debug\hello_cargo.exe on Windows
|
||||
Hello, world!
|
||||
```
|
||||
|
||||
Bam! If all goes well, `Hello, world!` should print to the terminal once more.
|
||||
Running `cargo build` for the first time also causes Cargo to create a new file
|
||||
at the top level called *Cargo.lock*, which is used to keep track of the exact
|
||||
versions of dependencies in your project. This project doesn’t have
|
||||
dependencies, so the file is a bit sparse. You won’t ever need to touch this
|
||||
file yourself; Cargo will manage its contents for you.
|
||||
|
||||
We just built a project with `cargo build` and ran it with
|
||||
`./target/debug/hello_cargo`, but we can also use `cargo run` to compile and
|
||||
then run all in one go:
|
||||
|
||||
```text
|
||||
$ cargo run
|
||||
Finished dev [unoptimized + debuginfo] target(s) in 0.0 secs
|
||||
Running `target/debug/hello_cargo`
|
||||
Hello, world!
|
||||
```
|
||||
|
||||
Notice that this time, we didn’t see the output telling us that Cargo was
|
||||
compiling `hello_cargo`. Cargo figured out that the files haven’t changed, so
|
||||
it just ran the binary. If you had modified your source code, Cargo would have
|
||||
rebuilt the project before running it, and you would have seen output like this:
|
||||
|
||||
```text
|
||||
$ cargo run
|
||||
Compiling hello_cargo v0.1.0 (file:///projects/hello_cargo)
|
||||
Finished dev [unoptimized + debuginfo] target(s) in 0.33 secs
|
||||
Running `target/debug/hello_cargo`
|
||||
Hello, world!
|
||||
```
|
||||
|
||||
Finally, there’s `cargo check`. This command will quickly check your code to
|
||||
make sure that it compiles, but not bother producing an executable:
|
||||
|
||||
```text
|
||||
$ cargo check
|
||||
Compiling hello_cargo v0.1.0 (file:///projects/hello_cargo)
|
||||
Finished dev [unoptimized + debuginfo] target(s) in 0.32 secs
|
||||
```
|
||||
|
||||
Why would you not want an executable? `cargo check` is often much faster than
|
||||
`cargo build`, because it skips the entire step of producing the executable. If
|
||||
you’re checking your work throughout the process of writing the code, using
|
||||
`cargo check` will speed things up! As such, many Rustaceans run `cargo check`
|
||||
periodically as they write their program to make sure that it compiles, and
|
||||
then run `cargo build` once they’re ready to give it a spin themselves.
|
||||
|
||||
So to recap, using Cargo:
|
||||
|
||||
- We can build a project using `cargo build` or `cargo check`
|
||||
- We can build and run the project in one step with `cargo run`
|
||||
- Instead of the result of the build being put in the same directory as our
|
||||
code, Cargo will put it in the *target/debug* directory.
|
||||
|
||||
A final advantage of using Cargo is that the commands are the same no matter
|
||||
what operating system you’re on, so at this point we will no longer be
|
||||
providing specific instructions for Linux and Mac versus Windows.
|
||||
|
||||
### Building for Release
|
||||
|
||||
When your project is finally ready for release, you can use `cargo build
|
||||
--release` to compile your project with optimizations. This will create an
|
||||
executable in *target/release* instead of *target/debug*. These optimizations
|
||||
make your Rust code run faster, but turning them on makes your program take
|
||||
longer to compile. This is why there are two different profiles: one for
|
||||
development when you want to be able to rebuild quickly and often, and one for
|
||||
building the final program you’ll give to a user that won’t be rebuilt
|
||||
repeatedly and that will run as fast as possible. If you’re benchmarking the
|
||||
running time of your code, be sure to run `cargo build --release` and benchmark
|
||||
with the executable in *target/release*.
|
||||
|
||||
### Cargo as Convention
|
||||
|
||||
With simple projects, Cargo doesn’t provide a whole lot of value over just
|
||||
using `rustc`, but it will prove its worth as you continue. With complex
|
||||
projects composed of multiple crates, it’s much easier to let Cargo coordinate
|
||||
the build.
|
||||
|
||||
Even though the `hello_cargo` project is simple, it now uses much of the real
|
||||
tooling you’ll use for the rest of your Rust career. In fact, to work on any
|
||||
existing projects you can use the following commands to check out the code
|
||||
using Git, change into the project directory, and build:
|
||||
|
||||
```text
|
||||
$ git clone someurl.com/someproject
|
||||
$ cd someproject
|
||||
$ cargo build
|
||||
```
|
||||
|
||||
If you want to look at Cargo in more detail, check out [its documentation].
|
||||
|
||||
[its documentation]: https://doc.rust-lang.org/cargo/
|
||||
|
||||
<!--Below -- I`m not sure this is the place for this conversation, it seems too
|
||||
deep into the weeds for the "getting started" chapter. I know we discussed
|
||||
Nightly Rust as an appendix previously, but honestly I think this is more
|
||||
suited somewhere online, perhaps in the extended docs. I like the idea of
|
||||
finishing the chapter here, on this practical note, and I think at this point
|
||||
readers will want to get stuck in anyway and may skip this and never come back
|
||||
because it's buried at the end of a chapter that's not really related to it. If
|
||||
it's online somewhere separate they can come to it when they're ready. What do
|
||||
you think?-->
|
||||
<!-- Ok, I can see that. /Carol -->
|
||||
|
||||
## Summary
|
||||
|
||||
You’re already off to a great start on your Rust journey! In this chapter,
|
||||
you’ve:
|
||||
|
||||
* Installed the latest stable version of Rust
|
||||
* Written a “Hello, world!” program using both `rustc` directly and using
|
||||
the conventions of `cargo`
|
||||
|
||||
This is a great time to build a more substantial program, to get used to
|
||||
reading and writing Rust code. In the next chapter, we’ll build a guessing game
|
||||
program. If you’d rather start by learning about how common programming
|
||||
concepts work in Rust, see Chapter 3.
|
||||
Reference in New Issue
Block a user