| ## Hello, Cargo! |
| |
| 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 |
| _dependencies_.) |
| |
| 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. |
| |
| 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 |
| [“Installation”][installation]<!-- ignore --> section. If you installed Rust |
| through some other means, check whether Cargo is installed by entering the |
| following in your terminal: |
| |
| ```console |
| $ cargo --version |
| ``` |
| |
| If you see a version number, you have it! If you see an error, such as |
| `command |
| not found`, 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 store your code). Then, on any operating system, run the |
| following: |
| |
| ```console |
| $ cargo new hello_cargo |
| $ cd hello_cargo |
| ``` |
| |
| The first command creates a new directory and project called _hello_cargo_. |
| We’ve named our project _hello_cargo_, and Cargo creates its files in a |
| directory of the same name. |
| |
| Go into the _hello_cargo_ directory and list the files. You’ll see that Cargo |
| has generated two files and one directory for us: a _Cargo.toml_ file and a |
| _src_ directory with a _main.rs_ file inside. |
| |
| It has also initialized a new Git repository along with a _.gitignore_ file. Git |
| files won’t be generated if you run `cargo new` within an existing Git |
| repository; you can override this behavior by using `cargo new --vcs=git`. |
| |
| > 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 _Cargo.toml_ in your text editor of choice. It should look similar to the |
| code in Listing 1-2. |
| |
| <Listing number="1-2" file-name="Cargo.toml" caption="Contents of *Cargo.toml* generated by `cargo new`"> |
| |
| ```toml |
| [package] |
| name = "hello_cargo" |
| version = "0.1.0" |
| edition = "2021" |
| |
| # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html |
| |
| [dependencies] |
| ``` |
| |
| </Listing> |
| |
| This file is in the [_TOML_][toml]<!-- ignore --> (_Tom’s Obvious, Minimal |
| Language_) format, which is Cargo’s 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 configuration information Cargo needs to compile |
| your program: the name, the version, and the edition of Rust to use. We’ll talk |
| about the `edition` key in [Appendix E][appendix-e]<!-- ignore -->. |
| |
| 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 _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!” 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 _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. 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. |
| |
| 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 _src_ directory and create an appropriate _Cargo.toml_ |
| file. One easy way to get that _Cargo.toml_ file is to run `cargo init`, which |
| will create it for you automatically. |
| |
| ### Building and Running a Cargo Project |
| |
| Now let’s look at what’s different when we build and run the “Hello, world!” |
| program with Cargo! From your _hello_cargo_ directory, build your project by |
| entering the following command: |
| |
| ```console |
| $ cargo build |
| Compiling hello_cargo v0.1.0 (file:///projects/hello_cargo) |
| Finished dev [unoptimized + debuginfo] target(s) in 2.85 secs |
| ``` |
| |
| This command creates an executable file in _target/debug/hello_cargo_ (or |
| _target\debug\hello_cargo.exe_ on Windows) rather than in your current |
| directory. Because the default build is a debug build, Cargo puts the binary in |
| a directory named _debug_. You can run the executable with this command: |
| |
| ```console |
| $ ./target/debug/hello_cargo # or .\target\debug\hello_cargo.exe on Windows |
| Hello, world! |
| ``` |
| |
| If all goes well, `Hello, world!` should print to the terminal. Running |
| `cargo |
| build` for the first time also causes Cargo to create a new file at the |
| top level: _Cargo.lock_. 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. |
| |
| 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 the |
| code and then run the resultant executable all in one command: |
| |
| ```console |
| $ cargo run |
| Finished dev [unoptimized + debuginfo] target(s) in 0.0 secs |
| Running `target/debug/hello_cargo` |
| Hello, world! |
| ``` |
| |
| Using `cargo run` is more convenient than having to remember to run `cargo |
| build` |
| and then use the whole path to the binary, so most developers use `cargo |
| run`. |
| |
| Notice that this time we didn’t see output indicating that Cargo was compiling |
| `hello_cargo`. 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: |
| |
| ```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! |
| ``` |
| |
| Cargo also provides a command called `cargo check`. This command quickly checks |
| your code to make sure it compiles but doesn’t produce an executable: |
| |
| ```console |
| $ cargo check |
| Checking 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? Often, `cargo check` is much faster than |
| `cargo build` because it skips the step of producing an executable. If you’re |
| continually checking your work while writing the code, using `cargo check` will |
| speed up the process of letting you know if your project is still compiling! As |
| such, many Rustaceans run `cargo check` periodically as they write their program |
| to make sure it compiles. Then they run `cargo build` when they’re ready to use |
| the executable. |
| |
| Let’s recap what we’ve learned so far about Cargo: |
| |
| * We can create a project using `cargo new`. |
| * We can build a project using `cargo build`. |
| * We can build and run a project in one step using `cargo run`. |
| * We can build a project without producing a binary to check for errors using |
| `cargo check`. |
| * Instead of saving the result of the build in the same directory as our code, |
| Cargo stores it in the _target/debug_ directory. |
| |
| 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. |
| |
| ### Building for Release |
| |
| When your project is finally ready for release, you can use |
| `cargo build |
| --release` to compile it with optimizations. This command will |
| create an executable in _target/release_ instead of _target/debug_. 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 `cargo build --release` and benchmark |
| with the executable in _target/release_. |
| |
| ### Cargo as Convention |
| |
| With simple projects, Cargo doesn’t provide a lot of value over just using |
| `rustc`, 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. |
| |
| Even though the `hello_cargo` 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: |
| |
| ```console |
| $ git clone example.org/someproject |
| $ cd someproject |
| $ cargo build |
| ``` |
| |
| For more information about Cargo, check out [its documentation][cargo]. |
| |
| ## Summary |
| |
| You’re already off to a great start on your Rust journey! In this chapter, |
| you’ve learned how to: |
| |
| * Install the latest stable version of Rust using `rustup` |
| * Update to a newer Rust version |
| * Open locally installed documentation |
| * Write and run a “Hello, world!” program using `rustc` directly |
| * Create and run a new project 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. 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. |
| |
| [installation]: ch01-01-installation.html#installation |
| [toml]: https://toml.io |
| [appendix-e]: appendix-05-editions.html |
| [cargo]: https://doc.rust-lang.org/cargo/ |