DEV Community

Cover image for Further Understanding Cargo and Crates.io
John Wilson
John Wilson

Posted on

Further Understanding Cargo and Crates.io

In Rust, "release profiles" are predefined and customizable sets of settings with different options that allow programmers to control compilation options flexibly. Each profile is independent.

Cargo mainly has two profiles: the dev profile used when running cargo build, and the release profile used when running cargo build --release. The dev profile is the default suitable for development, while the release profile is suitable for building optimized release binaries.

You may see these names in the build output:

$ cargo build
   Compiling cargo1 v0.1.0 (/rust/cargo1)
    Finished dev [unoptimized + debuginfo] target(s) in 0.67s
$ cargo build --release
   Compiling cargo1 v0.1.0 (/rust/cargo1)
    Finished release [optimized] target(s) in 0.11s
Enter fullscreen mode Exit fullscreen mode

The output shows dev and release, indicating that the compiler is using different settings.

If you do not explicitly add [profile.] sections in your project's Cargo.toml, Cargo uses default settings for all profiles. You can override any subset by adding the corresponding [profile.] section. For example, the default opt-level values for dev and release are:

[profile.dev]
opt-level = 0

[profile.release]
opt-level = 3
Enter fullscreen mode Exit fullscreen mode

The opt-level controls how much optimization Rust applies to the code. It ranges from 0 to 3. Higher optimization levels increase compile time, so during development you may prefer faster compile times at the cost of less optimization. Hence, dev has default opt-level of 0. Release builds, intended to be compiled once and run multiple times, benefit from more optimization, so release defaults to opt-level 3.

You can override defaults in Cargo.toml. For example, to use optimization level 1 for development builds:

[profile.dev]
opt-level = 1
Enter fullscreen mode Exit fullscreen mode

This will increase optimization in dev builds but not as aggressively as the release profile.

Documentation Comments

Documentation comments start with triple slashes /// and support Markdown. They must be placed immediately before the item being documented. Create a new project:

$ cargo new learn_cratel
$ cd learn_cratel
$ cargo new mylib --lib
Enter fullscreen mode Exit fullscreen mode

Open mylib's lib.rs and add a documentation comment to the default add function:

/// Adds two usize values
pub fn add(left: usize, right: usize) -> usize {
    left + right
}
Enter fullscreen mode Exit fullscreen mode

Run cargo doc to generate HTML documentation from the comments. This calls rustdoc and outputs docs into target/doc.

Running cargo doc --open builds the docs and opens them in your browser. You can see how the documentation renders when following the add function.

You can add more detailed comments:

/// Adds two numbers
/// # Example
/// ```
{% endraw %}

/// let left = 1;  
/// let right = 2;  
/// assert_eq!(3, mylib::add(left, right));  
///
{% raw %}
Enter fullscreen mode Exit fullscreen mode

pub fn add(left: usize, right: usize) -> usize {
left + right
}



Here, the description and an example section demonstrate how to use the add function.


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/y97jpolgd562kthxae6a.webp)

### Testing Documentation Examples
The sample code inside doc comments also acts as tests. cargo test runs these docs tests to help make sure examples don't break after code changes. Running cargo test produces:



Enter fullscreen mode Exit fullscreen mode

Doc-tests mylib

running 1 test
test src/lib.rs - add (line 3) ... ok

test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.18s



If an example assertion fails, cargo test reports it as a failure.

### Inner Documentation Comments

The //! style documents the enclosing item itself and appears at the beginning of files, commonly at crate root (src/lib.rs) or module roots. It documents the crate or module as a whole.

Example in src/lib.rs:



Enter fullscreen mode Exit fullscreen mode

//! # My Crate
//!
//! learn_cratel is a utility collection

/// Adds two numbers
/// # Example
/// ```

/// let left = 1;

/// let right = 2;

/// assert_eq!(3, mylib::add(left, right));

///

pub fn add(left: usize, right: usize) -> usize {
    left + right
}
Enter fullscreen mode Exit fullscreen mode

//! comments appear on the crate's top-level documentation page above the list of public items when running cargo doc --open.

Publishing Crates to Crates.io

We have used dependencies from crates.io, but you can also publish your own crates to share code with others. crates.io is a distribution platform for open-source Rust code.

Create a Crates.io Account

Before publishing, you need an account and an API token from crates.io. Log in using your GitHub account (currently the only supported login). Get your token from https://crates.io/me/.

Then run:

$ cargo login your_api_token
Enter fullscreen mode Exit fullscreen mode

This stores your token in ~/.cargo/credentials. Keep this token secret.

Publish to Crates.io

Once logged in, publish a specific crate version to make it available for others to depend on.

Publishing is permanent; versions cannot be overwritten or deleted. This preserves stable code for dependent projects. Version numbers follow semantic versioning but you can publish any version.

If you run cargo publish and see an error like:

Caused by:
  the remote server responded with an error: missing or empty metadata fields: description, license. Please see https://doc.rust-lang.org/cargo/reference/manifest.html for how to upload metadata
Enter fullscreen mode Exit fullscreen mode

It means description and license fields are missing in your Cargo.toml. Add them:

description = "This is a test project"
license = "MIT OR Apache-2.0"
Enter fullscreen mode Exit fullscreen mode

Publish again, and it should succeed:

$ cargo publish
    Updating crates.io index
warning: manifest has no documentation, homepage or repository.
See https://doc.rust-lang.org/cargo/reference/manifest.html#package-metadata for more info.
   Packaging mylib-hekang v0.1.0 (/rust/learn_cratel/mylib)
   Verifying mylib-hekang v0.1.0 (/rust/learn_cratel/mylib)
   Compiling mylib-hekang v0.1.0 (/rust/learn_cratel/mylib/target/package/mylib-hekang-0.1.0)
    Finished dev [unoptimized + debuginfo] target(s) in 0.84s
    Packaged 3 files, 1.3KiB (901.0B compressed)
   Uploading mylib-hekang v0.1.0 (/rust/learn_cratel/mylib)
    Updating crates.io index
    Waiting on `mylib-hekang` to propagate to crates.io index (ctrl-c to wait asynchronously)
    Updating crates.io index
...
Enter fullscreen mode Exit fullscreen mode

Now your code is shared with the Rust community, and anyone can add it as a dependency.

Publishing New Versions

When updating your crate, increment the version in Cargo.toml following semantic versioning and run cargo publish again.

Yank Crate Versions

You cannot remove published versions but can "yank" them to mark them as deprecated for new projects. Existing projects using that version continue to work, but new dependencies won’t use it.

To yank version 0.1.0:

$ cargo yank --vers 0.1.0
    Updating crates.io index
    Yank [email protected]
Enter fullscreen mode Exit fullscreen mode

To undo the yank:

$ cargo yank --vers 0.1.0 --undo
    Updating crates.io index
    Unyank [email protected]
Enter fullscreen mode Exit fullscreen mode

Yanking does not delete code; if secrets were published accidentally, regenerate new versions with fixes.

Top comments (0)