Phase 5Practical project

#20 Publishing

cargo publish, docs, crates.io

Documentation comments

Rust has first-class documentation support. Use /// for documenting the item that follows. These comments support full Markdown syntax:

Documenting functions
/// Adds two numbers together.
///
/// # Arguments
///
/// * `a` - The first number
/// * `b` - The second number
///
/// # Returns
///
/// The sum of `a` and `b`.
///
/// # Examples
///
/// ```
/// let result = my_crate::add(2, 3);
/// assert_eq!(result, 5);
/// ```
pub fn add(a: i32, b: i32) -> i32 {
    a + b
}

Use //! for documenting the enclosing item (typically the crate or module):

Crate-level documentation (src/lib.rs)
//! # My Crate
//!
//! `my_crate` is a collection of utilities for
//! performing mathematical operations.
//!
//! ## Quick Start
//!
//! ```rust
//! use my_crate::add;
//!
//! let sum = add(1, 2);
//! assert_eq!(sum, 3);
//! ```

/// Adds two numbers together.
pub fn add(a: i32, b: i32) -> i32 {
    a + b
}

/// Multiplies two numbers.
pub fn multiply(a: i32, b: i32) -> i32 {
    a * b
}

Code examples in doc comments are automatically run as tests by cargo test, ensuring your documentation stays up to date!

Generating docs

Cargo generates beautiful HTML documentation from your doc comments:

Generating documentation
# Generate and open docs in browser
cargo doc --open

# Generate docs including dependencies
cargo doc --open --document-private-items

# Generate docs for your crate only (faster)
cargo doc --no-deps --open

The generated documentation is placed in target/doc/. When you publish to crates.io, documentation is automatically built and hosted at docs.rs/your-crate-name.

Common doc sections that Rust developers expect:

Standard doc sections
/// Brief description of the function.
///
/// More detailed explanation if needed.
///
/// # Arguments     -- describe parameters
/// # Returns       -- describe return value
/// # Errors        -- describe error conditions
/// # Panics        -- describe when it panics
/// # Safety        -- for unsafe functions
/// # Examples      -- usage examples (tested!)

Cargo.toml metadata

Before publishing, your Cargo.toml needs proper metadata:

Complete Cargo.toml
[package]
name = "my-crate"
version = "0.1.0"
edition = "2021"
authors = ["Your Name <you@example.com>"]
description = "A short description of what this crate does"
license = "MIT OR Apache-2.0"
repository = "https://github.com/username/my-crate"
homepage = "https://github.com/username/my-crate"
documentation = "https://docs.rs/my-crate"
readme = "README.md"
keywords = ["math", "utility", "example"]
categories = ["mathematics"]

[dependencies]
# your dependencies here

The required fields for publishing are: name, version, description, and license (or license-file). keywords and categories help users find your crate. You can have at most 5 keywords.

Publishing to crates.io

Follow these steps to publish your crate:

Publishing workflow
# 1. Create an account on crates.io (login with GitHub)
# 2. Get your API token from https://crates.io/settings/tokens

# 3. Login with your token
cargo login your-api-token-here

# 4. Verify your package looks correct
cargo package

# 5. Do a dry run to check everything
cargo publish --dry-run

# 6. Publish for real!
cargo publish

Important: once a version is published, it cannot be modified or deleted. You can only yank a version, which prevents new projects from depending on it but does not remove it.

Yanking a version
# Yank a version (no new dependents)
cargo yank --vers 0.1.0

# Undo a yank
cargo yank --vers 0.1.0 --undo

Versioning

Rust crates follow Semantic Versioning (SemVer): MAJOR.MINOR.PATCH.

SemVer rules
# Given version X.Y.Z:
#
# X (MAJOR) - Increment for incompatible API changes
#   0.1.0 -> 1.0.0  (first stable release)
#   1.0.0 -> 2.0.0  (breaking change)
#
# Y (MINOR) - Increment for new features (backwards compatible)
#   1.0.0 -> 1.1.0  (new function added)
#   1.1.0 -> 1.2.0  (new module added)
#
# Z (PATCH) - Increment for bug fixes (backwards compatible)
#   1.0.0 -> 1.0.1  (bug fix)
#   1.0.1 -> 1.0.2  (another fix)
#
# Pre-1.0 (0.x.y): minor version bumps may include breaking changes

In Cargo.toml, dependency version requirements follow these patterns:

Version requirements in Cargo.toml
[dependencies]
# Caret (default): compatible updates
serde = "1.0"       # >= 1.0.0, < 2.0.0
serde = "1.0.104"   # >= 1.0.104, < 2.0.0

# Tilde: patch-level updates only
log = "~1.0"        # >= 1.0.0, < 1.1.0
log = "~1.0.5"      # >= 1.0.5, < 1.1.0

# Exact version
rand = "=0.8.5"     # exactly 0.8.5

# Wildcard
regex = "1.*"       # >= 1.0.0, < 2.0.0

# Range
clap = ">=3.0, <5.0"

Summary

Quick reference
/// Doc comment (item)         // Markdown supported
//! Doc comment (module/crate)  // At top of file

cargo doc --open               // Generate & view docs
cargo package                  // Create package
cargo publish --dry-run        // Test publish
cargo publish                  // Publish to crates.io
cargo yank --vers 0.1.0        // Yank a version

# Cargo.toml required fields:
# name, version, description, license

# SemVer: MAJOR.MINOR.PATCH
# Breaking change -> MAJOR
# New feature     -> MINOR
# Bug fix         -> PATCH

Your turn

Try generating documentation with cargo doc --open, packaging your crate with cargo package, and doing a dry run with cargo publish --dry-run:

terminal — cargo
user@stemlegacy:~/my-crate$