Cargo.toml for a Rust Project
Cargo.toml is to Rust what package.json is to Node.js — the manifest file that defines everything about a Rust project. It specifies the package metadata used by crates.io (Rust's package registry), lists runtime and development dependencies with their version constraints, enables optional feature flags, and configures compilation profiles for development and release builds. The TOML format is Cargo's choice of configuration language: human-readable, unambiguous, and well-typed. This example defines a typical Rust binary application (CLI tool) with six production dependencies and one development dependency. The dependencies block uses SemVer version requirements: "1" means "compatible with 1.x.x" (the caret requirement, equivalent to "^1"). tokio is Rust's async runtime and the most commonly used dependency in networked Rust applications. serde and serde_json provide serialization and deserialization. clap handles command-line argument parsing. anyhow provides ergonomic error handling. reqwest is the HTTP client for making API calls. The features key within a dependency declaration enables optional functionality that the crate hides behind feature flags: tokio = { version = "1", features = ["full"] } enables all of Tokio's features including networking, file I/O, and the full async runtime. serde = { version = "1", features = ["derive"] } enables the derive macros (#[derive(Serialize, Deserialize)]) that automatically implement serialization for your types. The [dev-dependencies] section lists packages needed only for testing and benchmarking, not included in the final compiled binary. tokio-test provides async testing utilities that work with Tokio's runtime, enabling you to write async test functions. The [profile.release] section configures the optimized release build. opt-level = 3 enables maximum optimization (the default for release builds). lto = true enables Link-Time Optimization, which allows the compiler to optimize across crate boundaries — it can take significantly longer to compile but often produces 10-30% smaller and faster binaries. codegen-units = 1 prevents parallel code generation, allowing more optimization opportunities at the cost of compile time. strip = true removes debug symbols from the binary, reducing its size by 50-80% for distribution. Real-world scenarios: publishing a CLI tool to crates.io where binary size matters for download speed; building a high-performance network service where LTO shaves critical milliseconds; setting up a project for a team where consistent feature flags prevent "it works on my machine" issues. Tips: use cargo update to update dependencies to the latest compatible versions, then commit the updated Cargo.lock to ensure reproducible builds across machines and CI. Use cargo tree to visualize your dependency graph and identify transitive dependencies.
[package] name = "my-app" version = "0.1.0" edition = "2021" authors = ["Your Name <[email protected]>"] description = "A fast CLI tool" license = "MIT" [dependencies] tokio = { version = "1", features = ["full"] } serde = { version = "1", features = ["derive"] } serde_json = "1" clap = { version = "4", features = ["derive"] } anyhow = "1" reqwest = { version = "0.11", features = ["json"] } [dev-dependencies] tokio-test = "0.4" [profile.release] opt-level = 3 lto = true codegen-units = 1 strip = true
FAQ
- What is the difference between dependencies and dev-dependencies?
- dependencies are compiled into your final binary. dev-dependencies are only compiled for tests and benchmarks, reducing production binary size and build time.
- How do Cargo features work?
- Features are opt-in functionality flags. Crates can gate code behind features, and consumers enable them in Cargo.toml. This avoids compiling unused code and reduces binary size.
- What does strip = true do in the release profile?
- strip = true removes debug symbols from the compiled binary, reducing its file size significantly. Stripped binaries cannot be debugged with a source-level debugger but are smaller for distribution.
Related Examples
TypeScript's strict mode is the single highest-leverage configuration option for...
EditorConfig for a Multi-Language ProjectEditorConfig is a cross-editor configuration standard that solves a practical te...
Maven pom.xml for a Java ProjectMaven's pom.xml (Project Object Model) is the build configuration, dependency ma...