]>
Commit | Line | Data |
---|---|---|
13cf67c4 XL |
1 | ## Hello, Cargo! |
2 | ||
3 | Cargo is Rust’s build system and package manager. Most Rustaceans use this tool | |
4 | to manage their Rust projects because Cargo handles a lot of tasks for you, | |
5 | such as building your code, downloading the libraries your code depends on, and | |
136023e0 XL |
6 | building those libraries. (We call the libraries that your code needs |
7 | *dependencies*.) | |
13cf67c4 XL |
8 | |
9 | The simplest Rust programs, like the one we’ve written so far, don’t have any | |
923072b8 FG |
10 | dependencies. If we had built the “Hello, world!” project with Cargo, it would |
11 | only use the part of Cargo that handles building your code. As you write more | |
12 | complex Rust programs, you’ll add dependencies, and if you start a project | |
13cf67c4 XL |
13 | using Cargo, adding dependencies will be much easier to do. |
14 | ||
15 | Because the vast majority of Rust projects use Cargo, the rest of this book | |
16 | assumes that you’re using Cargo too. Cargo comes installed with Rust if you | |
dc9dc135 XL |
17 | used the official installers discussed in the |
18 | [“Installation”][installation]<!-- ignore --> section. If you installed Rust | |
19 | through some other means, check whether Cargo is installed by entering the | |
2b03887a | 20 | following in your terminal: |
13cf67c4 | 21 | |
f035d41b | 22 | ```console |
13cf67c4 XL |
23 | $ cargo --version |
24 | ``` | |
25 | ||
26 | If you see a version number, you have it! If you see an error, such as `command | |
27 | not found`, look at the documentation for your method of installation to | |
28 | determine how to install Cargo separately. | |
29 | ||
30 | ### Creating a Project with Cargo | |
31 | ||
32 | Let’s create a new project using Cargo and look at how it differs from our | |
2b03887a FG |
33 | original “Hello, world!” project. Navigate back to your *projects* directory |
34 | (or wherever you decided to store your code). Then, on any operating system, | |
35 | run the following: | |
13cf67c4 | 36 | |
f035d41b | 37 | ```console |
13cf67c4 XL |
38 | $ cargo new hello_cargo |
39 | $ cd hello_cargo | |
40 | ``` | |
41 | ||
923072b8 FG |
42 | The first command creates a new directory and project called *hello_cargo*. |
43 | We’ve named our project *hello_cargo*, and Cargo creates its files in a | |
44 | directory of the same name. | |
13cf67c4 XL |
45 | |
46 | Go into the *hello_cargo* directory and list the files. You’ll see that Cargo | |
47 | has generated two files and one directory for us: a *Cargo.toml* file and a | |
74b04a01 XL |
48 | *src* directory with a *main.rs* file inside. |
49 | ||
50 | It has also initialized a new Git repository along with a *.gitignore* file. | |
51 | Git files won’t be generated if you run `cargo new` within an existing Git | |
52 | repository; you can override this behavior by using `cargo new --vcs=git`. | |
13cf67c4 XL |
53 | |
54 | > Note: Git is a common version control system. You can change `cargo new` to | |
55 | > use a different version control system or no version control system by using | |
56 | > the `--vcs` flag. Run `cargo new --help` to see the available options. | |
57 | ||
58 | Open *Cargo.toml* in your text editor of choice. It should look similar to the | |
59 | code in Listing 1-2. | |
60 | ||
31ef2f64 | 61 | <Listing number="1-2" file-name="Cargo.toml" caption="Contents of *Cargo.toml* generated by `cargo new`"> |
13cf67c4 XL |
62 | |
63 | ```toml | |
64 | [package] | |
65 | name = "hello_cargo" | |
66 | version = "0.1.0" | |
a2a8927a | 67 | edition = "2021" |
13cf67c4 | 68 | |
f2b60f7d FG |
69 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html |
70 | ||
13cf67c4 XL |
71 | [dependencies] |
72 | ``` | |
73 | ||
31ef2f64 | 74 | </Listing> |
13cf67c4 | 75 | |
2b03887a FG |
76 | This file is in the [*TOML*][toml]<!-- ignore --> (*Tom’s Obvious, Minimal |
77 | Language*) format, which is Cargo’s configuration format. | |
13cf67c4 XL |
78 | |
79 | The first line, `[package]`, is a section heading that indicates that the | |
80 | following statements are configuring a package. As we add more information to | |
81 | this file, we’ll add other sections. | |
82 | ||
136023e0 XL |
83 | The next three lines set the configuration information Cargo needs to compile |
84 | your program: the name, the version, and the edition of Rust to use. We’ll talk | |
85 | about the `edition` key in [Appendix E][appendix-e]<!-- ignore -->. | |
13cf67c4 XL |
86 | |
87 | The last line, `[dependencies]`, is the start of a section for you to list any | |
88 | of your project’s dependencies. In Rust, packages of code are referred to as | |
89 | *crates*. We won’t need any other crates for this project, but we will in the | |
90 | first project in Chapter 2, so we’ll use this dependencies section then. | |
91 | ||
92 | Now open *src/main.rs* and take a look: | |
93 | ||
94 | <span class="filename">Filename: src/main.rs</span> | |
95 | ||
96 | ```rust | |
97 | fn main() { | |
98 | println!("Hello, world!"); | |
99 | } | |
100 | ``` | |
101 | ||
e74abb32 | 102 | Cargo has generated a “Hello, world!” program for you, just like the one we |
923072b8 | 103 | wrote in Listing 1-1! So far, the differences between our project and the |
2b03887a | 104 | project Cargo generated are that Cargo placed the code in the *src* directory |
923072b8 | 105 | and we have a *Cargo.toml* configuration file in the top directory. |
13cf67c4 XL |
106 | |
107 | Cargo expects your source files to live inside the *src* directory. The | |
108 | top-level project directory is just for README files, license information, | |
109 | configuration files, and anything else not related to your code. Using Cargo | |
110 | helps you organize your projects. There’s a place for everything, and | |
111 | everything is in its place. | |
112 | ||
e74abb32 XL |
113 | If you started a project that doesn’t use Cargo, as we did with the “Hello, |
114 | world!” project, you can convert it to a project that does use Cargo. Move the | |
13cf67c4 XL |
115 | project code into the *src* directory and create an appropriate *Cargo.toml* |
116 | file. | |
117 | ||
118 | ### Building and Running a Cargo Project | |
119 | ||
e74abb32 | 120 | Now let’s look at what’s different when we build and run the “Hello, world!” |
13cf67c4 XL |
121 | program with Cargo! From your *hello_cargo* directory, build your project by |
122 | entering the following command: | |
123 | ||
f035d41b | 124 | ```console |
13cf67c4 XL |
125 | $ cargo build |
126 | Compiling hello_cargo v0.1.0 (file:///projects/hello_cargo) | |
127 | Finished dev [unoptimized + debuginfo] target(s) in 2.85 secs | |
128 | ``` | |
129 | ||
130 | This command creates an executable file in *target/debug/hello_cargo* (or | |
131 | *target\debug\hello_cargo.exe* on Windows) rather than in your current | |
064997fb FG |
132 | directory. Because the default build is a debug build, Cargo puts the binary in |
133 | a directory named *debug*. You can run the executable with this command: | |
13cf67c4 | 134 | |
f035d41b | 135 | ```console |
13cf67c4 XL |
136 | $ ./target/debug/hello_cargo # or .\target\debug\hello_cargo.exe on Windows |
137 | Hello, world! | |
138 | ``` | |
139 | ||
140 | If all goes well, `Hello, world!` should print to the terminal. Running `cargo | |
141 | build` for the first time also causes Cargo to create a new file at the top | |
142 | level: *Cargo.lock*. This file keeps track of the exact versions of | |
143 | dependencies in your project. This project doesn’t have dependencies, so the | |
144 | file is a bit sparse. You won’t ever need to change this file manually; Cargo | |
145 | manages its contents for you. | |
146 | ||
147 | We just built a project with `cargo build` and ran it with | |
148 | `./target/debug/hello_cargo`, but we can also use `cargo run` to compile the | |
2b03887a | 149 | code and then run the resultant executable all in one command: |
13cf67c4 | 150 | |
f035d41b | 151 | ```console |
13cf67c4 XL |
152 | $ cargo run |
153 | Finished dev [unoptimized + debuginfo] target(s) in 0.0 secs | |
154 | Running `target/debug/hello_cargo` | |
155 | Hello, world! | |
156 | ``` | |
157 | ||
923072b8 FG |
158 | Using `cargo run` is more convenient than having to remember to run `cargo |
159 | build` and then use the whole path to the binary, so most developers use `cargo | |
160 | run`. | |
161 | ||
13cf67c4 | 162 | Notice that this time we didn’t see output indicating that Cargo was compiling |
923072b8 FG |
163 | `hello_cargo`. Cargo figured out that the files hadn’t changed, so it didn’t |
164 | rebuild but just ran the binary. If you had modified your source code, Cargo | |
165 | would have rebuilt the project before running it, and you would have seen this | |
166 | output: | |
13cf67c4 | 167 | |
f035d41b | 168 | ```console |
13cf67c4 XL |
169 | $ cargo run |
170 | Compiling hello_cargo v0.1.0 (file:///projects/hello_cargo) | |
171 | Finished dev [unoptimized + debuginfo] target(s) in 0.33 secs | |
172 | Running `target/debug/hello_cargo` | |
173 | Hello, world! | |
174 | ``` | |
175 | ||
176 | Cargo also provides a command called `cargo check`. This command quickly checks | |
177 | your code to make sure it compiles but doesn’t produce an executable: | |
178 | ||
f035d41b | 179 | ```console |
13cf67c4 XL |
180 | $ cargo check |
181 | Checking hello_cargo v0.1.0 (file:///projects/hello_cargo) | |
182 | Finished dev [unoptimized + debuginfo] target(s) in 0.32 secs | |
183 | ``` | |
184 | ||
185 | Why would you not want an executable? Often, `cargo check` is much faster than | |
2b03887a | 186 | `cargo build` because it skips the step of producing an executable. If you’re |
13cf67c4 | 187 | continually checking your work while writing the code, using `cargo check` will |
923072b8 FG |
188 | speed up the process of letting you know if your project is still compiling! As |
189 | such, many Rustaceans run `cargo check` periodically as they write their | |
190 | program to make sure it compiles. Then they run `cargo build` when they’re | |
191 | ready to use the executable. | |
13cf67c4 XL |
192 | |
193 | Let’s recap what we’ve learned so far about Cargo: | |
194 | ||
5e7ed085 | 195 | * We can create a project using `cargo new`. |
f035d41b | 196 | * We can build a project using `cargo build`. |
13cf67c4 | 197 | * We can build and run a project in one step using `cargo run`. |
6a06907d XL |
198 | * We can build a project without producing a binary to check for errors using |
199 | `cargo check`. | |
13cf67c4 XL |
200 | * Instead of saving the result of the build in the same directory as our code, |
201 | Cargo stores it in the *target/debug* directory. | |
202 | ||
203 | An additional advantage of using Cargo is that the commands are the same no | |
204 | matter which operating system you’re working on. So, at this point, we’ll no | |
205 | longer provide specific instructions for Linux and macOS versus Windows. | |
206 | ||
207 | ### Building for Release | |
208 | ||
209 | When your project is finally ready for release, you can use `cargo build | |
210 | --release` to compile it with optimizations. This command will create an | |
211 | executable in *target/release* instead of *target/debug*. The optimizations | |
212 | make your Rust code run faster, but turning them on lengthens the time it takes | |
213 | for your program to compile. This is why there are two different profiles: one | |
214 | for development, when you want to rebuild quickly and often, and another for | |
215 | building the final program you’ll give to a user that won’t be rebuilt | |
216 | repeatedly and that will run as fast as possible. If you’re benchmarking your | |
217 | code’s running time, be sure to run `cargo build --release` and benchmark with | |
218 | the executable in *target/release*. | |
219 | ||
220 | ### Cargo as Convention | |
221 | ||
222 | With simple projects, Cargo doesn’t provide a lot of value over just using | |
223 | `rustc`, but it will prove its worth as your programs become more intricate. | |
064997fb FG |
224 | Once programs grow to multiple files or need a dependency, it’s much easier to |
225 | let Cargo coordinate the build. | |
13cf67c4 XL |
226 | |
227 | Even though the `hello_cargo` project is simple, it now uses much of the real | |
228 | tooling you’ll use in the rest of your Rust career. In fact, to work on any | |
229 | existing projects, you can use the following commands to check out the code | |
230 | using Git, change to that project’s directory, and build: | |
231 | ||
f035d41b | 232 | ```console |
cdc7bbd5 | 233 | $ git clone example.org/someproject |
13cf67c4 XL |
234 | $ cd someproject |
235 | $ cargo build | |
236 | ``` | |
237 | ||
2b03887a | 238 | For more information about Cargo, check out [its documentation][cargo]. |
13cf67c4 XL |
239 | |
240 | ## Summary | |
241 | ||
242 | You’re already off to a great start on your Rust journey! In this chapter, | |
243 | you’ve learned how to: | |
244 | ||
245 | * Install the latest stable version of Rust using `rustup` | |
246 | * Update to a newer Rust version | |
247 | * Open locally installed documentation | |
e74abb32 | 248 | * Write and run a “Hello, world!” program using `rustc` directly |
13cf67c4 XL |
249 | * Create and run a new project using the conventions of Cargo |
250 | ||
251 | This is a great time to build a more substantial program to get used to reading | |
252 | and writing Rust code. So, in Chapter 2, we’ll build a guessing game program. | |
253 | If you would rather start by learning how common programming concepts work in | |
254 | Rust, see Chapter 3 and then return to Chapter 2. | |
9fa01778 XL |
255 | |
256 | [installation]: ch01-01-installation.html#installation | |
2b03887a | 257 | [toml]: https://toml.io |
136023e0 | 258 | [appendix-e]: appendix-05-editions.html |
2b03887a | 259 | [cargo]: https://doc.rust-lang.org/cargo/ |