Cargo and crates.io

Published: January 1, 2026

Last updated: January 1, 2026

Customizing builds with release profiles

Cargo has two main profiles:
1. Dev profile - Used when you run cargo build
2. Release profile - Used when you run cargo build --release
Cargo has default settings for each of the profiles that apply if you've not overridden said settings by adding a profile.* section.

Example: Default settings for opt-level

[profile.dev]
opt-level = 0

[profile.release]
opt-level = 3

opt-level controls the number of optimizations with a range of 0 to 3.

Example: Override default opt-level for dev profile

[profile.dev]
opt-level = 1

Publishing a crate to crates.io

Documentation Comments

They use three slashes /// and generate html documentation.

Example

/// Adds one to the number given
///
/// # Examples
/// ``` 
/// let arg = 5;
/// let answer = my_crate::add_one(arg);
///
/// assert_eq!(6, answer);
///```

pub fn add_one(x: i32) -> i32 {
    x + 1
}

To generate the html documentation, run cargo doc. The generated html is at the target/doc/ directory. Running cargo doc --open builds the html for the current crate's and any dependencies' html documentation and open the result in a web browser.

The documentation makes use of Markdown. # Example creates a section.
Commonly used sections

Exporting a convenient public API with pub use

Re-exporting takes a public item in one location and makes it available in another location. Without re-exporting use::my_crate::some_module::another_module::UsefulType After re-exporting use::my_crate::UsefulType Example
With a library named art with two modules kinds and utils. The kinds module has two enums and the utils module has a mix function.

///! # Art
///!
///!A library for modelling artistic concepts

pub mod kinds {
    /// Primary colors according to the RYB mode
    pub enum PrimaryColor {
        Red,
        Yellow,
        Blue,
    }
    /// Secondary colors according to RYB model
    pub enum SecondaryColor {
        Orange,
        Green,
        Purple,
    }
}

pub mod utils {
    use crate::kinds::*;
    /// Combines two primary colors in equal amounts to create a secondary color
    pub fn mix(c1: PrimaryColor, c2: PrimaryColor) -> SecondaryColor {
        SecondaryColor::Green
    }
}

With this setup, the PrimaryColor, SecondaryColor and the mix function will not be on the front page of the documentation. To use these items, one needs to specify the full path as shown below.

use art::kinds::PrimaryColor;
use art::utils::mix;

An external user of the crate needs to figure out that the PrimaryColor is part of the kinds module and the mix function is part of the utils module. To remove the internal organization from the public API, modify the art crate to use pub use.

pub use self::kinds::PrimaryColor;
pub use self::kinds::SecondaryColor;
pub use self::utils::mix;

It's now easier to access these items.

use art::PrimaryColor;
use art::SecondaryColor;
use art::mix;

Adding metadata to a new crate

Added in Cargo.toml file under [package] section.

[package]
name = 'unique_package_name'

In addition to a unique package name (one not already used in crates.io), a description and a licence are needed for publishing a crate.

[package]
name = "unique_package_name"
version = "0.1.0"
edition = "2024"
description = "This is a package that does nothing!"
license = "MIT OR Apache-2.0"

Publishing to crates.io

Publishing a crate uploads a specific version. A publish is permanent, the version cannot be overwritten and the code cannot be deleted except under certain circumstances (which circumstances?). There is no limit to the versions of crates you can publish.

Publishing a new version of an existing crate

Change the version value in Cargo.toml file and publish the crate by running cargo publish

Deprecating versions

Deprecating a version prevents any future projects from adding the version as a new dependency.
cargo yank --vers 0.1.0 - Yank version 0.1.0
cargo yank --vers 0.1.0 --undo - Undo a yank

Cargo Workspaces

Workspace - A set of packages that share the same Cargo.lock and output directory.

Creating a workspace

  • Create a new directory for the workspace
mkdir add
cd add
  • Create a Cargo.toml file to configure the workspace. The resolver value(3) in the [workspace] section point's to the latest and greatest version of Cargo's resolver algorithm.
[workspace]
resolver = "3"
  • Create the adder binary crate
cargo new adder

This automatically adds the newly created package to the members key in the [workspace] definition.

[workspace]
resolver = "3"
members = ["adder"]

The workspace has one target directory at the top level. - Create a second package in the workspace

cargo new add_one --lib

The top-level Cargo.toml will now also include add_one in the members section.
- Add an add_one function in add_one/src/lib.rs

pub fn add_one(x: i32) -> i32 {
    x + 1
}
  • Make the adder package depend on the add_one package. In adder/Cargo.toml;
[dependencies]
add_one ={ path = "../add_one/" }
  • Use the add_one function from the add_one crate in the adder crate.
fn main() {
    let num = 5;
    println!("{num} + 1 = {}", add_one::add_one(num));
}

To specify which package in the workspace to run use -p argument and package name with cargo run. Ex: cargo run -p adder.
Running cargo test runs the tests in all the crates in the workspace.
There is only one Cargo.lock file at the top level. This ensures that all crates are using the same version of all dependencies. Cargo tries to resolve any external dependencies to one version.

cargo install - Used to install and use binary crates locally. Cargo can also be extended with custom commands.

Tags: rust