]>
Commit | Line | Data |
---|---|---|
13cf67c4 XL |
1 | ## Publishing a Crate to Crates.io |
2 | ||
dc9dc135 | 3 | We’ve used packages from [crates.io](https://crates.io/)<!-- ignore --> as |
13cf67c4 XL |
4 | dependencies of our project, but you can also share your code with other people |
5 | by publishing your own packages. The crate registry at | |
dc9dc135 | 6 | [crates.io](https://crates.io/)<!-- ignore --> distributes the source code of |
13cf67c4 XL |
7 | your packages, so it primarily hosts code that is open source. |
8 | ||
9 | Rust and Cargo have features that help make your published package easier for | |
10 | people to use and to find in the first place. We’ll talk about some of these | |
11 | features next and then explain how to publish a package. | |
12 | ||
13 | ### Making Useful Documentation Comments | |
14 | ||
15 | Accurately documenting your packages will help other users know how and when to | |
16 | use them, so it’s worth investing the time to write documentation. In Chapter | |
17 | 3, we discussed how to comment Rust code using two slashes, `//`. Rust also has | |
18 | a particular kind of comment for documentation, known conveniently as a | |
19 | *documentation comment*, that will generate HTML documentation. The HTML | |
20 | displays the contents of documentation comments for public API items intended | |
21 | for programmers interested in knowing how to *use* your crate as opposed to how | |
22 | your crate is *implemented*. | |
23 | ||
24 | Documentation comments use three slashes, `///`, instead of two and support | |
25 | Markdown notation for formatting the text. Place documentation comments just | |
26 | before the item they’re documenting. Listing 14-1 shows documentation comments | |
27 | for an `add_one` function in a crate named `my_crate`: | |
28 | ||
29 | <span class="filename">Filename: src/lib.rs</span> | |
30 | ||
31 | ```rust,ignore | |
74b04a01 | 32 | {{#rustdoc_include ../listings/ch14-more-about-cargo/listing-14-01/src/lib.rs}} |
13cf67c4 XL |
33 | ``` |
34 | ||
35 | <span class="caption">Listing 14-1: A documentation comment for a | |
36 | function</span> | |
37 | ||
38 | Here, we give a description of what the `add_one` function does, start a | |
39 | section with the heading `Examples`, and then provide code that demonstrates | |
40 | how to use the `add_one` function. We can generate the HTML documentation from | |
41 | this documentation comment by running `cargo doc`. This command runs the | |
42 | `rustdoc` tool distributed with Rust and puts the generated HTML documentation | |
43 | in the *target/doc* directory. | |
44 | ||
45 | For convenience, running `cargo doc --open` will build the HTML for your | |
46 | current crate’s documentation (as well as the documentation for all of your | |
47 | crate’s dependencies) and open the result in a web browser. Navigate to the | |
48 | `add_one` function and you’ll see how the text in the documentation comments is | |
49 | rendered, as shown in Figure 14-1: | |
50 | ||
51 | <img alt="Rendered HTML documentation for the `add_one` function of `my_crate`" src="img/trpl14-01.png" class="center" /> | |
52 | ||
53 | <span class="caption">Figure 14-1: HTML documentation for the `add_one` | |
54 | function</span> | |
55 | ||
56 | #### Commonly Used Sections | |
57 | ||
58 | We used the `# Examples` Markdown heading in Listing 14-1 to create a section | |
59 | in the HTML with the title “Examples.” Here are some other sections that crate | |
60 | authors commonly use in their documentation: | |
61 | ||
62 | * **Panics**: The scenarios in which the function being documented could | |
63 | panic. Callers of the function who don’t want their programs to panic should | |
64 | make sure they don’t call the function in these situations. | |
65 | * **Errors**: If the function returns a `Result`, describing the kinds of | |
66 | errors that might occur and what conditions might cause those errors to be | |
67 | returned can be helpful to callers so they can write code to handle the | |
68 | different kinds of errors in different ways. | |
69 | * **Safety**: If the function is `unsafe` to call (we discuss unsafety in | |
70 | Chapter 19), there should be a section explaining why the function is unsafe | |
71 | and covering the invariants that the function expects callers to uphold. | |
72 | ||
73 | Most documentation comments don’t need all of these sections, but this is a | |
74 | good checklist to remind you of the aspects of your code that people calling | |
75 | your code will be interested in knowing about. | |
76 | ||
77 | #### Documentation Comments as Tests | |
78 | ||
79 | Adding example code blocks in your documentation comments can help demonstrate | |
80 | how to use your library, and doing so has an additional bonus: running `cargo | |
81 | test` will run the code examples in your documentation as tests! Nothing is | |
82 | better than documentation with examples. But nothing is worse than examples | |
83 | that don’t work because the code has changed since the documentation was | |
84 | written. If we run `cargo test` with the documentation for the `add_one` | |
85 | function from Listing 14-1, we will see a section in the test results like this: | |
86 | ||
74b04a01 XL |
87 | <!-- manual-regeneration |
88 | cd listings/ch14-more-about-cargo/listing-14-01/ | |
89 | cargo test | |
90 | copy just the doc-tests section below | |
91 | --> | |
92 | ||
13cf67c4 XL |
93 | ```text |
94 | Doc-tests my_crate | |
95 | ||
96 | running 1 test | |
97 | test src/lib.rs - add_one (line 5) ... ok | |
98 | ||
99 | test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out | |
100 | ``` | |
101 | ||
102 | Now if we change either the function or the example so the `assert_eq!` in the | |
103 | example panics and run `cargo test` again, we’ll see that the doc tests catch | |
104 | that the example and the code are out of sync with each other! | |
105 | ||
106 | #### Commenting Contained Items | |
107 | ||
108 | Another style of doc comment, `//!`, adds documentation to the item that | |
109 | contains the comments rather than adding documentation to the items following | |
110 | the comments. We typically use these doc comments inside the crate root file | |
111 | (*src/lib.rs* by convention) or inside a module to document the crate or the | |
112 | module as a whole. | |
113 | ||
114 | For example, if we want to add documentation that describes the purpose of the | |
115 | `my_crate` crate that contains the `add_one` function, we can add documentation | |
116 | comments that start with `//!` to the beginning of the *src/lib.rs* file, as | |
117 | shown in Listing 14-2: | |
118 | ||
119 | <span class="filename">Filename: src/lib.rs</span> | |
120 | ||
121 | ```rust,ignore | |
74b04a01 | 122 | {{#rustdoc_include ../listings/ch14-more-about-cargo/listing-14-02/src/lib.rs:here}} |
13cf67c4 XL |
123 | ``` |
124 | ||
125 | <span class="caption">Listing 14-2: Documentation for the `my_crate` crate as a | |
126 | whole</span> | |
127 | ||
128 | Notice there isn’t any code after the last line that begins with `//!`. Because | |
129 | we started the comments with `//!` instead of `///`, we’re documenting the item | |
130 | that contains this comment rather than an item that follows this comment. In | |
131 | this case, the item that contains this comment is the *src/lib.rs* file, which | |
132 | is the crate root. These comments describe the entire crate. | |
133 | ||
134 | When we run `cargo doc --open`, these comments will display on the front | |
135 | page of the documentation for `my_crate` above the list of public items in the | |
136 | crate, as shown in Figure 14-2: | |
137 | ||
138 | <img alt="Rendered HTML documentation with a comment for the crate as a whole" src="img/trpl14-02.png" class="center" /> | |
139 | ||
140 | <span class="caption">Figure 14-2: Rendered documentation for `my_crate`, | |
141 | including the comment describing the crate as a whole</span> | |
142 | ||
143 | Documentation comments within items are useful for describing crates and | |
144 | modules especially. Use them to explain the overall purpose of the container to | |
145 | help your users understand the crate’s organization. | |
146 | ||
147 | ### Exporting a Convenient Public API with `pub use` | |
148 | ||
149 | In Chapter 7, we covered how to organize our code into modules using the `mod` | |
150 | keyword, how to make items public using the `pub` keyword, and how to bring | |
151 | items into a scope with the `use` keyword. However, the structure that makes | |
152 | sense to you while you’re developing a crate might not be very convenient for | |
153 | your users. You might want to organize your structs in a hierarchy containing | |
154 | multiple levels, but then people who want to use a type you’ve defined deep in | |
155 | the hierarchy might have trouble finding out that type exists. They might also | |
156 | be annoyed at having to enter `use` | |
157 | `my_crate::some_module::another_module::UsefulType;` rather than `use` | |
158 | `my_crate::UsefulType;`. | |
159 | ||
160 | The structure of your public API is a major consideration when publishing a | |
161 | crate. People who use your crate are less familiar with the structure than you | |
162 | are and might have difficulty finding the pieces they want to use if your crate | |
163 | has a large module hierarchy. | |
164 | ||
165 | The good news is that if the structure *isn’t* convenient for others to use | |
166 | from another library, you don’t have to rearrange your internal organization: | |
167 | instead, you can re-export items to make a public structure that’s different | |
168 | from your private structure by using `pub use`. Re-exporting takes a public | |
169 | item in one location and makes it public in another location, as if it were | |
170 | defined in the other location instead. | |
171 | ||
172 | For example, say we made a library named `art` for modeling artistic concepts. | |
173 | Within this library are two modules: a `kinds` module containing two enums | |
174 | named `PrimaryColor` and `SecondaryColor` and a `utils` module containing a | |
175 | function named `mix`, as shown in Listing 14-3: | |
176 | ||
177 | <span class="filename">Filename: src/lib.rs</span> | |
178 | ||
fc512014 XL |
179 | ```rust,noplayground,test_harness |
180 | {{#rustdoc_include ../listings/ch14-more-about-cargo/listing-14-03/src/lib.rs}} | |
13cf67c4 XL |
181 | ``` |
182 | ||
183 | <span class="caption">Listing 14-3: An `art` library with items organized into | |
184 | `kinds` and `utils` modules</span> | |
185 | ||
186 | Figure 14-3 shows what the front page of the documentation for this crate | |
187 | generated by `cargo doc` would look like: | |
188 | ||
189 | <img alt="Rendered documentation for the `art` crate that lists the `kinds` and `utils` modules" src="img/trpl14-03.png" class="center" /> | |
190 | ||
191 | <span class="caption">Figure 14-3: Front page of the documentation for `art` | |
192 | that lists the `kinds` and `utils` modules</span> | |
193 | ||
194 | Note that the `PrimaryColor` and `SecondaryColor` types aren’t listed on the | |
195 | front page, nor is the `mix` function. We have to click `kinds` and `utils` to | |
196 | see them. | |
197 | ||
198 | Another crate that depends on this library would need `use` statements that | |
199 | bring the items from `art` into scope, specifying the module structure that’s | |
200 | currently defined. Listing 14-4 shows an example of a crate that uses the | |
201 | `PrimaryColor` and `mix` items from the `art` crate: | |
202 | ||
203 | <span class="filename">Filename: src/main.rs</span> | |
204 | ||
205 | ```rust,ignore | |
74b04a01 | 206 | {{#rustdoc_include ../listings/ch14-more-about-cargo/listing-14-04/src/main.rs}} |
13cf67c4 XL |
207 | ``` |
208 | ||
209 | <span class="caption">Listing 14-4: A crate using the `art` crate’s items with | |
210 | its internal structure exported</span> | |
211 | ||
212 | The author of the code in Listing 14-4, which uses the `art` crate, had to | |
213 | figure out that `PrimaryColor` is in the `kinds` module and `mix` is in the | |
214 | `utils` module. The module structure of the `art` crate is more relevant to | |
215 | developers working on the `art` crate than to developers using the `art` crate. | |
216 | The internal structure that organizes parts of the crate into the `kinds` | |
217 | module and the `utils` module doesn’t contain any useful information for | |
218 | someone trying to understand how to use the `art` crate. Instead, the `art` | |
219 | crate’s module structure causes confusion because developers have to figure out | |
220 | where to look, and the structure is inconvenient because developers must | |
221 | specify the module names in the `use` statements. | |
222 | ||
223 | To remove the internal organization from the public API, we can modify the | |
224 | `art` crate code in Listing 14-3 to add `pub use` statements to re-export the | |
225 | items at the top level, as shown in Listing 14-5: | |
226 | ||
227 | <span class="filename">Filename: src/lib.rs</span> | |
228 | ||
229 | ```rust,ignore | |
74b04a01 | 230 | {{#rustdoc_include ../listings/ch14-more-about-cargo/listing-14-05/src/lib.rs:here}} |
13cf67c4 XL |
231 | ``` |
232 | ||
233 | <span class="caption">Listing 14-5: Adding `pub use` statements to re-export | |
234 | items</span> | |
235 | ||
236 | The API documentation that `cargo doc` generates for this crate will now list | |
237 | and link re-exports on the front page, as shown in Figure 14-4, making the | |
238 | `PrimaryColor` and `SecondaryColor` types and the `mix` function easier to find. | |
239 | ||
240 | <img alt="Rendered documentation for the `art` crate with the re-exports on the front page" src="img/trpl14-04.png" class="center" /> | |
241 | ||
242 | <span class="caption">Figure 14-4: The front page of the documentation for `art` | |
243 | that lists the re-exports</span> | |
244 | ||
245 | The `art` crate users can still see and use the internal structure from Listing | |
246 | 14-3 as demonstrated in Listing 14-4, or they can use the more convenient | |
247 | structure in Listing 14-5, as shown in Listing 14-6: | |
248 | ||
249 | <span class="filename">Filename: src/main.rs</span> | |
250 | ||
251 | ```rust,ignore | |
74b04a01 | 252 | {{#rustdoc_include ../listings/ch14-more-about-cargo/listing-14-06/src/main.rs:here}} |
13cf67c4 XL |
253 | ``` |
254 | ||
255 | <span class="caption">Listing 14-6: A program using the re-exported items from | |
256 | the `art` crate</span> | |
257 | ||
258 | In cases where there are many nested modules, re-exporting the types at the top | |
259 | level with `pub use` can make a significant difference in the experience of | |
260 | people who use the crate. | |
261 | ||
262 | Creating a useful public API structure is more of an art than a science, and | |
263 | you can iterate to find the API that works best for your users. Choosing `pub | |
264 | use` gives you flexibility in how you structure your crate internally and | |
265 | decouples that internal structure from what you present to your users. Look at | |
266 | some of the code of crates you’ve installed to see if their internal structure | |
267 | differs from their public API. | |
268 | ||
269 | ### Setting Up a Crates.io Account | |
270 | ||
271 | Before you can publish any crates, you need to create an account on | |
dc9dc135 XL |
272 | [crates.io](https://crates.io/)<!-- ignore --> and get an API token. To do so, |
273 | visit the home page at [crates.io](https://crates.io/)<!-- ignore --> and log in | |
13cf67c4 XL |
274 | via a GitHub account. (The GitHub account is currently a requirement, but the |
275 | site might support other ways of creating an account in the future.) Once | |
276 | you’re logged in, visit your account settings at | |
277 | [https://crates.io/me/](https://crates.io/me/)<!-- ignore --> and retrieve your | |
278 | API key. Then run the `cargo login` command with your API key, like this: | |
279 | ||
f035d41b | 280 | ```console |
13cf67c4 XL |
281 | $ cargo login abcdefghijklmnopqrstuvwxyz012345 |
282 | ``` | |
283 | ||
284 | This command will inform Cargo of your API token and store it locally in | |
285 | *~/.cargo/credentials*. Note that this token is a *secret*: do not share it | |
286 | with anyone else. If you do share it with anyone for any reason, you should | |
dc9dc135 | 287 | revoke it and generate a new token on [crates.io](https://crates.io/)<!-- ignore |
13cf67c4 XL |
288 | -->. |
289 | ||
290 | ### Adding Metadata to a New Crate | |
291 | ||
292 | Now that you have an account, let’s say you have a crate you want to publish. | |
293 | Before publishing, you’ll need to add some metadata to your crate by adding it | |
294 | to the `[package]` section of the crate’s *Cargo.toml* file. | |
295 | ||
296 | Your crate will need a unique name. While you’re working on a crate locally, | |
297 | you can name a crate whatever you’d like. However, crate names on | |
dc9dc135 | 298 | [crates.io](https://crates.io/)<!-- ignore --> are allocated on a first-come, |
13cf67c4 | 299 | first-served basis. Once a crate name is taken, no one else can publish a crate |
9fa01778 XL |
300 | with that name. Before attempting to publish a crate, search for the name you |
301 | want to use on the site. If the name has been used by another crate, you will | |
302 | need to find another name and edit the `name` field in the *Cargo.toml* file | |
303 | under the `[package]` section to use the new name for publishing, like so: | |
13cf67c4 XL |
304 | |
305 | <span class="filename">Filename: Cargo.toml</span> | |
306 | ||
307 | ```toml | |
308 | [package] | |
309 | name = "guessing_game" | |
310 | ``` | |
311 | ||
312 | Even if you’ve chosen a unique name, when you run `cargo publish` to publish | |
313 | the crate at this point, you’ll get a warning and then an error: | |
314 | ||
74b04a01 XL |
315 | <!-- manual-regeneration |
316 | cd listings/ch14-more-about-cargo/listing-14-01/ | |
317 | cargo publish | |
318 | copy just the relevant lines below | |
319 | --> | |
320 | ||
f035d41b | 321 | ```console |
13cf67c4 | 322 | $ cargo publish |
74b04a01 XL |
323 | Updating crates.io index |
324 | warning: manifest has no description, license, license-file, documentation, homepage or repository. | |
325 | See https://doc.rust-lang.org/cargo/reference/manifest.html#package-metadata for more info. | |
13cf67c4 | 326 | --snip-- |
74b04a01 | 327 | error: api errors (status 200 OK): missing or empty metadata fields: description, license. Please see https://doc.rust-lang.org/cargo/reference/manifest.html for how to upload metadata |
13cf67c4 XL |
328 | ``` |
329 | ||
330 | The reason is that you’re missing some crucial information: a description and | |
331 | license are required so people will know what your crate does and under what | |
332 | terms they can use it. To rectify this error, you need to include this | |
333 | information in the *Cargo.toml* file. | |
334 | ||
335 | Add a description that is just a sentence or two, because it will appear with | |
336 | your crate in search results. For the `license` field, you need to give a | |
337 | *license identifier value*. The [Linux Foundation’s Software Package Data | |
338 | Exchange (SPDX)][spdx] lists the identifiers you can use for this value. For | |
339 | example, to specify that you’ve licensed your crate using the MIT License, add | |
340 | the `MIT` identifier: | |
341 | ||
342 | [spdx]: http://spdx.org/licenses/ | |
343 | ||
344 | <span class="filename">Filename: Cargo.toml</span> | |
345 | ||
346 | ```toml | |
347 | [package] | |
348 | name = "guessing_game" | |
349 | license = "MIT" | |
350 | ``` | |
351 | ||
352 | If you want to use a license that doesn’t appear in the SPDX, you need to place | |
353 | the text of that license in a file, include the file in your project, and then | |
354 | use `license-file` to specify the name of that file instead of using the | |
355 | `license` key. | |
356 | ||
357 | Guidance on which license is appropriate for your project is beyond the scope | |
358 | of this book. Many people in the Rust community license their projects in the | |
359 | same way as Rust by using a dual license of `MIT OR Apache-2.0`. This practice | |
360 | demonstrates that you can also specify multiple license identifiers separated | |
361 | by `OR` to have multiple licenses for your project. | |
362 | ||
363 | With a unique name, the version, the author details that `cargo new` added | |
364 | when you created the crate, your description, and a license added, the | |
365 | *Cargo.toml* file for a project that is ready to publish might look like this: | |
366 | ||
367 | <span class="filename">Filename: Cargo.toml</span> | |
368 | ||
369 | ```toml | |
370 | [package] | |
371 | name = "guessing_game" | |
372 | version = "0.1.0" | |
373 | authors = ["Your Name <you@example.com>"] | |
69743fb6 | 374 | edition = "2018" |
13cf67c4 XL |
375 | description = "A fun game where you guess what number the computer has chosen." |
376 | license = "MIT OR Apache-2.0" | |
377 | ||
378 | [dependencies] | |
379 | ``` | |
380 | ||
381 | [Cargo’s documentation](https://doc.rust-lang.org/cargo/) describes other | |
382 | metadata you can specify to ensure others can discover and use your crate more | |
383 | easily. | |
384 | ||
385 | ### Publishing to Crates.io | |
386 | ||
387 | Now that you’ve created an account, saved your API token, chosen a name for | |
388 | your crate, and specified the required metadata, you’re ready to publish! | |
389 | Publishing a crate uploads a specific version to | |
dc9dc135 | 390 | [crates.io](https://crates.io/)<!-- ignore --> for others to use. |
13cf67c4 XL |
391 | |
392 | Be careful when publishing a crate because a publish is *permanent*. The | |
393 | version can never be overwritten, and the code cannot be deleted. One major | |
dc9dc135 | 394 | goal of [crates.io](https://crates.io/)<!-- ignore --> is to act as a permanent |
13cf67c4 | 395 | archive of code so that builds of all projects that depend on crates from |
dc9dc135 | 396 | [crates.io](https://crates.io/)<!-- ignore --> will continue to work. Allowing |
13cf67c4 XL |
397 | version deletions would make fulfilling that goal impossible. However, there is |
398 | no limit to the number of crate versions you can publish. | |
399 | ||
400 | Run the `cargo publish` command again. It should succeed now: | |
401 | ||
74b04a01 XL |
402 | <!-- manual-regeneration |
403 | go to some valid crate, publish a new version | |
404 | cargo publish | |
405 | copy just the relevant lines below | |
406 | --> | |
407 | ||
f035d41b | 408 | ```console |
13cf67c4 | 409 | $ cargo publish |
74b04a01 XL |
410 | Updating crates.io index |
411 | Packaging guessing_game v0.1.0 (file:///projects/guessing_game) | |
412 | Verifying guessing_game v0.1.0 (file:///projects/guessing_game) | |
413 | Compiling guessing_game v0.1.0 | |
13cf67c4 | 414 | (file:///projects/guessing_game/target/package/guessing_game-0.1.0) |
74b04a01 XL |
415 | Finished dev [unoptimized + debuginfo] target(s) in 0.19s |
416 | Uploading guessing_game v0.1.0 (file:///projects/guessing_game) | |
13cf67c4 XL |
417 | ``` |
418 | ||
419 | Congratulations! You’ve now shared your code with the Rust community, and | |
420 | anyone can easily add your crate as a dependency of their project. | |
421 | ||
422 | ### Publishing a New Version of an Existing Crate | |
423 | ||
424 | When you’ve made changes to your crate and are ready to release a new version, | |
425 | you change the `version` value specified in your *Cargo.toml* file and | |
426 | republish. Use the [Semantic Versioning rules][semver] to decide what an | |
427 | appropriate next version number is based on the kinds of changes you’ve made. | |
428 | Then run `cargo publish` to upload the new version. | |
429 | ||
430 | [semver]: http://semver.org/ | |
431 | ||
432 | ### Removing Versions from Crates.io with `cargo yank` | |
433 | ||
434 | Although you can’t remove previous versions of a crate, you can prevent any | |
435 | future projects from adding them as a new dependency. This is useful when a | |
436 | crate version is broken for one reason or another. In such situations, Cargo | |
437 | supports *yanking* a crate version. | |
438 | ||
439 | Yanking a version prevents new projects from starting to depend on that version | |
440 | while allowing all existing projects that depend on it to continue to download | |
441 | and depend on that version. Essentially, a yank means that all projects with a | |
442 | *Cargo.lock* will not break, and any future *Cargo.lock* files generated will | |
443 | not use the yanked version. | |
444 | ||
445 | To yank a version of a crate, run `cargo yank` and specify which version you | |
446 | want to yank: | |
447 | ||
f035d41b | 448 | ```console |
13cf67c4 XL |
449 | $ cargo yank --vers 1.0.1 |
450 | ``` | |
451 | ||
452 | By adding `--undo` to the command, you can also undo a yank and allow projects | |
453 | to start depending on a version again: | |
454 | ||
f035d41b | 455 | ```console |
13cf67c4 XL |
456 | $ cargo yank --vers 1.0.1 --undo |
457 | ``` | |
458 | ||
459 | A yank *does not* delete any code. For example, the yank feature is not | |
460 | intended for deleting accidentally uploaded secrets. If that happens, you must | |
461 | reset those secrets immediately. |