Rust Workspaces

In Rust, workspaces are a way to organize multiple packages (crates) into a single project with a shared Cargo.lock and output directory (target/). This is especially useful for large projects with multiple components, such as libraries and binaries, that need to share code or build settings.


🧱 What Is a Workspace?

A workspace is a set of one or more member crates (packages) managed together by Cargo.

  • It has a single root Cargo.toml (called the workspace manifest) that defines the workspace.
  • Each member crate has its own Cargo.toml.
  • All members share the same Cargo.lock and target/ directory.

πŸ“ Basic Structure

Here’s an example of a typical workspace layout:

my_workspace/
β”œβ”€β”€ Cargo.toml            # Workspace root (workspace manifest)
β”œβ”€β”€ members/
β”‚   β”œβ”€β”€ my_lib/
β”‚   β”‚   └── Cargo.toml    # A library crate
β”‚   └── my_app/
β”‚       └── Cargo.toml    # A binary crate
└── target/               # Shared build output directory

πŸ› οΈ Workspace Root Cargo.toml

[workspace]
members = [
    "members/my_lib",
    "members/my_app"
]

You can also use globs:

[workspace]
members = ["members/*"]

πŸ“¦ Member Crates

Each member crate still has its own Cargo.toml, like this for my_lib:

[package]
name = "my_lib"
version = "0.1.0"
edition = "2021"

[dependencies]

And for my_app:

[package]
name = "my_app"
version = "0.1.0"
edition = "2021"

[dependencies]

my_lib = { path = “../my_lib” } # Use the workspace member


βœ… Benefits of Workspaces

  • Single build directory (target/) saves build time.
  • Shared Cargo.lock ensures consistent dependency versions across all crates.
  • Ideal for monorepos: libraries, apps, plugins in one repo.
  • Easier testing: you can test the whole workspace with cargo test.

πŸš€ Common Commands

  • cargo build (in workspace root) builds all members.
  • cargo build -p my_app builds just one member.
  • cargo test, cargo check, etc. also work similarly.

πŸ”’ Optional Members

You can have crates in your repository that are not part of the workspace using exclude:

[workspace]
members = ["members/*"]
exclude = ["members/experimental_crate"]

πŸ§ͺ Example Use Case

A real-world example could be:

  • core – a reusable library.
  • cli – a command-line interface binary.
  • web – a web server binary.
  • tools/gen_docs – an internal documentation tool.

All living in one repo, built and tested together.