23.4 Cargo.toml

The Cargo.toml file serves as the manifest for each package, written in TOML format. It includes all the metadata needed to compile the package.

23.4.1 Structure

A typical Cargo.toml might look like:

[package]
name = "my_project"
version = "0.1.0"
edition = "2021"
authors = ["Your Name <you@example.com>"]
description = "A brief description of your crate"
license = "MIT OR Apache-2.0"
repository = "https://github.com/yourname/my_project"

[dependencies]
serde = "1.0"
rand = "0.8"

[dev-dependencies]
quickcheck = "1.0"

[features]
# Optional features can be declared here.

[profile.dev]
# Customize debug builds here.

[profile.release]
# Customize release builds here.
  • [package]: Defines package metadata (name, version, edition, license, etc.).
  • [dependencies]: Lists runtime dependencies (usually from Crates.io).
  • [dev-dependencies]: Dependencies for tests, benchmarks, or development tools.
  • [profile.*]: Customizes debug and release builds.

If you plan to publish on Crates.io, ensure [package] includes all required metadata (e.g., license, description, version).

23.4.2 Managing Dependencies

Cargo automatically resolves and fetches dependencies declared in Cargo.toml.

Adding Dependencies Manually

Include a dependency by name and version (using Semantic Versioning):

[dependencies]
serde = "1.0"

Cargo fetches the crate from Crates.io if it’s not already downloaded.

Semantic Versioning (SemVer) in Cargo

  • "1.2.3" or "^1.2.3": Accepts bugfix and minor updates in 1.x (>=1.2.3, <2.0.0).
  • "~1.2.3": Restricts updates to the same minor version (>=1.2.3, <1.3.0).
  • "=1.2.3": Requires exactly 1.2.3.
  • ">=1.2.3, <1.5.0": Uses a version range.

Updating vs. Upgrading

  • Update: cargo update pulls the latest compatible versions based on current constraints (updating only Cargo.lock).
  • Upgrade: Loosens constraints or bumps major versions in Cargo.toml, then runs cargo update. This changes both Cargo.toml and Cargo.lock.

Cargo.lock

  • Cargo.lock records exact version information (including transitive dependencies).
  • Commit Cargo.lock for applications/binaries to ensure consistent builds across environments.
  • For library crates, maintaining Cargo.lock is optional. Library consumers usually manage their own lock files. Some library authors still commit it for consistent CI builds.

Checking for Outdated Dependencies

Install and run cargo-outdated to see out-of-date crates:

cargo install cargo-outdated
cargo outdated

This is helpful for planning version upgrades.

Alternative Sources and Features

You can fetch crates from Git repositories or local paths:

[dependencies]
my_crate = { git = "https://github.com/user/my_crate" }

Enable optional features in a dependency:

[dependencies]
serde = { version = "1.0", features = ["derive"] }

This activates extra functionality, like auto-deriving Serialize and Deserialize.