| title | Workspaces |
|---|---|
| slug | workspaces |
- Rust workspaces provide a convenient way to manage multiple related crates together as a single project or monorepo.
- A Rust workspace uses a shared
Cargo.lockfile and a commontargetdirectory to efficiently build and manage shared dependencies, reducing build times. - Cargo commands such as
cargo test,cargo build,cargo check,cargo fmt,cargo clippy, andcargo cleancan be run once from the workspace root to apply to all workspace members.
Let's build a sample Rust workspace with two simple crates.
[!lab]
mkdir my_project && cd my_project echo -e "[workspace]\nresolver = \"3\"" > ./Cargo.toml cargo new app_bar && cargo new app_buzz cargo add uuid -F v7 -p app_bar && cargo add uuid -F v7 -p app_buzz echo 'fn main() { \tprintln!("Bar ID: {}", uuid::Uuid::now_v7()); }' > app_bar/src/main.rs echo 'fn main() { \tprintln!("Buzz ID: {}", uuid::Uuid::now_v7()); }' > app_buzz/src/main.rs
my_project
├── app_bar
│ ├── Cargo.toml
│ └── src
│ └── main.rs
├── app_buzz
│ ├── Cargo.toml
│ └── src
│ └── main.rs
├── Cargo.lock
└── Cargo.toml{{< tabs count=3 label="Select File" >}} {{< tab label="app_bar → main.rs" >}}
fn main() {
println!("Bar ID: {}", uuid::Uuid::now_v7());
}{{< /tab >}} {{< tab label="app_buzz → main.rs" >}}
fn main() {
println!("Buzz ID: {}", uuid::Uuid::now_v7());
}{{< /tab >}} {{< tab label="Cargo.toml" >}}
[workspace]
resolver = "3"
members = ["app_bar", "app_buzz"]{{< /tab >}} {{< /tabs >}}
As you can see,
- Cargo commands can automatically add workspace members to the
Cargo.tomlfile in the workspace root(my_project). - Try running
cargo buildand observe how each dependency is compiled only once through the sharedtargetdirectory in the workspace root.
[!assignment]
- Examine the
Cargo.tomlfiles in the workspace root and in each crate, and identify the main tables(sections) they contain.- Examine the
Cargo.lockfile in the workspace root and identify how theapp_buzzandapp_barcrates record their dependencies.- Run
cargo run -p app_barandcargo run -p app_buzzcommands from the workspace root.
[!lab]
mkdir my_project2 && cd my_project2 echo -e "[workspace]\nresolver = \"3\"\nmembers = [\"crates/*\"]" > ./Cargo.toml cargo new crates/bar && cargo new crates/buzz cargo new crates/common --lib
my_project
├── crates
│ ├── bar
│ │ ├── Cargo.toml
│ │ └── src
│ │ └── main.rs
│ ├── buzz
│ │ ├── Cargo.toml
│ │ └── src
│ │ └── main.rs
│ └── common
│ ├── Cargo.toml
│ └── src
│ └── lib.rs
├── Cargo.toml
└── Cargo.lock- To use the
commoncrate fromcrates/barandcrates/buzz,- We have to add
commoncrate as a dependency in bothcrates/bar/Cargo.tomlandcrates/buzz/Cargo.toml.[dependencies] common = { path = "../common" }
- Then, we can use the
commoncrate like any other dependency incrates/barandcrates/buzz.fn main() { let x = common::add(1, 1); println!("{x}"); }
- We have to add
{{< tabs count=3 label="Select File" >}} {{< tab label="bar → Cargo.toml" >}}
[package]
name = "bar"
version = "0.1.0"
edition = "2024"
[dependencies]
common = { path = "../common" }{{< /tab >}} {{< tab label="buzz → Cargo.toml" >}}
[package]
name = "buzz"
version = "0.1.0"
edition = "2024"
[dependencies]
common = { path = "../common" }{{< /tab >}} {{< tab label="my_project2 → Cargo.toml" >}}
[workspace]
resolver = "3"
members = ["crates/*"]{{< /tab >}} {{< /tabs >}}
- rust-lang/rust library folder is a good example for a workspace. Explore and identify Rust library workspace structure.