Cargo and Package Management
Packages and Crates
In Rust terminology, a crate is a single compilation unit passed to rustc (producing either a library or an executable binary), whereas a package is a bundle of one or more crates defined by a single Cargo.toml file.
+-------------------------------------------------------------------+
| Cargo Package (`Cargo.toml`) |
| |
| +---------------------------+ +-----------------------------+ |
| | Library Crate (Max 1) | | Binary Crates (0 or more) | |
| | Crate Root: src/lib.rs | | - src/main.rs | |
| | Produces: libmy_pkg.rlib| | - src/bin/worker.rs | |
| +---------------------------+ | - src/bin/migrator.rs | |
| ^ +-----------------------------+ |
| | | |
| +------ Links automatically -----+ |
+-------------------------------------------------------------------+
Rules Connecting Packages, Crates, and Modules
| Concept | Definition | Cardinality & Rules |
|---|---|---|
Module (mod) |
A namespace unit inside a crate controlling item paths and privacy (pub). |
A crate contains a tree of 1 or more modules rooted at the crate root (lib.rs or main.rs). Does not define a compilation boundary on its own. |
| Crate | A single compilation unit compiled by one invocation of rustc. |
Either a library crate (--crate-type lib) or a binary crate (--crate-type bin). |
| Package | A Cargo.toml manifest and all the targets it builds. |
Must contain at least 1 crate (library or binary), at most 1 library crate, and any number of binary crates. |
| Workspace | A collection of related packages sharing a single Cargo.lock and target/ directory. |
Contains 1 or more member packages. |
How Binary Crates Use the Package's Library Crate
When a package contains both src/lib.rs and src/main.rs (say, in a package named image-tools), Cargo compiles two separate crates:
- First, Cargo compiles
src/lib.rsas the library crateimage_tools. - Second, Cargo compiles
src/main.rsas the binary crateimage-tools, linkingimage_toolsas an external crate dependency.
Note that src/main.rs must import items from src/lib.rs using the library crate's public name (use image_tools::...)—not crate::...—because src/main.rs has its own separate crate root!
// Simulating the separation between the library crate and binary crate root:
pub mod image_tools_lib {
#[derive(Debug, PartialEq, Eq)]
pub struct Dimensions {
pub width: u32,
pub height: u32,
}
pub fn aspect_ratio(dim: &Dimensions) -> f64 {
f64::from(dim.width) / f64::from(dim.height)
}
}
fn main() {
// In `src/main.rs`, the binary imports public items from the library crate:
use image_tools_lib::{Dimensions, aspect_ratio};
let hd = Dimensions {
width: 1920,
height: 1080,
};
println!("1920x1080 aspect ratio: {:.4}", aspect_ratio(&hd));
}
1920x1080 aspect ratio: 1.7778
All Target Crate Types inside a Single Package
A single Cargo package can contain up to five kinds of compilation targets:
- Library (
[lib]):src/lib.rs(at most one). - Binaries (
[[bin]]):src/main.rsandsrc/bin/*.rs. - Examples (
[[example]]):examples/*.rs(compiled withcargo build --examplesor run viacargo run --example <name>). - Integration Tests (
[[test]]):tests/*.rs(compiled duringcargo test). - Benchmarks (
[[bench]]):benches/*.rs(compiled duringcargo bench).