---
title: Workspace and Project Management
url: https://doc.liz6.com/en/rust/09-cargo-and-build/03-workspace-and-project-management
locale: en
area: rust
tags:
- rust
- cargo-and-build
date: null
modified: 2026-07-16
description: Workspace and Project Management When a project contains multiple interdependent crates (such as a core library + API server + CLI), a workspace allows them to …
---

# Workspace and Project Management

> When a project contains multiple interdependent crates (such as a core library + API server + CLI), a workspace allows them to share the same Cargo.lock and target directory—enabling compilation cache reuse and unified dependency versions. The [patch] feature allows temporarily replacing a dependency's source code during development, while build.rs executes code generation before compilation.

## Workspace: Multiple Crates in a Single Repository

When a project contains multiple interdependent crates (such as a core library + API server + CLI), placing them in a workspace offers three main benefits:

```toml
[workspace]
members = ["crates/core", "crates/api", "crates/cli"]
resolver = "2"
```

1. **Shared build artifacts**: All members share a single `target/` directory—dependencies are compiled only once, significantly reducing disk usage and compilation time.
2. **Consistent versions**: `Cargo.lock` is shared at the workspace level—every member sees the same versions of dependencies.
3. **Internal cross-referencing**: `api` can directly reference `core` using `path = "../../crates/core"` (no need to publish to crates.io).

## [workspace.dependencies]: Shared Version Declarations

Starting with version 1.64, you can declare versions in the root `Cargo.toml`, and members can reference them by key:

```toml
[workspace.dependencies]
serde = "1"
tokio = { version = "1", features = ["full"] }

# Each member: [dependencies] → serde = { workspace = true }
```

This solves the classic problem in multi-crate projects where dependency versions are scattered across various files, leading to missed updates during upgrades. Change the version in one place, and all members update accordingly.

## [patch]: Temporarily Replace Dependencies

When an upstream crate has a bug and you need to use a fork until the upstream fixes it:

```toml
[patch.crates-io]
serde = { git = "https://github.com/myfork/serde", branch = "fix" }
```

Note: The version specified in `[patch]` must be globally compatible within the workspace—if one member depends on `serde 1.0` and another on `serde 1.3`, the fork must satisfy the API requirements of both. This is why forks should ideally only modify internal logic and not public APIs.

## Advanced build.rs

```rust
// build.rs — executed before compiling the main code
fn main() {
    // Rerun conditions: only rerun when these conditions change
    println!("cargo:rerun-if-changed=src/c/wrapper.h");
    println!("cargo:rerun-if-env-changed=MY_LIB_PATH");

    // Link system libraries
    println!("cargo:rustc-link-search=native={}", my_lib_dir);
    println!("cargo:rustc-link-lib=static=my_lib");

    // Pass cfg flags to the main code — enables #[cfg(has_avx2)]
    println!("cargo:rustc-cfg=has_avx2");
}
```

build.rs is commonly used for: compiling C/C++ dependencies (via the `cc` crate), detecting the presence of system libraries, generating code (e.g., protobuf, OpenAPI), and setting feature flags.

## References

- **Cargo Book**: workspaces, build scripts
- **cc crate**: docs.rs/cc

*Keywords: workspace, members, patch, build.rs, shared dependencies, multi-crate, Cargo.lock*
