| name | cargo-workflows |
| description | Cargo workflow skill for Rust projects. Use when managing workspaces, feature flags, build scripts, cargo cache, incremental builds, dependency auditing, or CI configuration with Cargo. Activates on queries about cargo workspaces, Cargo.toml features, build.rs, cargo nextest, cargo deny, cargo check vs build, or Cargo.lock management. |
Cargo Workflows
Purpose
Guide agents through Cargo workspaces, feature management, build scripts (build.rs), CI integration, incremental compilation, and the Cargo tool ecosystem.
Triggers
- "How do I set up a Cargo workspace with multiple crates?"
- "How do features work in Cargo?"
- "How do I write a build.rs script?"
- "How do I speed up Cargo builds in CI?"
- "How do I audit my Rust dependencies?"
- "What is cargo nextest and should I use it?"
Workflow
1. Workspace setup
my-project/
├── Cargo.toml # Workspace root
├── Cargo.lock # Single lock file for all members
├── crates/
│ ├── core/
│ │ └── Cargo.toml
│ ├── cli/
│ │ └── Cargo.toml
│ └── server/
│ └── Cargo.toml
└── tools/
└── codegen/
└── Cargo.toml
[workspace]
members = [
"crates/core",
"crates/cli",
"crates/server",
"tools/codegen",
]
resolver = "2"
[workspace.dependencies]
serde = { version = "1", features = ["derive"] }
tokio = { version = "1", features = ["full"] }
anyhow = "1"
[profile.release]
lto = "thin"
codegen-units = 1
[package]
name = "myapp-core"
version.workspace = true
edition.workspace = true
[dependencies]
serde.workspace = true
anyhow.workspace = true
2. Feature flags
[features]
default = ["std"]
std = []
full = ["std", "async", "serde-support"]
async = ["dep:tokio"]
serde-support = ["dep:serde", "serde/derive"]
[dependencies]
tokio = { version = "1", optional = true }
serde = { version = "1", optional = true }
cargo build --features "async,serde-support"
cargo build --no-default-features
cargo build --all-features
cargo check --no-default-features
cargo check --all-features
Feature gotchas:
- Features are additive: once enabled anywhere in the dependency graph, they stay enabled
resolver = "2" prevents feature leakage between dev-dependencies and regular deps
- Use
dep:optional_dep syntax (edition 2021) to avoid implicit feature creation
3. Build scripts (build.rs)
use std::env;
use std::path::PathBuf;
fn main() {
println!("cargo:rerun-if-changed=build.rs");
println!("cargo:rerun-if-changed=wrapper.h");
println!("cargo:rerun-if-env-changed=MY_LIB_PATH");
println!("cargo:rustc-link-lib=mylib");
println!("cargo:rustc-link-search=/usr/local/lib");
let target = env::var("TARGET").unwrap();
if target.contains("linux") {
println!("cargo:rustc-cfg=target_os_linux");
}
println!("cargo:rustc-env=MY_GENERATED_VAR=value");
let bindings = bindgen::Builder::default()
.header("wrapper.h")
.generate()
.expect("Unable to generate bindings");
let out_path = PathBuf::from(env::var("OUT_DIR").unwrap());
bindings.write_to_file(out_path.join("bindings.rs")).unwrap();
}
println! directive | Effect |
|---|
cargo:rerun-if-changed=FILE | Re-run build script if file changes |
cargo:rerun-if-env-changed=VAR | Re-run if env var changes |
cargo:rustc-link-lib=NAME | Link library |
cargo:rustc-link-search=PATH | Add library search path |
cargo:rustc-cfg=FLAG | Enable #[cfg(FLAG)] in code |
cargo:rustc-env=KEY=VAL | Set env!("KEY") at compile time |
cargo:warning=MSG | Emit build warning |
4. Incremental builds and CI caching
- uses: Swatinem/rust-cache@v2
with:
cache-on-failure: true
shared-key: "release-build"
- uses: actions/cache@v3
with:
path: |
~/.cargo/registry/index/
~/.cargo/registry/cache/
~/.cargo/git/db/
target/
key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }}
cargo fetch
cargo build --tests
[profile.release]
incremental = false
5. cargo nextest (faster test runner)
cargo install cargo-nextest
cargo nextest run
cargo nextest run test_name_pattern
cargo nextest list
cargo nextest run --profile ci
nextest.toml:
[profile.ci]
fail-fast = false
test-threads = "num-cpus"
retries = { backoff = "exponential", count = 2, delay = "1s" }
[profile.default]
test-threads = "num-cpus"
6. Dependency management and auditing
cargo install cargo-audit
cargo audit
cargo install cargo-deny
cargo deny check
cargo install cargo-machete
cargo machete
cargo update
cargo update -p serde
cargo upgrade
deny.toml:
[licenses]
allow = ["MIT", "Apache-2.0", "BSD-2-Clause", "BSD-3-Clause"]
deny = ["GPL-2.0", "AGPL-3.0"]
[bans]
multiple-versions = "warn"
deny = [{ name = "openssl", reason = "Use rustls instead" }]
[advisories]
ignore = []
7. Useful cargo commands
cargo build --bin myapp
cargo build --example myexample
cargo run -- --flag arg1 arg2
cargo install cargo-expand
cargo expand module::path
cargo tree
cargo tree --duplicates
cargo tree -i serde
cargo metadata --format-version 1 | jq '.packages[].name'
For workspace patterns and dependency resolution details, see references/workspace-patterns.md.
Related skills
- Use
skills/rust/rustc-basics for compiler flags and profile configuration
- Use
skills/rust/rust-debugging for debugging Cargo-built binaries
- Use
skills/rust/rust-ffi for build.rs with C library bindings
- Use
skills/build-systems/cmake when integrating Rust into a CMake build