]> git.proxmox.com Git - rustc.git/blame - src/doc/book/second-edition/nostarch/chapter14.md
New upstream version 1.21.0+dfsg1
[rustc.git] / src / doc / book / second-edition / nostarch / chapter14.md
CommitLineData
cc61c64b
XL
1
2[TOC]
3
4# More about Cargo and Crates.io
5
3b2f2976
XL
6So far we’ve used only the most basic features of Cargo to build, run, and test
7our code, but it can do a lot more. Here we’ll go over some of its other, more
8advanced features to show you how to:
cc61c64b 9
3b2f2976
XL
10* Customize your build through release profiles
11* Publish libraries on crates.io
12* Organize larger projects with workspaces
13* Install binaries from crates.io
14* Extend Cargo with your own custom commands
cc61c64b 15
3b2f2976
XL
16Cargo can do even more than what we can cover in this chapter too, so for a
17full explanation, see its documentation at *http://doc.rust-lang.org/cargo/*.
cc61c64b 18
3b2f2976
XL
19<!--can you give a link to the documentation?-->
20<!-- done /Carol -->
cc61c64b 21
3b2f2976 22## Customizing Builds with Release Profiles
cc61c64b 23
3b2f2976
XL
24In Rust *release profiles* are pre-defined, and customizable, profiles with
25different configurations, to allow the programmer more control over various
26options for compiling your code. Each profile is configured independently of
27the others.
28
29<!-- To be clear, are these release profiles pre-defined profiles that you use
30for different things? Can you lay that out more explicitly, give a more
31detailed definition? That seems super useful, but I'm not sure I'm following
32what they actually are. -->
33<!-- They are pre-defined, we've tried to clarify /Carol -->
34
35Cargo has four profiles defined with good default configurations for each use
36case. Cargo uses the different profiles based on which command you’re running.
37The commands correspond to the profiles as shown in Table 14-1:
38
39<!-- Hm, so these profiles aren't built-in, just supported? and used for what
40for cargo build? How do you use a particular profile in a build, is it chosen
41by default? Do you have to specify? -->
42<!-- They are built in with defaults. We've tried to clarify by changing this
43to a table and adding some more explanation, is this better? /Carol -->
44
45| Command | Profile |
46|-------------------------|-----------|
47| `cargo build` | `dev` |
48| `cargo build --release` | `release` |
49| `cargo test` | `test` |
50| `cargo doc` | `doc` |
51
52Table 14-1: Which profile is used when you run different Cargo commands
53
54This may be familiar from the output of your builds, which shows the profile
55used in the build:
56
57<!-- Above-is that what you meant here? -->
58<!-- Yep! /Carol -->
59
60```
cc61c64b 61$ cargo build
3b2f2976 62 Finished dev [unoptimized + debuginfo] target(s) in 0.0 secs
cc61c64b
XL
63$ cargo build --release
64 Finished release [optimized] target(s) in 0.0 secs
65```
66
3b2f2976
XL
67The “dev” and “release” notifications here indicate that the compiler is
68using different profiles.
69
70<!-- which profile is "debug" associated with? As you can probably tell, I'm
71not confident in my interpretation here, I think we need more info -->
72<!-- Sorry, this was an inconsistency in cargo that we actually noticed while
73writing this section and has since been fixed, but then I think we missed
74updating this spot. `debug` should be gone. /Carol -->
cc61c64b 75
3b2f2976 76### Customizing Release Profiles
cc61c64b 77
3b2f2976
XL
78<!-- Do we mean that the profiles are all already stored in Cargo.toml, or you
79have to add the entire code to cargo.toml? It seems like the former from the
80writing, but looking through toml files I've made the latter seems to be true.
81If you have multiple profiles in the toml, how do you choose which one to use?
82-->
83<!-- We've tried to clarify below. Please let me know if this is still unclear,
84I'm confused about how you're drawing your conclusions. /Carol -->
cc61c64b 85
3b2f2976
XL
86Cargo has default settings for each of the profiles that apply when there
87aren’t any `[profile.*]` sections in the project’s *Cargo.toml* file. By adding
88`[profile.*]` sections for any profile we want to customize, we can choose to
89override any subset of the default settings. For example, here are the default
90values for the `opt-level` setting for the `dev` and `release` profiles:
91
92```
cc61c64b
XL
93[profile.dev]
94opt-level = 0
95
96[profile.release]
97opt-level = 3
98```
99
100The `opt-level` setting controls how many optimizations Rust will apply to your
3b2f2976
XL
101code, with a range of zero to three. Applying more optimizations makes
102compilation take longer, so if you’re in development and compiling very often,
103you’d want compiling to be fast at the expense of the resulting code running
104slower. That’s why the default `opt-level` for `dev` is `0`. When you’re ready
105to release, it’s better to spend more time compiling. You’ll only be compiling
106in release mode once, and running the compiled program many times, so release
107mode trades longer compile time for code that runs faster. That’s why the
108default `opt-level` for the `release` profile is `3`.
109
110We can choose to override any default setting by adding a different value for
111them in *Cargo.toml*. If we wanted to use optimization level 1 in the
112development profile, for example, we can add these two lines to our project’s
113*Cargo.toml*:
114
115<!-- So do we choose which profile to use when? How do we do that? Or is that
116determined automatically by Rust, and if so, how? I think we need to show that
117somewhere around here -->
118<!-- Which profile is used is determined by which command you're running, which
119we tried to show above. I hope the table added above has clarified this, if
120not, please suggest further wording above, but the reader should understand
121which profile gets used when by this point and I don't think we should repeat
122it again here. /Carol -->
123
124Filename: Cargo.toml
cc61c64b 125
3b2f2976 126```
cc61c64b
XL
127[profile.dev]
128opt-level = 1
129```
130
3b2f2976
XL
131This overrides the default setting of `0`. Now when we run `cargo build`, Cargo
132will use the defaults for the `dev` profile plus our customization to
133`opt-level`. Because we set `opt-level` to `1`, Cargo will apply more
134optimizations than the default, but not as many as a release build.
cc61c64b 135
3b2f2976
XL
136For the full list of configuration options and defaults for each profile, see
137Cargo’s documentation at *http://doc.rust-lang.org/cargo/*.
cc61c64b
XL
138
139## Publishing a Crate to Crates.io
140
3b2f2976
XL
141We’ve used packages from crates.io as dependencies of our project, but you can
142also share your code for other people to use by publishing your own packages.
143Crates.io distributes the source code of your packages, so it primarily hosts
144code that’s open source.
cc61c64b 145
3b2f2976
XL
146Rust and Cargo have features that help make your published package easier for
147people to find and use. We’ll talk about some of those features, then cover how
148to publish a package.
cc61c64b 149
3b2f2976 150### Making Useful Documentation Comments
cc61c64b 151
3b2f2976
XL
152Accurately documenting your packages will help other users know how and when to
153use them, so it’s worth spending some time to write documentation. In Chapter
1543, we discussed how to comment Rust code with `//`. Rust also has particular
155kind of comment for documentation, known conveniently as *documentation
156comments*, that will generate HTML documentation. The HTML displays the
157contents of documentation comments for public API items, intended for
158programmers interested in knowing how to *use* your crate, as opposed to how
159your crate is *implemented*.
cc61c64b 160
3b2f2976
XL
161<!-- Doc comments support markdown but don’t require markdown, is that right?
162Just wanted to make that distinction -->
163<!-- yes -->
cc61c64b 164
3b2f2976
XL
165Documentation comments use `///` instead of `//` and support Markdown notation
166for formatting the text if you’d like. You place documentation comments just
167before the item they are documenting. Listing 14-2 shows documentation comments
168for an `add_one` function in a crate named `my_crate`:
cc61c64b 169
3b2f2976 170Filename: src/lib.rs
cc61c64b 171
3b2f2976 172```
cc61c64b
XL
173/// Adds one to the number given.
174///
175/// # Examples
176///
177/// ```
178/// let five = 5;
179///
3b2f2976 180/// assert_eq!(6, my_crate::add_one(5));
cc61c64b
XL
181/// ```
182pub fn add_one(x: i32) -> i32 {
183 x + 1
184}
3b2f2976
XL
185```
186
187Listing 14-2: A documentation comment for a function
cc61c64b 188
3b2f2976
XL
189<!-- At some point, a screenshot of how this is rendered in HTML could be really
190useful here, what you do think? -->
191<!-- Yup! /Carol -->
cc61c64b 192
3b2f2976
XL
193Here, we give a description of what the `add_one` function does, then start a
194section with the heading “Examples”, and code that demonstrates how to use the
195`add_one` function. We can generate the HTML documentation from this
196documentation comment by running `cargo doc`. This command runs the `rustdoc`
197tool distributed with Rust and puts the generated HTML documentation in the
198*target/doc* directory.
cc61c64b 199
3b2f2976
XL
200For convenience, running `cargo doc --open` will build the HTML for your
201current crate’s documentation (as well as the documentation for all of your
202crate’s dependencies) and open the result in a web browser. Navigate to the
203`add_one` function and you’ll see how the text in the documentation comments
204gets rendered, shown here in Figure 14-3:
cc61c64b 205
3b2f2976
XL
206<img alt="Rendered HTML documentation for the `add_one` function of `my_crate`" src="img/trpl14-03.png" class="center" />
207
208Figure 14-3: HTML documentation for the `add_one` function
209
210<!--Above - I added this line to describe what we're doing, encourage good
211practice, can you add/edit where necessary? These will generate as HTML when
212the code is run, is that how it works? -->
213<!-- Not when the code is run, when the programmer runs `cargo doc`. That
214doesn't run the programmer's code, really, not in the way `cargo run` runs it
215anyway. We've tried clarifying as well as adding a screenshot. /Carol -->
216
217#### Commonly Used Sections
218
219We used the `# Examples` markdown heading in Listing 14-2 to create a section
220in the HTML with the title “Examples”. Some other sections that crate authors
221commonly use in their documentation include:
222
223- Panics: The scenarios in which this function could `panic!`. Callers of this
224 function who don’t want their programs to panic should make sure that they
225 don’t call this function in these situations.
226- Errors: If this function returns a `Result`, describing the kinds of errors
227 that might occur and what conditions might cause those errors to be returned
228 can be helpful to callers so that they can write code to handle the different
229 kinds of errors in different ways.
230- Safety: If this function uses `unsafe` code (which we will discuss in Chapter
231 19), there should be a section covering the invariants that this function
232 expects callers to uphold in order for the code in `unsafe` blocks to
233 function correctly.
234
235Most documentation comment sections don’t need all of these sections, but this
236is a good list to check to remind you of the kinds of things that people
237calling your code will be interested in knowing about.
238
239#### Documentation Comments as Tests
cc61c64b
XL
240
241Adding examples in code blocks in your documentation comments is a way to
3b2f2976
XL
242clearly demonstrate how to use your library, but it has an additional bonus:
243running `cargo test` will run the code examples in your documentation as tests!
244Nothing is better than documentation with examples. Nothing is worse than
245examples that don’t actually work because the code has changed since the
cc61c64b 246documentation has been written. Try running `cargo test` with the documentation
3b2f2976
XL
247for the `add_one` function like in Listing 14-2; you should see a section in
248the test results like this:
cc61c64b 249
3b2f2976
XL
250```
251 Doc-tests my_crate
cc61c64b
XL
252
253running 1 test
3b2f2976 254test src/lib.rs - add_one (line 5) ... ok
cc61c64b
XL
255
256test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured
257```
258
3b2f2976
XL
259Now try changing either the function or the example so that the `assert_eq!` in
260the example will panic. Run `cargo test` again, and you’ll see that the doc
261tests catch that the example and the code are out of sync from one another!
cc61c64b 262
3b2f2976
XL
263#### Commenting Contained Items
264
265<!-- I'm not clear what this comment does that's different, what do you mean by
266"comment containing items"? The lingo might just be going over my head here -->
267<!-- we've tried to reword and we've changed the example, is this clearer?
268/Carol -->
269
270There’s another style of doc comment, `//!`, that adds documentation to the
271item that contains the comments, rather than adding documentation to the items
272following the comments. These are typically used inside the crate root file
273(*src/lib.rs*) or inside a module’s root (*mod.rs*) to document the crate or
274the module as a whole.
275
276For example, if we wanted to add documentation that described the purpose of
277the `my_crate` crate that contains the `add_one` function, we can add
278documentation comments that start with `//!` to the beginning of *src/lib.rs*
279as shown in Listing 14-4:
280
281Filename: src/lib.rs
cc61c64b
XL
282
283```
3b2f2976 284//! # My Crate
cc61c64b 285//!
3b2f2976
XL
286//! `my_crate` is a collection of utilities to make performing certain
287//! calculations more convenient.
288
289/// Adds one to the number given.
290// ...snip...
cc61c64b
XL
291```
292
3b2f2976
XL
293Listing 14-4: Documentation for the `my_crate` crate as a whole
294
295Notice there isn’t any code after the last line that begins with `//!`. Because
296we started the comments with `//!` instead of `///`, we’re documenting the item
297that contains this comment rather than an item that follows this comment. In
298this case, the item that contains this comment is the *src/lib.rs* file, which
299is the crate root. These comments describe the entire crate.
300
301If we run `cargo doc --open`, we’ll see these comments displayed on the front
302page of the documentation for `my_crate` above the list of public items in the
303crate, as shown in Figure 14-5:
304
305<img alt="Rendered HTML documentation with a comment for the crate as a whole" src="img/trpl14-05.png" class="center" />
306
307Figure 14-5: Rendered documentation for `my_crate` including the comment
308describing the crate as a whole
309
310<!-- I'm not sure what we're looking at here, that's different from just using
311///, can you point it out, talk about it? -->
312<!-- Does the screenshot help? /Carol -->
313
314Documentation comments within items are useful for describing crates and
315modules especially. Use them to talk about the purpose of the container overall
316to help users of your crate understand your organization.
317
cc61c64b
XL
318### Exporting a Convenient Public API with `pub use`
319
320In Chapter 7, we covered how to organize our code into modules with the `mod`
321keyword, how to make items public with the `pub` keyword, and how to bring
3b2f2976
XL
322items into a scope with the `use` keyword. The structure that makes sense to
323you while you’re developing a crate may not be very convenient for your users,
324however. You may wish to organize your structs in a hierarchy containing
325multiple levels, but people that want to use a type you’ve defined deep in the
326hierarchy might have trouble finding out that those types exist. They might
327also be annoyed at having to type `use
328my_crate::some_module::another_module::UsefulType;` rather than `use
329my_crate::UsefulType;`.
330
331<!-- Can you outline why, briefly, here? Reading on, is it something like:
332because some useful functions might be buried within modules that the user is
333unaware of -->
334<!-- Yes, that's pretty much it. We've clarified above. /Carol -->
335
336The structure of your public API is a major consideration when publishing a
337crate. People who use your crate are less familiar with the structure than you
338are, and might have trouble finding the pieces they want to use if the module
339hierarchy is large.
340
341The good news is that, if the structure *isn’t* convenient for others to use
342from another library, you don’t have to rearrange your internal organization:
343you can choose to re-export items to make a public structure that’s different
344to your private structure, using `pub use`. Re-exporting takes a public item in
345one location and makes it public in another location as if it was defined in
346the other location instead.
347
348<!-- Can you give a quick definition of "re-export" here? -->
349<!-- Yup! /Carol -->
350
351For example, say we made a library named `art` for modeling artistic concepts.
352Within this library is a `kinds` module containing two enums named
353`PrimaryColor` and `SecondaryColor` and a `utils` module containing a function
354named `mix` as shown in Listing 14-6:
355
356Filename: src/lib.rs
357
358```
cc61c64b
XL
359//! # Art
360//!
361//! A library for modeling artistic concepts.
362
363pub mod kinds {
364 /// The primary colors according to the RYB color model.
365 pub enum PrimaryColor {
366 Red,
367 Yellow,
368 Blue,
369 }
370
371 /// The secondary colors according to the RYB color model.
372 pub enum SecondaryColor {
373 Orange,
374 Green,
375 Purple,
376 }
377}
378
379pub mod utils {
380 use kinds::*;
381
382 /// Combines two primary colors in equal amounts to create
383 /// a secondary color.
384 pub fn mix(c1: PrimaryColor, c2: PrimaryColor) -> SecondaryColor {
385 // ...snip...
386 }
387}
388```
389
3b2f2976 390Listing 14-6: An `art` library with items organized into `kinds` and `utils`
cc61c64b
XL
391modules
392
3b2f2976
XL
393The front page of the documentation for this crate generated by `cargo doc`
394would look like Figure 14-7:
395
396<img alt="Rendered documentation for the `art` crate that lists the `kinds` and `utils` modules" src="img/trpl14-07.png" class="center" />
397
398Figure 14-7: Front page of the documentation for `art`
399that lists the `kinds` and `utils` modules
cc61c64b 400
3b2f2976
XL
401Note that the `PrimaryColor` and `SecondaryColor` types aren’t listed on the
402front page, nor is the `mix` function. We have to click on `kinds` and `utils`
403in order to see them.
cc61c64b 404
3b2f2976
XL
405Another crate depending on this library would need `use` statements that import
406the items from `art` including specifying the module structure that’s currently
407defined. Listing 14-8 shows an example of a crate that uses the `PrimaryColor`
408and `mix` items from the `art` crate:
cc61c64b 409
3b2f2976
XL
410Filename: src/main.rs
411
412```
cc61c64b
XL
413extern crate art;
414
415use art::kinds::PrimaryColor;
416use art::utils::mix;
417
418fn main() {
419 let red = PrimaryColor::Red;
420 let yellow = PrimaryColor::Yellow;
421 mix(red, yellow);
422}
423```
424
3b2f2976
XL
425Listing 14-8: A crate using the `art` crate’s items with its internal structure
426exported
cc61c64b 427
3b2f2976
XL
428<!--Below -- just to clarify, the "users of this crate" refers to people using
429the crate in 14-8 that `uses` art, is that right? I want to make sure I'm
430following accurately! -->
431<!-- No, it refers to the users of the `art` crate. I've tried to clarify
432/Carol -->
cc61c64b 433
3b2f2976
XL
434The author of the code in Listing 14-8 that uses the `art` crate had to figure
435out that `PrimaryColor` is in the `kinds` module and `mix` is in the `utils`
436module. The module structure of the `art` crate is more relevant to developers
437working on the `art` crate than developers using the `art` crate. The internal
438structure that organizes parts of the crate into the `kinds` module and the
439`utils` module doesn’t add any useful information to someone trying to
440understand how to use the `art` crate. The `art` crate’s module structure adds
441confusion in having to figure out where to look and inconvenience in having to
442specify the module names in the `use` statements.
cc61c64b 443
3b2f2976
XL
444To remove the internal organization from the public API, we can take the `art`
445crate code from Listing 14-6 and add `pub use` statements to re-export the
446items at the top level, as shown in Listing 14-9:
cc61c64b 447
3b2f2976 448Filename: src/lib.rs
cc61c64b 449
3b2f2976 450```
cc61c64b
XL
451//! # Art
452//!
453//! A library for modeling artistic concepts.
454
455pub use kinds::PrimaryColor;
456pub use kinds::SecondaryColor;
457pub use utils::mix;
458
459pub mod kinds {
460 // ...snip...
3b2f2976
XL
461}
462
463pub mod utils {
464 // ...snip...
465}
cc61c64b
XL
466```
467
3b2f2976 468Listing 14-9: Adding `pub use` statements to re-export items
cc61c64b 469
3b2f2976 470<!-- Will add ghosting in libreoffice /Carol -->
cc61c64b 471
3b2f2976
XL
472The API documentation generated with `cargo doc` for this crate will now list
473and link re-exports on the front page as shown in Figure 14-10, which makes
474these types easier to find.
cc61c64b 475
3b2f2976
XL
476<img alt="Rendered documentation for the `art` crate with the re-exports on the front page" src="img/trpl14-10.png" class="center" />
477
478Figure 14-10: Front page of the documentation for `art` that lists the
479re-exports
cc61c64b 480
3b2f2976
XL
481Users of the `art` crate can still see and choose to use the internal structure
482as in Listing 14-8, or they can use the more convenient structure from Listing
48314-9, as shown in Listing 14-11:
cc61c64b 484
3b2f2976 485Filename: src/main.rs
cc61c64b 486
3b2f2976 487```
cc61c64b
XL
488extern crate art;
489
490use art::PrimaryColor;
491use art::mix;
492
493fn main() {
494 // ...snip...
495}
496```
497
3b2f2976 498Listing 14-11: A program using the re-exported items from the `art` crate
cc61c64b
XL
499
500<!-- Will add ghosting in libreoffice /Carol -->
501
3b2f2976
XL
502In cases where there are many nested modules, re-exporting the types at the top
503level with `pub use` can make a big difference in the experience of people who
504use the crate.
505
506Creating a useful public API structure is more of an art than a science, and
507you can iterate to find the API that works best for your users. Choosing `pub
508use` gives you flexibility in how you structure your crate internally, and
509decouples that internal structure with what you present to your users. Take a
510look at some of the code of crates you’ve installed to see if their internal
511structure differs from their public API.
512
513### Setting up a Crates.io Account
514
515Before you can publish any crates, you need to create an account on crates.io
516and get an API token. To do so, visit the home page at *https://crates.io* and
517log in via a GitHub account---the GitHub account is a requirement for now, but
518the site may support other ways of creating an account in the future. Once
519you’re logged in, visit your account settings at *https://crates.io/me* and
520retrieve your API key. Then run the `cargo login` command with your API key,
521like this:
cc61c64b 522
3b2f2976 523```
cc61c64b
XL
524$ cargo login abcdefghijklmnopqrstuvwxyz012345
525```
526
527This command will inform Cargo of your API token and store it locally in
3b2f2976
XL
528*~/.cargo/credentials*. Note that this token is a **secret** and should not be
529shared with anyone else. If it is shared with anyone for any reason, you should
530revoke it and generate a new token on Crates.io.
cc61c64b
XL
531
532### Before Publishing a New Crate
533
3b2f2976
XL
534Now you have an account, and let’s say you already have a crate you want to
535publish. Before publishing, you’ll need to add some metadata to your crate by
536adding it to the `[package]` section of the crate’s *Cargo.toml*.
537
538<!-- Is this right, everything here is relevant to cargo.toml?-->
539<!-- Yep /Carol -->
540
541Your crate will first need a unique name. While you’re working on a crate
542locally, you may name a crate whatever you’d like. However, crate names on
543Crates.io are allocated on a first-come-first-serve basis. Once a crate name is
544taken, no one else may publish a crate with that name. Search for the name
545you’d like to use on the site to find out if it has been taken. If it hasn’t,
546edit the name in *Cargo.toml* under `[package]` to have the name you want to
547use for publishing like so:
548
549```
550[package]
551name = "guessing_game"
552```
cc61c64b 553
3b2f2976
XL
554Even if you’ve chosen a unique name, if you try to run `cargo publish` to
555publish the crate at this point, you’ll get a warning and then an error:
cc61c64b 556
3b2f2976 557```
cc61c64b
XL
558$ cargo publish
559 Updating registry `https://github.com/rust-lang/crates.io-index`
560warning: manifest has no description, license, license-file, documentation,
561homepage or repository.
562...snip...
563error: api errors: missing or empty metadata fields: description, license.
cc61c64b
XL
564```
565
3b2f2976
XL
566This is because we’re missing some crucial information: a description and
567license are required so that people will know what your crate does and under
568what terms they may use it. To rectify this error, we need to include this
569information in *Cargo.toml*.
cc61c64b 570
3b2f2976
XL
571Make a description that’s just a sentence or two, as it will appear with your
572crate in search results and on your crate’s page. For the `license` field, you
573need to give a *license identifier value*. The Linux Foundation’s Software
574Package Data Exchange (SPDX) at *http://spdx.org/licenses/* lists the
575identifiers you can use for this value. For example, to specify that you’ve
576licensed your crate using the MIT License, add the `MIT` identifier:
577
578```
579[package]
580name = "guessing_game"
581license = "MIT"
582```
583
584<!-- Can you give an example of what a license identifier value looks like? It
585is a alphanumerical code? -->
586<!-- Mostly, yeah. /Carol -->
587
588If you want to use a license that doesn’t appear in the SPDX, you need to place
589the text of that license in a file, include the file in your project, then use
590`license-file` to specify the name of that file instead of using the `license`
591key.
cc61c64b
XL
592
593Guidance on which license is right for your project is out of scope for this
594book. Many people in the Rust community choose to license their projects in the
3b2f2976
XL
595same way as Rust itself, with a dual license of `MIT/Apache-2.0`---this
596demonstrates that you can also specify multiple license identifiers separated
597by a slash.
cc61c64b 598
3b2f2976
XL
599So, with a unique name, the version, and author details that `cargo new` added
600when you created the crate, your description, and the license you chose added,
601the *Cargo.toml* for a project that’s ready to publish might look like this:
cc61c64b 602
3b2f2976 603```
cc61c64b
XL
604[package]
605name = "guessing_game"
606version = "0.1.0"
607authors = ["Your Name <you@example.com>"]
608description = "A fun game where you guess what number the computer has chosen."
609license = "MIT/Apache-2.0"
610
611[dependencies]
612```
613
3b2f2976
XL
614Cargo's documentation at *http://doc.rust-lang.org/cargo/* describes other
615metadata you can specify to ensure your crate can be discovered and used more
616easily!
cc61c64b
XL
617
618### Publishing to Crates.io
619
3b2f2976
XL
620Now that you’ve created an account, saved your API token, chosen a name for
621your crate, and specified the required metadata, you’re ready to publish!
622Publishing a crate uploads a specific version to crates.io for others to use.
cc61c64b 623
3b2f2976
XL
624Take care when publishing a crate, because a publish is *permanent*. The
625version can never be overwritten, and the code cannot be deleted. One major
626goal of Crates.io is to act as a permanent archive of code so that builds of
627all projects that depend on crates from Crates.io will continue to work.
628Allowing deletion of versions would make fulfilling that goal impossible.
629However, there is no limit to the number of versions of a crate you can publish.
cc61c64b 630
3b2f2976 631Let’s run the `cargo publish` command again. It should succeed now:
cc61c64b 632
3b2f2976 633```
cc61c64b
XL
634$ cargo publish
635 Updating registry `https://github.com/rust-lang/crates.io-index`
636Packaging guessing_game v0.1.0 (file:///projects/guessing_game)
637Verifying guessing_game v0.1.0 (file:///projects/guessing_game)
638Compiling guessing_game v0.1.0
639(file:///projects/guessing_game/target/package/guessing_game-0.1.0)
3b2f2976 640 Finished dev [unoptimized + debuginfo] target(s) in 0.19 secs
cc61c64b
XL
641Uploading guessing_game v0.1.0 (file:///projects/guessing_game)
642```
643
3b2f2976
XL
644Congratulations! You’ve now shared your code with the Rust community, and
645anyone can easily add your crate as a dependency of their project.
cc61c64b
XL
646
647### Publishing a New Version of an Existing Crate
648
3b2f2976
XL
649When you’ve made changes to your crate and are ready to release a new version,
650you change the `version` value specified in your *Cargo.toml* and republish.
651Use the Semantic Versioning rules at *http://semver.org/* to decide what an appropriate next
652version number is based on the kinds of changes you’ve made. Then run `cargo
653publish` to upload the new version.
cc61c64b
XL
654
655
656### Removing Versions from Crates.io with `cargo yank`
657
3b2f2976
XL
658While you can’t remove previous versions of a crate, you can prevent any future
659projects from adding them as a new dependency. This is useful when a version of
660a crate ends up being broken for one reason or another. For situations such as
661this, Cargo supports *yanking* a version of a crate.
662
663Yanking a version prevents new projects from starting to depend on that
664version while allowing all existing projects that depend on it to continue to
665download and depend on that version. Essentially, a yank means that all
666projects with a *Cargo.lock* will not break, while any future *Cargo.lock*
667files generated will not use the yanked version.
cc61c64b
XL
668
669To yank a version of a crate, run `cargo yank` and specify which version you
670want to yank:
671
3b2f2976 672```
cc61c64b
XL
673$ cargo yank --vers 1.0.1
674```
675
676You can also undo a yank, and allow projects to start depending on a version
677again, by adding `--undo` to the command:
678
3b2f2976 679```
cc61c64b
XL
680$ cargo yank --vers 1.0.1 --undo
681```
682
3b2f2976
XL
683A yank *does not* delete any code. The yank feature is not intended for
684deleting accidentally uploaded secrets, for example. If that happens, you must
685reset those secrets immediately.
686
cc61c64b
XL
687## Cargo Workspaces
688
689In Chapter 12, we built a package that included both a binary crate and a
3b2f2976
XL
690library crate. You may find, as your project develops, that the library crate
691continues to get bigger and you want to split your package up further into
692multiple library crates. In this situation, Cargo has a feature called
693*workspaces* that can help manage multiple related packages that are developed
694in tandem.
cc61c64b
XL
695
696A *workspace* is a set of packages that will all share the same *Cargo.lock*
3b2f2976
XL
697and output directory. Let’s make a project using a workspace, using trivial
698code so we can concentrate on the structure of a workspace. We’ll have a binary
699that uses two libraries: one library that will provide an `add_one` function
700and a second library that will provide an `add_two` function. These three
701crates will all be part of the same workspace. We’ll start by creating a new
702crate for the binary:
cc61c64b 703
3b2f2976 704```
cc61c64b
XL
705$ cargo new --bin adder
706 Created binary (application) `adder` project
707$ cd adder
708```
709
3b2f2976
XL
710We need to modify the binary package’s *Cargo.toml* and add a `[workspace]`
711section to tell Cargo the `adder` package is a workspace. Add this at the
712bottom of the file:
cc61c64b 713
3b2f2976 714```
cc61c64b
XL
715[workspace]
716```
717
718Like many Cargo features, workspaces support convention over configuration: we
3b2f2976
XL
719don’t need to add anything more than this to *Cargo.toml* to define our
720workspace as long as we follow the convention.
721
722<!-- Below -- any crates what depends on, specifically? The program? -->
723<!-- They're all programs. We mean the top-level crate in the workspace here,
724I've tried to clarify. /Carol -->
725
726### Specifying Workspace Dependencies
727
728The workspace convention says any crates in any subdirectories that the
729top-level crate depends on are part of the workspace. Any crate, whether in a
730workspace or not, can specify that it has a dependency on a crate in a local
731directory by using the `path` attribute on the dependency specification in
732*Cargo.toml*. If a crate has the `[workspace]` key and we specify path
733dependencies where the paths are subdirectories of the crate’s directory, those
734dependent crates will be considered part of the workspace. Let’s specify in the
735*Cargo.toml* for the top-level `adder` crate that it will have a dependency on
736an `add-one` crate that will be in the `add-one` subdirectory, by changing
737*Cargo.toml* to look like this:
738
739<!-- Above, what is the path dependency actually doing here, can you fill out
740the paragraph above? -->
741<!-- done /Carol -->
cc61c64b 742
3b2f2976 743```
cc61c64b
XL
744[dependencies]
745add-one = { path = "add-one" }
746```
747
3b2f2976
XL
748If we add dependencies to *Cargo.toml* that don’t have a `path` specified,
749those dependencies will be normal dependencies that aren’t in this workspace
750and are assumed to come from Crates.io.
cc61c64b 751
3b2f2976 752### Creating the Second Crate in the Workspace
cc61c64b 753
3b2f2976
XL
754<!-- You can see I'm adding headings, here, trying to add some more navigable
755structure -- can you improve these? I'm not sure mine are accurate -->
756<!-- Yep! /Carol -->
757
758Next, while in the `adder` directory, generate an `add-one` crate:
759
760```
cc61c64b
XL
761$ cargo new add-one
762 Created library `add-one` project
763```
764
765Your `adder` directory should now have these directories and files:
766
3b2f2976 767```
cc61c64b
XL
768├── Cargo.toml
769├── add-one
770│   ├── Cargo.toml
771│   └── src
772│   └── lib.rs
773└── src
774 └── main.rs
775```
776
3b2f2976 777In *add-one/src/lib.rs*, let’s add an `add_one` function:
cc61c64b 778
3b2f2976 779Filename: add-one/src/lib.rs
cc61c64b 780
3b2f2976 781```
cc61c64b
XL
782pub fn add_one(x: i32) -> i32 {
783 x + 1
784}
785```
786
3b2f2976
XL
787<!-- below -- Where are we adding the extern crate line? -->
788<!-- at the top, where all the extern crate lines go and as illustrated by the listing /Carol -->
789
790Open up *src/main.rs* for `adder` and add an `extern crate` line at the top of
791the file to bring the new `add-one` library crate into scope. Then change the
792`main` function to call the `add_one` function, as in Listing 14-12:
cc61c64b 793
3b2f2976 794```
cc61c64b
XL
795extern crate add_one;
796
797fn main() {
798 let num = 10;
799 println!("Hello, world! {} plus one is {}!", num, add_one::add_one(num));
800}
801```
802
3b2f2976 803Listing 14-12: Using the `add-one` library crate from the `adder` crate
cc61c64b 804
3b2f2976
XL
805Let’s build the `adder` crate by running `cargo build` in the *adder* directory!
806
807```
cc61c64b
XL
808$ cargo build
809 Compiling add-one v0.1.0 (file:///projects/adder/add-one)
810 Compiling adder v0.1.0 (file:///projects/adder)
3b2f2976 811 Finished dev [unoptimized + debuginfo] target(s) in 0.68 secs
cc61c64b
XL
812```
813
3b2f2976
XL
814Note that this builds both the `adder` crate and the `add-one` crate in
815*adder/add-one*. Now your *adder* directory should have these files:
cc61c64b 816
3b2f2976
XL
817```
818├── Cargo.lock
819├── Cargo.toml
820├── add-one
821│   ├── Cargo.toml
822│   └── src
823│   └── lib.rs
824├── src
825│   └── main.rs
826└── target
827```
cc61c64b 828
3b2f2976
XL
829The workspace has one *target* directory at the top level; *add-one* doesn’t
830have its own *target* directory. Even if we go into the `add-one` directory and
831run `cargo build`, the compiled artifacts end up in *adder/target* rather than
832*adder/add-one/target*. The crates in a workspace depend on each other. If each
833crate had its own *target* directory, each crate in the workspace would have to
834recompile each other crate in the workspace in order to have the artifacts in
835its own *target* directory. By sharing one *target* directory, the crates in
836the workspace can avoid rebuilding the other crates in the workspace more than
837necessary.
838
839<!-- Above -- I have no idea what this means for our project here, can you put
840it in more practical terms, or otherwise maybe just explain what this means for
841the user? -->
842<!-- I added more explanation for the target directory in this section and
843added more explanation for the Cargo.lock in the next section, since the
844Cargo.lock advantages aren't as visible until you start adding dependencies on
845external crates. What do you think? /Carol -->
846
847#### Depending on an External Crate in a Workspace
848
849Also notice the workspace only has one *Cargo.lock*, rather than having a
850top-level *Cargo.lock* and *add-one/Cargo.lock*. This ensures that all crates
851are using the same version of all dependencies. If we add the `rand` crate to
852both *Cargo.toml* and *add-one/Cargo.toml*, Cargo will resolve both of those to
853one version of `rand` and record that in the one *Cargo.lock*. Making all
854crates in the workspace use the same dependencies means the crates in the
855workspace will always be compatible with each other. Let’s try this out now.
856
857Let’s add the `rand` crate to the `[dependencies]` section in
858*add-one/Cargo.toml* in order to be able to use the `rand` crate in the
859`add-one` crate:
860
861Filename: add-one/Cargo.toml
cc61c64b 862
3b2f2976 863```
cc61c64b
XL
864[dependencies]
865
866rand = "0.3.14"
867```
868
3b2f2976
XL
869We can now add `extern crate rand;` to *add-one/src/lib.rs*, and building the
870whole workspace by running `cargo build` in the *adder* directory will bring in
871and compile the `rand` crate:
cc61c64b 872
3b2f2976 873```
cc61c64b
XL
874$ cargo build
875 Updating registry `https://github.com/rust-lang/crates.io-index`
876 Downloading rand v0.3.14
877 ...snip...
878 Compiling rand v0.3.14
879 Compiling add-one v0.1.0 (file:///projects/adder/add-one)
880 Compiling adder v0.1.0 (file:///projects/adder)
3b2f2976 881 Finished dev [unoptimized + debuginfo] target(s) in 10.18 secs
cc61c64b
XL
882```
883
3b2f2976
XL
884The top level *Cargo.lock* now contains information about `add-one`’s
885dependency on `rand`. However, even though `rand` is used somewhere in the
886workspace, we can’t use it in other crates in the workspace unless we add
cc61c64b 887`rand` to their *Cargo.toml* as well. If we add `extern crate rand;` to
3b2f2976 888*src/main.rs* for the top level `adder` crate, for example, we’ll get an error:
cc61c64b 889
3b2f2976 890```
cc61c64b
XL
891$ cargo build
892 Compiling adder v0.1.0 (file:///projects/adder)
893error[E0463]: can't find crate for `rand`
894 --> src/main.rs:1:1
895 |
8961 | extern crate rand;
897 | ^^^^^^^^^^^^^^^^^^^ can't find crate
898```
899
3b2f2976
XL
900To fix this, edit *Cargo.toml* for the top level `adder` crate and indicate
901that `rand` is a dependency for that crate as well. Building the `adder` crate
902will add `rand` to the list of dependencies for `adder` in *Cargo.lock*, but no
903additional copies of `rand` will be downloaded. Cargo has ensured for us that
904any crate in the workspace using the `rand` crate will be using the same
905version. Using the same version of `rand` across the workspace saves space
906since we won’t have multiple copies and ensures that the crates in the
907workspace will be compatible with each other.
908
909#### Adding a Test to a Workspace
cc61c64b 910
3b2f2976
XL
911For another enhancement, let’s add a test of the `add_one::add_one` function
912within the `add_one` crate:
cc61c64b 913
3b2f2976 914Filename: add-one/src/lib.rs
cc61c64b 915
3b2f2976 916```
cc61c64b
XL
917pub fn add_one(x: i32) -> i32 {
918 x + 1
919}
920
921#[cfg(test)]
922mod tests {
923 use super::*;
924
925 #[test]
926 fn it_works() {
927 assert_eq!(3, add_one(2));
928 }
929}
930```
931
932Now run `cargo test` in the top-level *adder* directory:
933
3b2f2976 934```
cc61c64b
XL
935$ cargo test
936 Compiling adder v0.1.0 (file:///projects/adder)
3b2f2976 937 Finished dev [unoptimized + debuginfo] target(s) in 0.27 secs
cc61c64b
XL
938 Running target/debug/adder-f0253159197f7841
939
940running 0 tests
941
942test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured
943```
944
945Wait a second, zero tests? We just added one! If we look at the output, we can
3b2f2976
XL
946see that `cargo test` in a workspace only runs tests for the top level crate.
947To run tests for all of the crates in the workspace, we need to pass the
948`--all` flag:
cc61c64b 949
3b2f2976
XL
950```
951$ cargo test --all
952 Finished dev [unoptimized + debuginfo] target(s) in 0.37 secs
cc61c64b
XL
953 Running target/debug/deps/add_one-abcabcabc
954
955running 1 test
956test tests::it_works ... ok
957
3b2f2976
XL
958test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out
959
960 Running target/debug/deps/adder-abcabcabc
961
962running 0 tests
963
964test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out
cc61c64b
XL
965
966 Doc-tests add-one
967
968running 0 tests
969
3b2f2976
XL
970test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out
971```
972
973When passing `--all`, `cargo test` will run the tests for all of the crates in
974the workspace. We can also choose to run tests for one particular crate in a
975workspace from the top level directory by using the `-p` flag and specifying
976the name of the crate we want to test:
977
978```
979$ cargo test -p add-one
980 Finished dev [unoptimized + debuginfo] target(s) in 0.0 secs
981 Running target/debug/deps/add_one-b3235fea9a156f74
982
983running 1 test
984test tests::it_works ... ok
985
986test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out
987
988 Doc-tests add-one
989
990running 0 tests
991
992test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out
cc61c64b
XL
993```
994
3b2f2976
XL
995This output shows `cargo test` only ran the tests for the `add-one` crate and
996didn’t run the `adder` crate tests.
997
998If you choose to publish the crates in the workspace to crates.io, each crate
999in the workspace will get published separately. The `cargo publish` command
1000does not have an `--all` flag or a `-p` flag, so it is necessary to change to
1001each crate’s directory and run `cargo publish` on each crate in the workspace
1002in order to publish them.
cc61c64b 1003
3b2f2976
XL
1004<!-- What does that mean, we have to publish them all one at a time?-->
1005<!-- Yep, we've tried to clarify /Carol -->
1006
1007Now try adding an `add-two` crate to this workspace in a similar way as the
1008`add-one` crate for some more practice!
1009
1010As your project grows, consider using a workspace: smaller components are
1011easier to understand individually than one big blob of code. Keeping the crates
1012in a workspace can make coordination among them easier if they work together
1013and are often changed at the same time.
cc61c64b
XL
1014
1015## Installing Binaries from Crates.io with `cargo install`
1016
1017The `cargo install` command allows you to install and use binary crates
3b2f2976 1018locally. This isn’t intended to replace system packages; it’s meant to be a
cc61c64b 1019convenient way for Rust developers to install tools that others have shared on
3b2f2976
XL
1020crates.io. Only packages that have binary targets can be installed. A binary
1021target is the runnable program that gets created if the crate has a
1022*src/main.rs* or another file specified as a binary, as opposed to a library
1023target that isn’t runnable on its own but is suitable for including within
1024other programs. Usually, crates have information in the *README* file about
1025whether a crate is a library, has a binary target, or both.
1026
1027<!-- What is a binary target, and how do you know if a package has one? -->
1028<!-- Added /Carol -->
1029
1030All binaries from `cargo install` are put into the installation root’s *bin*
1031folder. If you installed Rust using *rustup.rs* and don’t have any custom
1032configurations, this will be `$HOME/.cargo/bin`. Add that directory to your
1033`$PATH` to be able to run programs you’ve gotten through `cargo install`.
1034
1035For example, we mentioned in Chapter 12 that there’s a Rust implementation of
cc61c64b
XL
1036the `grep` tool for searching files called `ripgrep`. If we want to install
1037`ripgrep`, we can run:
1038
3b2f2976 1039```
cc61c64b
XL
1040$ cargo install ripgrep
1041Updating registry `https://github.com/rust-lang/crates.io-index`
1042 Downloading ripgrep v0.3.2
1043 ...snip...
1044 Compiling ripgrep v0.3.2
1045 Finished release [optimized + debuginfo] target(s) in 97.91 secs
1046 Installing ~/.cargo/bin/rg
1047```
1048
1049The last line of the output shows the location and the name of the installed
3b2f2976
XL
1050binary, which in the case of `ripgrep` is `rg`. As long as the installation
1051directory is in your `$PATH` as mentioned above, you can then run `rg --help`
1052and start using a faster, rustier tool for searching files!
cc61c64b
XL
1053
1054## Extending Cargo with Custom Commands
1055
3b2f2976 1056Cargo is designed so you can extend it with new subcommands without having to
cc61c64b
XL
1057modify Cargo itself. If a binary in your `$PATH` is named `cargo-something`,
1058you can run it as if it were a Cargo subcommand by running `cargo something`.
3b2f2976
XL
1059Custom commands like this are also listed when you run `cargo --list`. Being
1060able to `cargo install` extensions and then run them just like the built-in
1061Cargo tools is a super convenient benefit of Cargo’s design!
cc61c64b
XL
1062
1063## Summary
1064
1065Sharing code with Cargo and crates.io is part of what makes the Rust ecosystem
3b2f2976
XL
1066useful for many different tasks. Rust’s standard library is small and stable,
1067but crates are easy to share, use, and improve on a timeline different from the
1068language itself. Don’t be shy about sharing code that’s useful to you on
1069Crates.io; it’s likely that it will be useful to someone else as well!