]>
Commit | Line | Data |
---|---|---|
cc61c64b XL |
1 | ## Hello, World! |
2 | ||
3b2f2976 | 3 | Now that you have Rust installed, let’s write your first Rust program. It’s |
cc61c64b | 4 | traditional when learning a new language to write a little program to print the |
3b2f2976 | 5 | text “Hello, world!” to the screen, and in this section, we’ll follow that |
cc61c64b XL |
6 | tradition. |
7 | ||
8 | > Note: This book assumes basic familiarity with the command line. Rust itself | |
9 | > makes no specific demands about your editing, tooling, or where your code | |
10 | > lives, so if you prefer an IDE to the command line, feel free to use your | |
11 | > favorite IDE. | |
12 | ||
13 | ### Creating a Project Directory | |
14 | ||
3b2f2976 XL |
15 | First, make a directory to put your Rust code in. Rust doesn’t care where your code |
16 | lives, but for this book, we’d suggest making a *projects* directory in your | |
cc61c64b XL |
17 | home directory and keeping all your projects there. Open a terminal and enter |
18 | the following commands to make a directory for this particular project: | |
19 | ||
20 | Linux and Mac: | |
21 | ||
22 | ```text | |
23 | $ mkdir ~/projects | |
24 | $ cd ~/projects | |
25 | $ mkdir hello_world | |
26 | $ cd hello_world | |
27 | ``` | |
28 | ||
7cac9316 | 29 | Windows CMD: |
cc61c64b XL |
30 | |
31 | ```cmd | |
32 | > mkdir %USERPROFILE%\projects | |
33 | > cd %USERPROFILE%\projects | |
34 | > mkdir hello_world | |
35 | > cd hello_world | |
36 | ``` | |
37 | ||
7cac9316 XL |
38 | Windows PowerShell: |
39 | ||
40 | ```powershell | |
41 | > mkdir $env:USERPROFILE\projects | |
42 | > cd $env:USERPROFILE\projects | |
43 | > mkdir hello_world | |
44 | > cd hello_world | |
45 | ``` | |
46 | ||
cc61c64b XL |
47 | ### Writing and Running a Rust Program |
48 | ||
49 | Next, make a new source file and call it *main.rs*. Rust files always end with | |
50 | the *.rs* extension. If you’re using more than one word in your filename, use | |
3b2f2976 | 51 | an underscore to separate them. For example, you’d use *hello_world.rs* rather |
cc61c64b XL |
52 | than *helloworld.rs*. |
53 | ||
54 | Now open the *main.rs* file you just created, and type the following code: | |
55 | ||
56 | <span class="filename">Filename: main.rs</span> | |
57 | ||
58 | ```rust | |
59 | fn main() { | |
60 | println!("Hello, world!"); | |
61 | } | |
62 | ``` | |
63 | ||
64 | Save the file, and go back to your terminal window. On Linux or OSX, enter the | |
65 | following commands: | |
66 | ||
67 | ```text | |
68 | $ rustc main.rs | |
69 | $ ./main | |
70 | Hello, world! | |
71 | ``` | |
72 | ||
73 | On Windows, run `.\main.exe` instead of `./main`. Regardless of your | |
74 | operating system, you should see the string `Hello, world!` print to the | |
3b2f2976 | 75 | terminal. If you did, then congratulations! You’ve officially written a Rust |
7cac9316 | 76 | program. That makes you a Rust programmer! Welcome! |
cc61c64b XL |
77 | |
78 | ### Anatomy of a Rust Program | |
79 | ||
3b2f2976 XL |
80 | Now, let’s go over what just happened in your “Hello, world!” program in |
81 | detail. Here’s the first piece of the puzzle: | |
cc61c64b XL |
82 | |
83 | ```rust | |
84 | fn main() { | |
85 | ||
86 | } | |
87 | ``` | |
88 | ||
3b2f2976 | 89 | These lines define a *function* in Rust. The `main` function is special: it’s |
cc61c64b XL |
90 | the first thing that is run for every executable Rust program. The first line |
91 | says, “I’m declaring a function named `main` that has no parameters and returns | |
92 | nothing.” If there were parameters, their names would go inside the | |
93 | parentheses, `(` and `)`. | |
94 | ||
ea8adc8c XL |
95 | Also note that the function body is wrapped in curly brackets, `{` and `}`. |
96 | Rust requires these around all function bodies. It’s considered good style to | |
97 | put the opening curly bracket on the same line as the function declaration, | |
98 | with one space in between. | |
cc61c64b XL |
99 | |
100 | Inside the `main` function: | |
101 | ||
102 | ```rust | |
103 | println!("Hello, world!"); | |
104 | ``` | |
105 | ||
106 | This line does all of the work in this little program: it prints text to the | |
107 | screen. There are a number of details to notice here. The first is that Rust | |
108 | style is to indent with four spaces, not a tab. | |
109 | ||
110 | The second important part is `println!`. This is calling a Rust *macro*, | |
111 | which is how metaprogramming is done in Rust. If it were calling a function | |
3b2f2976 | 112 | instead, it would look like this: `println` (without the `!`). We’ll discuss |
cc61c64b XL |
113 | Rust macros in more detail in Appendix E, but for now you just need to know |
114 | that when you see a `!` that means that you’re calling a macro instead of a | |
115 | normal function. | |
116 | ||
117 | Next is `"Hello, world!"` which is a *string*. We pass this string as an | |
118 | argument to `println!`, which prints the string to the screen. Easy enough! | |
119 | ||
120 | The line ends with a semicolon (`;`). The `;` indicates that this expression is | |
121 | over, and the next one is ready to begin. Most lines of Rust code end with a | |
122 | `;`. | |
123 | ||
124 | ### Compiling and Running Are Separate Steps | |
125 | ||
3b2f2976 XL |
126 | In “Writing and Running a Rust Program”, we showed you how to run a newly |
127 | created program. We’ll break that process down and examine each step now. | |
cc61c64b XL |
128 | |
129 | Before running a Rust program, you have to compile it. You can use the Rust | |
130 | compiler by entering the `rustc` command and passing it the name of your source | |
131 | file, like this: | |
132 | ||
133 | ```text | |
134 | $ rustc main.rs | |
135 | ``` | |
136 | ||
3b2f2976 | 137 | If you come from a C or C++ background, you’ll notice that this is similar to |
cc61c64b XL |
138 | `gcc` or `clang`. After compiling successfully, Rust should output a binary |
139 | executable, which you can see on Linux or OSX by entering the `ls` command in | |
140 | your shell as follows: | |
141 | ||
142 | ```text | |
143 | $ ls | |
144 | main main.rs | |
145 | ``` | |
146 | ||
3b2f2976 | 147 | On Windows, you’d enter: |
cc61c64b XL |
148 | |
149 | ```cmd | |
150 | > dir /B %= the /B option says to only show the file names =% | |
151 | main.exe | |
152 | main.rs | |
153 | ``` | |
154 | ||
155 | This shows we have two files: the source code, with the *.rs* extension, and the | |
3b2f2976 | 156 | executable (*main.exe* on Windows, *main* everywhere else). All that’s left to |
cc61c64b XL |
157 | do from here is run the *main* or *main.exe* file, like this: |
158 | ||
159 | ```text | |
160 | $ ./main # or .\main.exe on Windows | |
161 | ``` | |
162 | ||
3b2f2976 | 163 | If *main.rs* were your “Hello, world!” program, this would print `Hello, |
cc61c64b XL |
164 | world!` to your terminal. |
165 | ||
166 | If you come from a dynamic language like Ruby, Python, or JavaScript, you may | |
167 | not be used to compiling and running a program being separate steps. Rust is an | |
168 | *ahead-of-time compiled* language, which means that you can compile a program, | |
169 | give it to someone else, and they can run it even without having Rust | |
170 | installed. If you give someone a `.rb`, `.py`, or `.js` file, on the other | |
171 | hand, they need to have a Ruby, Python, or JavaScript implementation installed | |
172 | (respectively), but you only need one command to both compile and run your | |
173 | program. Everything is a tradeoff in language design. | |
174 | ||
175 | Just compiling with `rustc` is fine for simple programs, but as your project | |
3b2f2976 XL |
176 | grows, you’ll want to be able to manage all of the options your project has |
177 | and make it easy to share your code with other people and projects. Next, we’ll | |
cc61c64b XL |
178 | introduce you to a tool called Cargo, which will help you write real-world Rust |
179 | programs. | |
180 | ||
181 | ## Hello, Cargo! | |
182 | ||
183 | Cargo is Rust’s build system and package manager, and Rustaceans use Cargo to | |
184 | manage their Rust projects because it makes a lot of tasks easier. For example, | |
185 | Cargo takes care of building your code, downloading the libraries your code | |
186 | depends on, and building those libraries. We call libraries your code needs | |
187 | *dependencies*. | |
188 | ||
3b2f2976 XL |
189 | The simplest Rust programs, like the one we’ve written so far, don’t have any |
190 | dependencies, so right now, you’d only be using the part of Cargo that can take | |
cc61c64b XL |
191 | care of building your code. As you write more complex Rust programs, you’ll |
192 | want to add dependencies, and if you start off using Cargo, that will be a lot | |
193 | easier to do. | |
194 | ||
195 | As the vast, vast majority of Rust projects use Cargo, we will assume that | |
196 | you’re using it for the rest of the book. Cargo comes installed with Rust | |
197 | itself, if you used the official installers as covered in the Installation | |
198 | chapter. If you installed Rust through some other means, you can check if you | |
199 | have Cargo installed by typing the following into your terminal: | |
200 | ||
201 | ```text | |
202 | $ cargo --version | |
203 | ``` | |
204 | ||
205 | If you see a version number, great! If you see an error like `command not | |
206 | found`, then you should look at the documentation for your method of | |
207 | installation to determine how to install Cargo separately. | |
208 | ||
209 | ### Creating a Project with Cargo | |
210 | ||
3b2f2976 | 211 | Let’s create a new project using Cargo and look at how it differs from our |
cc61c64b XL |
212 | project in `hello_world`. Go back to your projects directory (or wherever you |
213 | decided to put your code): | |
214 | ||
215 | Linux and Mac: | |
216 | ||
217 | ```text | |
218 | $ cd ~/projects | |
219 | ``` | |
220 | ||
221 | Windows: | |
222 | ||
223 | ```cmd | |
224 | > cd %USERPROFILE%\projects | |
225 | ``` | |
226 | ||
227 | And then on any operating system run: | |
228 | ||
229 | ```text | |
230 | $ cargo new hello_cargo --bin | |
231 | $ cd hello_cargo | |
232 | ``` | |
233 | ||
234 | We passed the `--bin` argument to `cargo new` because our goal is to make an | |
235 | executable application, as opposed to a library. Executables are binary | |
3b2f2976 | 236 | executable files often called just *binaries*. We’ve given `hello_cargo` |
cc61c64b XL |
237 | as the name for our project, and Cargo creates its files in a directory |
238 | of the same name that we can then go into. | |
239 | ||
240 | If we list the files in the *hello_cargo* directory, we can see that Cargo has | |
241 | generated two files and one directory for us: a *Cargo.toml* and a *src* | |
242 | directory with a *main.rs* file inside. It has also initialized a new git | |
243 | repository in the *hello_cargo* directory for us, along with a *.gitignore* | |
244 | file; you can change this to use a different version control system, or no | |
245 | version control system, by using the `--vcs` flag. | |
246 | ||
247 | Open up *Cargo.toml* in your text editor of choice. It should look something | |
248 | like this: | |
249 | ||
250 | <span class="filename">Filename: Cargo.toml</span> | |
251 | ||
252 | ```toml | |
253 | [package] | |
254 | name = "hello_cargo" | |
255 | version = "0.1.0" | |
256 | authors = ["Your Name <you@example.com>"] | |
257 | ||
258 | [dependencies] | |
259 | ``` | |
260 | ||
3b2f2976 | 261 | This file is in the [*TOML*][toml]<!-- ignore --> (Tom’s Obvious, Minimal |
cc61c64b XL |
262 | Language) format. TOML is similar to INI but has some extra goodies and is used |
263 | as Cargo’s configuration format. | |
264 | ||
265 | [toml]: https://github.com/toml-lang/toml | |
266 | ||
267 | The first line, `[package]`, is a section heading that indicates that the | |
268 | following statements are configuring a package. As we add more information to | |
269 | this file, we’ll add other sections. | |
270 | ||
271 | The next three lines set the three bits of configuration that Cargo needs to | |
272 | see in order to know that it should compile your program: its name, what | |
273 | version it is, and who wrote it. Cargo gets your name and email information | |
274 | from your environment. If it’s not correct, go ahead and fix that and save the | |
275 | file. | |
276 | ||
277 | The last line, `[dependencies]`, is the start of a section for you to list any | |
278 | *crates* (which is what we call packages of Rust code) that your project will | |
3b2f2976 | 279 | depend on so that Cargo knows to download and compile those too. We won’t need |
cc61c64b XL |
280 | any other crates for this project, but we will in the guessing game tutorial in |
281 | the next chapter. | |
282 | ||
3b2f2976 | 283 | Now let’s look at *src/main.rs*: |
cc61c64b XL |
284 | |
285 | <span class="filename">Filename: src/main.rs</span> | |
286 | ||
287 | ```rust | |
288 | fn main() { | |
289 | println!("Hello, world!"); | |
290 | } | |
291 | ``` | |
292 | ||
3b2f2976 | 293 | Cargo has generated a “Hello World!” for you, just like the one we wrote |
cc61c64b | 294 | earlier! So that part is the same. The differences between our previous project |
3b2f2976 | 295 | and the project generated by Cargo that we’ve seen so far are: |
cc61c64b XL |
296 | |
297 | - Our code goes in the *src* directory | |
298 | - The top level contains a *Cargo.toml* configuration file | |
299 | ||
300 | Cargo expects your source files to live inside the *src* directory so that the | |
301 | top-level project directory is just for READMEs, license information, | |
302 | configuration files, and anything else not related to your code. In this way, | |
3b2f2976 | 303 | using Cargo helps you keep your projects nice and tidy. There’s a place for |
cc61c64b XL |
304 | everything, and everything is in its place. |
305 | ||
3b2f2976 | 306 | If you started a project that doesn’t use Cargo, as we did with our project in |
cc61c64b XL |
307 | the *hello_world* directory, you can convert it to a project that does use |
308 | Cargo by moving your code into the *src* directory and creating an appropriate | |
309 | *Cargo.toml*. | |
310 | ||
311 | ### Building and Running a Cargo Project | |
312 | ||
3b2f2976 | 313 | Now let’s look at what’s different about building and running your Hello World |
cc61c64b XL |
314 | program through Cargo! To do so, enter the following commands: |
315 | ||
316 | ```text | |
317 | $ cargo build | |
318 | Compiling hello_cargo v0.1.0 (file:///projects/hello_cargo) | |
319 | ``` | |
320 | ||
321 | This should have created an executable file in *target/debug/hello_cargo* (or | |
ea8adc8c | 322 | *target\\debug\\hello_cargo.exe* on Windows), which you can run with this command: |
cc61c64b XL |
323 | |
324 | ```text | |
325 | $ ./target/debug/hello_cargo # or .\target\debug\hello_cargo.exe on Windows | |
326 | Hello, world! | |
327 | ``` | |
328 | ||
329 | Bam! If all goes well, `Hello, world!` should print to the terminal once more. | |
330 | ||
331 | Running `cargo build` for the first time also causes Cargo to create a new file | |
332 | at the top level called *Cargo.lock*, which looks like this: | |
333 | ||
334 | <span class="filename">Filename: Cargo.lock</span> | |
335 | ||
336 | ```toml | |
337 | [root] | |
338 | name = "hello_cargo" | |
339 | version = "0.1.0" | |
340 | ``` | |
341 | ||
342 | Cargo uses the *Cargo.lock* to keep track of dependencies in your application. | |
3b2f2976 XL |
343 | This project doesn’t have dependencies, so the file is a bit sparse. |
344 | Realistically, you won’t ever need to touch this file yourself; just let Cargo | |
cc61c64b XL |
345 | handle it. |
346 | ||
347 | We just built a project with `cargo build` and ran it with | |
348 | `./target/debug/hello_cargo`, but we can also use `cargo run` to compile | |
349 | and then run: | |
350 | ||
351 | ```text | |
352 | $ cargo run | |
353 | Running `target/debug/hello_cargo` | |
354 | Hello, world! | |
355 | ``` | |
356 | ||
3b2f2976 | 357 | Notice that this time, we didn’t see the output telling us that Cargo was |
cc61c64b XL |
358 | compiling `hello_cargo`. Cargo figured out that the files haven’t changed, so |
359 | it just ran the binary. If you had modified your source code, Cargo would have | |
360 | rebuilt the project before running it, and you would have seen something like | |
361 | this: | |
362 | ||
363 | ```text | |
364 | $ cargo run | |
365 | Compiling hello_cargo v0.1.0 (file:///projects/hello_cargo) | |
366 | Running `target/debug/hello_cargo` | |
367 | Hello, world! | |
368 | ``` | |
369 | ||
3b2f2976 | 370 | So a few more differences we’ve now seen: |
cc61c64b XL |
371 | |
372 | - Instead of using `rustc`, build a project using `cargo build` (or build and | |
373 | run it in one step with `cargo run`) | |
374 | - Instead of the result of the build being put in the same directory as our | |
375 | code, Cargo will put it in the *target/debug* directory. | |
376 | ||
377 | The other advantage of using Cargo is that the commands are the same no matter | |
3b2f2976 | 378 | what operating system you’re on, so at this point we will no longer be |
cc61c64b XL |
379 | providing specific instructions for Linux and Mac versus Windows. |
380 | ||
381 | ### Building for Release | |
382 | ||
383 | When your project is finally ready for release, you can use `cargo build | |
384 | --release` to compile your project with optimizations. This will create an | |
385 | executable in *target/release* instead of *target/debug*. These optimizations | |
386 | make your Rust code run faster, but turning them on makes your program take | |
387 | longer to compile. This is why there are two different profiles: one for | |
388 | development when you want to be able to rebuild quickly and often, and one for | |
3b2f2976 XL |
389 | building the final program you’ll give to a user that won’t be rebuilt and |
390 | that we want to run as fast as possible. If you’re benchmarking the running | |
cc61c64b XL |
391 | time of your code, be sure to run `cargo build --release` and benchmark with |
392 | the executable in *target/release*. | |
393 | ||
394 | ### Cargo as Convention | |
395 | ||
3b2f2976 | 396 | With simple projects, Cargo doesn’t provide a whole lot of value over just |
cc61c64b XL |
397 | using `rustc`, but it will prove its worth as you continue. With complex |
398 | projects composed of multiple crates, it’s much easier to let Cargo coordinate | |
399 | the build. With Cargo, you can just run `cargo build`, and it should work the | |
400 | right way. Even though this project is simple, it now uses much of the real | |
401 | tooling you’ll use for the rest of your Rust career. In fact, you can get | |
402 | started with virtually all Rust projects you want to work | |
403 | on with the following commands: | |
404 | ||
405 | ```text | |
406 | $ git clone someurl.com/someproject | |
407 | $ cd someproject | |
408 | $ cargo build | |
409 | ``` | |
410 | ||
411 | > Note: If you want to look at Cargo in more detail, check out the official | |
412 | [Cargo guide], which covers all of its features. | |
413 | ||
414 | [Cargo guide]: http://doc.crates.io/guide.html |