← thecodex.expert · The Codex Family of Knowledge
Rust

Cargo and Packages

Publishing a Rust crate to the world is a single command — cargo publish — and once published, a version can never be deleted, only yanked.

Rust 1.95+ crates.io Last verified:
Where this bites you

Feature flags are additive switches, and default = ["json"] means "json is on unless the consumer says otherwise". A consumer that writes default-features = false to trim its build silently turns every default feature off, including the one it needed. The crate still compiles and runs — it just takes the other branch of every #[cfg(feature = ...)], and the output changes with no error.

Rustexporter/src/lib.rs
pub fn export(value: i32) -> String {
    #[cfg(feature = "json")]
    {
        format!("{{\"value\": {}}}", value)
    }
    #[cfg(not(feature = "json"))]
    {
        format!("value={}", value)
    }
}
Rustapp/Cargo.toml
# exporter's Cargo.toml has: default = ["json"]
[dependencies]
exporter = { path = "../exporter", default-features = false }

# cargo run  ->  value=42        (expected {"value": 42})
Canonical Definition

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, and description are required, and so is a license — as either a standard SPDX identifier in the license field, or, for something crates.io's checker doesn't recognize as a standard license, a license-file pointing at the actual license text; you don't need both). 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.

RustCargo.toml
[package]
name = "my_crate"
version = "0.1.0"
edition = "2024"
license = "MIT"
description = "A short description of what this crate does"
Shellterminal
$ cargo login          # one-time: link your crates.io API token
$ cargo publish         # packages and uploads the crate

Feature 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.

RustCargo.toml
[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 }

Opting out of the defaults means opting back in to whichever ones you actually use. Naming the feature explicitly keeps the slimmer build for everything else while restoring the behaviour the app depends on:

Rustapp/Cargo.toml
[dependencies]
exporter = { path = "../exporter", default-features = false, features = ["json"] }

# cargo run  ->  {"value": 42}

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).

RustCargo.toml (workspace root)
[workspace]
members = ["app", "core", "cli"]

Sources

1
The Rust Project. The Cargo Book, "Publishing on crates.io" and "Workspaces", doc.rust-lang.org/cargo.