Skip to content

Using Cargo and Crates

Release Profiles

Release profiles allow a developer to use different configurations when compiling their code.

There are two main release profiles, dev and release. By default the dev profile is used (e.g. cargo build) while the release() profile can be toggled with --release (e.g. cargo build --release).

You can override default options and add custom profiles to your Cargo.toml by adding a [profile.*] field. For example,

toml
[profile.dev]
opt-level = 1
[profile.dev]
opt-level = 1

will change the amount of compile-time optimizations to 1 instead of the default 0 (though this change is not advised, you get the point). A full list of profile options can be found in The Cargo Book.

Publishing a Crate to Crates.io

Documentation Comments

To make documentation comments use three slashes ///. This notation provides markdown support. Docmentaion comments that use /// are compiled into HTML using cargo doc. The generated HTML can be found in the target/doc directory. A handy tool is cargo doc --open try it out.

There's another type of documentation comment: //!. This doc comment should be placed at the top of crates (e.g. at the top of the src/lib.rs file) and modules to introduce them.

Common Documentation Sections

  • Examples
  • Panics
  • Errors
  • Safety

Documentation Tests

One of the coolest features in Rust is that any code blocks in a doc comment will be run as tests. This way, you know if a code change has broken an example in your documentation. Issuing cargo test, there will be a section at the bottom that looks as follows,

rust
   Doc-tests my_crate

running 1 test
test src/lib.rs - your_test (line 5) ... ok

test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.27s
   Doc-tests my_crate

running 1 test
test src/lib.rs - your_test (line 5) ... ok

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

Just make sure that your doc test has an assert.

... Stopped at 14.2 Exporting a Convenient Public API with pub use ...

TODO: Add section on adding examples and how to run examples with cargo in your library project

Rust Project Structure

Workspaces

Structure large projects with workspaces. Workspaces allow one project to contain several libraries with dependent binaries. If you take a look at almost any reasonably sized Rust project, you'll notice the use of a workspace. To begin, move all sub-crates into separate folders and specify them in the top-level Cargo.toml.

toml
[workspace]
members = [
  "binary-one",
  "binary-two",
  "library-one",
  "library-two"
]
[workspace]
members = [
  "binary-one",
  "binary-two",
  "library-one",
  "library-two"
]

Review Chp 14.3 Cargo Workspaces for more details.

Multiple Binaryies

You can build multiple binaries with each call to cargo build in two ways.

  1. Add each binary file to the src/bin/ path.
  2. Add the following lines to your Cargo.toml for each binary file.
toml
[[bin]]
name = "client" # <- creates a 'client' binary
path = "src/client.rs"
[[bin]]
name = "client" # <- creates a 'client' binary
path = "src/client.rs"

Examples

Placing files that have a main function in the examples folder allows you to compile and run them using Cargo's example functionality. If you have the following project structure

sh
.
├── Cargo.lock
├── Cargo.toml
├── examples
   └── your-example.rs
└── src
    └── main.rs
.
├── Cargo.lock
├── Cargo.toml
├── examples
   └── your-example.rs
└── src
    └── main.rs

Then you can build and run your_example.rs with

sh
cargo build --example your-example
cargo run --example your-example
cargo build --example your-example
cargo run --example your-example