If you're starting with Rust, you've probably heard about Cargo. It’s the official package manager and build system for Rust, and it handles almost everything you need to get your Rust project up and running—from compiling code to managing dependencies. In this article, we’ll take a closer look at how dependency management works using Cargo.toml
.
What is Cargo.toml
?
When you create a new Rust project using the command:
cargo new my_project
Cargo sets up a new project directory with a file called Cargo.toml
. This file is the heart of your project configuration. It contains metadata about your project—like its name, version, and authors—and, more importantly, a list of dependencies.
Here’s a simplified example of what a Cargo.toml
might look like:
[package]
name = "my_project"
version = "0.1.0"
edition = "2021"
[dependencies]
Right now, it's empty under [dependencies]
, but this is where the magic of dependency management begins.
Adding Dependencies
Dependencies are other Rust packages (called crates) that your project uses. Most of these crates live on crates.io, Rust's central package registry.
To use a crate, you simply add it under the [dependencies]
section with the name and version. For example, if you want to use the popular HTTP client crate reqwest
, you add:
[dependencies]
reqwest = "0.11"
When you run cargo build
, Cargo will:
- Download the
reqwest
crate (if not already cached), - Download any other crates that
reqwest
depends on, - Compile everything, and
- Link them into your project.
Understanding Version Numbers
Cargo uses Semantic Versioning, a convention for versioning that helps manage updates and compatibility. Here’s a quick breakdown:
-
1.2.3
means:-
1
is the major version (breaking changes), -
2
is the minor version (new features, backward-compatible), -
3
is the patch version (bug fixes).
-
In Cargo.toml
, if you write:
serde = "1.0"
Cargo interprets this as ^1.0
, meaning it will accept any 1.x.y
version that’s compatible with 1.0.0
(but not 2.0.0
). You can pin a version more strictly if needed:
serde = "=1.0.130"
Or specify a range:
serde = ">=1.0.100, <1.1.0"
Adding Local or Git Dependencies
Besides crates.io, you can also use:
Local crates
my_utils = { path = "../my_utils" }
This is useful for code you’ve written yourself but want to share between projects.
Git repositories
my_crate = { git = "https://github.com/username/my_crate.git" }
Cargo will fetch the crate directly from the Git repository.
Features and Optional Dependencies
Some crates support optional features. You can specify them like this:
tokio = { version = "1", features = ["full"] }
Or use optional dependencies and conditionally enable them:
[dependencies]
serde = { version = "1.0", optional = true }
[features]
default = []
use_serde = ["serde"]
Final Thoughts
Cargo.toml
is a powerful and flexible way to manage dependencies in Rust. By simply editing this file and running cargo build
, you can pull in any library you need, keep your code modular, and avoid reinventing the wheel.
As your projects grow, you’ll find more advanced use cases for Cargo.toml
—like workspace management, build scripts, and custom profiles—but for now, understanding dependencies is a great first step.
If you're a software developer who enjoys exploring different technologies and techniques like this one, check out LiveAPI. It’s a super-convenient tool that lets you generate interactive API docs instantly.
LiveAPI helps you discover, understand and use APIs in large tech infrastructures with ease!
So, if you’re working with a codebase that lacks documentation, just use LiveAPI to generate it and save time!
You can instantly try it out here! 🚀
Top comments (0)
Some comments may only be visible to logged-in visitors. Sign in to view all comments.