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