crates.io is Rust's central package registry; cargo publish uploads a crate there after packaging it according to Cargo.toml's metadata (name, version, license, description are required). Feature flags, declared in a [features] section, let a crate make parts of its functionality optional, reducing compile time and dependency footprint for consumers who don't need everything. A Cargo workspace groups multiple crates that share a single Cargo.lock and target directory, common for a project split into a library plus one or more binaries.
Publishing a crate
Required metadata lives in Cargo.toml; publishing requires a crates.io account linked via an API token, and once a version is live it's permanent — cargo yank marks a version as "don't use this for new projects" without deleting it, since other published crates may already depend on the exact version.
[package]
name = "my_crate"
version = "0.1.0"
edition = "2024"
license = "MIT"
description = "A short description of what this crate does"$ cargo login // one-time: link your crates.io API token
$ cargo publish // packages and uploads the crateFeature flags: optional functionality
Consumers opt into features explicitly in their own Cargo.toml, keeping unused code (and its dependencies) out of builds that don't need it.
[features]
default = ["json"]
json = ["dep:serde_json"]
yaml = ["dep:serde_yaml"]
[dependencies]
serde_json = { version = "1.0", optional = true }
serde_yaml = { version = "0.9", optional = true }Workspaces: multiple crates, one build
A workspace's top-level Cargo.toml lists its member crates, which then share a single Cargo.lock (guaranteeing every member uses the same dependency versions) and a single target directory (avoiding redundant recompilation across crates).
[workspace]
members = ["app", "core", "cli"]