203 lines
13 KiB
HTML
203 lines
13 KiB
HTML
<!DOCTYPE html>
|
||
<html lang="en">
|
||
<head>
|
||
<meta charset="UTF-8">
|
||
<title>Hello, Cargo!</title>
|
||
</head>
|
||
<body>
|
||
<h2 id="hello-cargo"><a class="header" href="#hello-cargo">Hello, Cargo!</a></h2>
|
||
<p>Cargo is Rust’s build system and package manager. Most Rustaceans use this tool
|
||
to manage their Rust projects because Cargo handles a lot of tasks for you,
|
||
such as building your code, downloading the libraries your code depends on, and
|
||
building those libraries. (We call the libraries that your code needs
|
||
<em>dependencies</em>.)</p>
|
||
<p>The simplest Rust programs, like the one we’ve written so far, don’t have any
|
||
dependencies. If we had built the “Hello, world!” project with Cargo, it would
|
||
only use the part of Cargo that handles building your code. As you write more
|
||
complex Rust programs, you’ll add dependencies, and if you start a project
|
||
using Cargo, adding dependencies will be much easier to do.</p>
|
||
<p>Because the vast majority of Rust projects use Cargo, the rest of this book
|
||
assumes that you’re using Cargo too. Cargo comes installed with Rust if you
|
||
used the official installers discussed in the
|
||
<a href="ch01-01-installation.html#installation">“Installation”</a><!-- ignore --> section. If you installed Rust
|
||
through some other means, check whether Cargo is installed by entering the
|
||
following in your terminal:</p>
|
||
<pre><code class="language-console">$ cargo --version
|
||
</code></pre>
|
||
<p>If you see a version number, you have it! If you see an error, such as <code>command not found</code>, look at the documentation for your method of installation to
|
||
determine how to install Cargo separately.</p>
|
||
<h3 id="creating-a-project-with-cargo"><a class="header" href="#creating-a-project-with-cargo">Creating a Project with Cargo</a></h3>
|
||
<p>Let’s create a new project using Cargo and look at how it differs from our
|
||
original “Hello, world!” project. Navigate back to your <em>projects</em> directory
|
||
(or wherever you decided to store your code). Then, on any operating system,
|
||
run the following:</p>
|
||
<pre><code class="language-console">$ cargo new hello_cargo
|
||
$ cd hello_cargo
|
||
</code></pre>
|
||
<p>The first command creates a new directory and project called <em>hello_cargo</em>.
|
||
We’ve named our project <em>hello_cargo</em>, and Cargo creates its files in a
|
||
directory of the same name.</p>
|
||
<p>Go into the <em>hello_cargo</em> directory and list the files. You’ll see that Cargo
|
||
has generated two files and one directory for us: a <em>Cargo.toml</em> file and a
|
||
<em>src</em> directory with a <em>main.rs</em> file inside.</p>
|
||
<p>It has also initialized a new Git repository along with a <em>.gitignore</em> file.
|
||
Git files won’t be generated if you run <code>cargo new</code> within an existing Git
|
||
repository; you can override this behavior by using <code>cargo new --vcs=git</code>.</p>
|
||
<section class="note" aria-role="note">
|
||
<p>Note: Git is a common version control system. You can change <code>cargo new</code> to
|
||
use a different version control system or no version control system by using
|
||
the <code>--vcs</code> flag. Run <code>cargo new --help</code> to see the available options.</p>
|
||
</section>
|
||
<p>Open <em>Cargo.toml</em> in your text editor of choice. It should look similar to the
|
||
code in Listing 1-2.</p>
|
||
<figure class="listing" id="listing-1-2">
|
||
<span class="file-name">Filename: Cargo.toml</span>
|
||
<pre><code class="language-toml">[package]
|
||
name = "hello_cargo"
|
||
version = "0.1.0"
|
||
edition = "2024"
|
||
|
||
[dependencies]
|
||
</code></pre>
|
||
<figcaption><a href="#listing-1-2">Listing 1-2</a>: Contents of <em>Cargo.toml</em> generated by <code>cargo new</code></figcaption>
|
||
</figure>
|
||
<p>This file is in the <a href="https://toml.io"><em>TOML</em></a><!-- ignore --> (<em>Tom’s Obvious, Minimal
|
||
Language</em>) format, which is Cargo’s configuration format.</p>
|
||
<p>The first line, <code>[package]</code>, 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.</p>
|
||
<p>The next three lines set the configuration information Cargo needs to compile
|
||
your program: the name, the version, and the edition of Rust to use. We’ll talk
|
||
about the <code>edition</code> key in <a href="../appendix/appendix-05-editions.html">Appendix E</a><!-- ignore -->.</p>
|
||
<p>The last line, <code>[dependencies]</code>, 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
|
||
<em>crates</em>. 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.</p>
|
||
<p>Now open <em>src/main.rs</em> and take a look:</p>
|
||
<p><span class="filename">Filename: src/main.rs</span></p>
|
||
<pre class="playground"><code class="language-rust edition2024">fn main() {
|
||
println!("Hello, world!");
|
||
}</code></pre>
|
||
<p>Cargo has generated a “Hello, world!” program for you, just like the one we
|
||
wrote in Listing 1-1! So far, the differences between our project and the
|
||
project Cargo generated are that Cargo placed the code in the <em>src</em> directory,
|
||
and we have a <em>Cargo.toml</em> configuration file in the top directory.</p>
|
||
<p>Cargo expects your source files to live inside the <em>src</em> directory. The
|
||
top-level project directory is just for README files, license information,
|
||
configuration files, and anything else not related to your code. Using Cargo
|
||
helps you organize your projects. There’s a place for everything, and
|
||
everything is in its place.</p>
|
||
<p>If you started a project that doesn’t use Cargo, as we did with the “Hello,
|
||
world!” project, you can convert it to a project that does use Cargo. Move the
|
||
project code into the <em>src</em> directory and create an appropriate <em>Cargo.toml</em>
|
||
file. One easy way to get that <em>Cargo.toml</em> file is to run <code>cargo init</code>, which
|
||
will create it for you automatically.</p>
|
||
<h3 id="building-and-running-a-cargo-project"><a class="header" href="#building-and-running-a-cargo-project">Building and Running a Cargo Project</a></h3>
|
||
<p>Now let’s look at what’s different when we build and run the “Hello, world!”
|
||
program with Cargo! From your <em>hello_cargo</em> directory, build your project by
|
||
entering the following command:</p>
|
||
<pre><code class="language-console">$ cargo build
|
||
Compiling hello_cargo v0.1.0 (file:///projects/hello_cargo)
|
||
Finished dev [unoptimized + debuginfo] target(s) in 2.85 secs
|
||
</code></pre>
|
||
<p>This command creates an executable file in <em>target/debug/hello_cargo</em> (or
|
||
<em>target\debug\hello_cargo.exe</em> on Windows) rather than in your current
|
||
directory. Because the default build is a debug build, Cargo puts the binary in
|
||
a directory named <em>debug</em>. You can run the executable with this command:</p>
|
||
<pre><code class="language-console">$ ./target/debug/hello_cargo # or .\target\debug\hello_cargo.exe on Windows
|
||
Hello, world!
|
||
</code></pre>
|
||
<p>If all goes well, <code>Hello, world!</code> should print to the terminal. Running <code>cargo build</code> for the first time also causes Cargo to create a new file at the top
|
||
level: <em>Cargo.lock</em>. This file keeps 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 change this file manually; Cargo
|
||
manages its contents for you.</p>
|
||
<p>We just built a project with <code>cargo build</code> and ran it with
|
||
<code>./target/debug/hello_cargo</code>, but we can also use <code>cargo run</code> to compile the
|
||
code and then run the resultant executable all in one command:</p>
|
||
<pre><code class="language-console">$ cargo run
|
||
Finished dev [unoptimized + debuginfo] target(s) in 0.0 secs
|
||
Running `target/debug/hello_cargo`
|
||
Hello, world!
|
||
</code></pre>
|
||
<p>Using <code>cargo run</code> is more convenient than having to remember to run <code>cargo build</code> and then use the whole path to the binary, so most developers use <code>cargo run</code>.</p>
|
||
<p>Notice that this time we didn’t see output indicating that Cargo was compiling
|
||
<code>hello_cargo</code>. Cargo figured out that the files hadn’t changed, so it didn’t
|
||
rebuild but 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 this
|
||
output:</p>
|
||
<pre><code class="language-console">$ 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!
|
||
</code></pre>
|
||
<p>Cargo also provides a command called <code>cargo check</code>. This command quickly checks
|
||
your code to make sure it compiles but doesn’t produce an executable:</p>
|
||
<pre><code class="language-console">$ cargo check
|
||
Checking hello_cargo v0.1.0 (file:///projects/hello_cargo)
|
||
Finished dev [unoptimized + debuginfo] target(s) in 0.32 secs
|
||
</code></pre>
|
||
<p>Why would you not want an executable? Often, <code>cargo check</code> is much faster than
|
||
<code>cargo build</code> because it skips the step of producing an executable. If you’re
|
||
continually checking your work while writing the code, using <code>cargo check</code> will
|
||
speed up the process of letting you know if your project is still compiling! As
|
||
such, many Rustaceans run <code>cargo check</code> periodically as they write their
|
||
program to make sure it compiles. Then, they run <code>cargo build</code> when they’re
|
||
ready to use the executable.</p>
|
||
<p>Let’s recap what we’ve learned so far about Cargo:</p>
|
||
<ul>
|
||
<li>We can create a project using <code>cargo new</code>.</li>
|
||
<li>We can build a project using <code>cargo build</code>.</li>
|
||
<li>We can build and run a project in one step using <code>cargo run</code>.</li>
|
||
<li>We can build a project without producing a binary to check for errors using
|
||
<code>cargo check</code>.</li>
|
||
<li>Instead of saving the result of the build in the same directory as our code,
|
||
Cargo stores it in the <em>target/debug</em> directory.</li>
|
||
</ul>
|
||
<p>An additional advantage of using Cargo is that the commands are the same no
|
||
matter which operating system you’re working on. So, at this point, we’ll no
|
||
longer provide specific instructions for Linux and macOS versus Windows.</p>
|
||
<h3 id="building-for-release"><a class="header" href="#building-for-release">Building for Release</a></h3>
|
||
<p>When your project is finally ready for release, you can use <code>cargo build --release</code> to compile it with optimizations. This command will create an
|
||
executable in <em>target/release</em> instead of <em>target/debug</em>. The optimizations
|
||
make your Rust code run faster, but turning them on lengthens the time it takes
|
||
for your program to compile. This is why there are two different profiles: one
|
||
for development, when you want to rebuild quickly and often, and another 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 your
|
||
code’s running time, be sure to run <code>cargo build --release</code> and benchmark with
|
||
the executable in <em>target/release</em>.</p>
|
||
<!-- Old headings. Do not remove or links may break. -->
|
||
<p><a id="cargo-as-convention"></a></p>
|
||
<h3 id="leveraging-cargos-conventions"><a class="header" href="#leveraging-cargos-conventions">Leveraging Cargo’s Conventions</a></h3>
|
||
<p>With simple projects, Cargo doesn’t provide a lot of value over just using
|
||
<code>rustc</code>, but it will prove its worth as your programs become more intricate.
|
||
Once programs grow to multiple files or need a dependency, it’s much easier to
|
||
let Cargo coordinate the build.</p>
|
||
<p>Even though the <code>hello_cargo</code> project is simple, it now uses much of the real
|
||
tooling you’ll use in 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 to that project’s directory, and build:</p>
|
||
<pre><code class="language-console">$ git clone example.org/someproject
|
||
$ cd someproject
|
||
$ cargo build
|
||
</code></pre>
|
||
<p>For more information about Cargo, check out <a href="https://doc.rust-lang.org/cargo/">its documentation</a>.</p>
|
||
<h2 id="summary"><a class="header" href="#summary">Summary</a></h2>
|
||
<p>You’re already off to a great start on your Rust journey! In this chapter, you
|
||
learned how to:</p>
|
||
<ul>
|
||
<li>Install the latest stable version of Rust using <code>rustup</code>.</li>
|
||
<li>Update to a newer Rust version.</li>
|
||
<li>Open locally installed documentation.</li>
|
||
<li>Write and run a “Hello, world!” program using <code>rustc</code> directly.</li>
|
||
<li>Create and run a new project using the conventions of Cargo.</li>
|
||
</ul>
|
||
<p>This is a great time to build a more substantial program to get used to reading
|
||
and writing Rust code. So, in Chapter 2, we’ll build a guessing game program.
|
||
If you would rather start by learning how common programming concepts work in
|
||
Rust, see Chapter 3 and then return to Chapter 2.</p>
|
||
</body>
|
||
</html>
|