
Cargo Workflows
- 329 installs
- 155 repo stars
- Updated June 27, 2026
- mohitmishra786/low-level-dev-skills
Structure Cargo workspaces, feature flags, publishing, cross-compilation, and repeatable local/CI workflows for Rust libraries and binaries.
About
Documents idiomatic Cargo workflows for Rust projects: workspace structuring, feature and target configuration, bench/test pipelines, cross-compilation, publishing crates, and keeping local developer commands aligned with CI build steps.
- Workspace member layout
- Feature flag design
- Cross-target builds
- crate publish flow
- Reproducible CI scripts
Cargo Workflows by the numbers
- 329 all-time installs (skills.sh)
- +25 installs in the week ending Aug 4, 2026 (Skillselion tracking)
- Ranked #35 of 121 Rust skills by installs in the Skillselion catalog
- Data as of Aug 4, 2026 (Skillselion catalog sync)
npx skills add https://github.com/mohitmishra786/low-level-dev-skills --skill cargo-workflowsAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 329 |
|---|---|
| repo stars | ★ 155 |
| Last updated | June 27, 2026 |
| Repository | mohitmishra786/low-level-dev-skills ↗ |
What it does
Structure Cargo workspaces, feature flags, publishing, cross-compilation, and repeatable local/CI workflows for Rust libraries and binaries.
Files
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 root Cargo.toml
[workspace]
members = [
"crates/core",
"crates/cli",
"crates/server",
"tools/codegen",
]
resolver = "2" # Feature resolver v2 (required for edition 2021)
# Shared dependency versions (workspace.dependencies)
[workspace.dependencies]
serde = { version = "1", features = ["derive"] }
tokio = { version = "1", features = ["full"] }
anyhow = "1"
# Shared profile settings
[profile.release]
lto = "thin"
codegen-units = 1# Member Cargo.toml
[package]
name = "myapp-core"
version.workspace = true
edition.workspace = true
[dependencies]
serde.workspace = true # Inherit from workspace
anyhow.workspace = true2. Feature flags
[features]
default = ["std"]
# Simple flag
std = []
# Feature that enables another feature
full = ["std", "async", "serde-support"]
# Feature with optional dependency
async = ["dep:tokio"]
serde-support = ["dep:serde", "serde/derive"]
[dependencies]
tokio = { version = "1", optional = true }
serde = { version = "1", optional = true }# Build with specific features
cargo build --features "async,serde-support"
# Build with no default features
cargo build --no-default-features
# Build with all features
cargo build --all-features
# Check feature combinations
cargo check --no-default-features
cargo check --all-featuresFeature 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_depsyntax (edition 2021) to avoid implicit feature creation
3. Build scripts (build.rs)
// build.rs (at crate root, runs before compilation)
use std::env;
use std::path::PathBuf;
fn main() {
// Re-run if these files change
println!("cargo:rerun-if-changed=build.rs");
println!("cargo:rerun-if-changed=wrapper.h");
println!("cargo:rerun-if-env-changed=MY_LIB_PATH");
// Link a system library
println!("cargo:rustc-link-lib=mylib");
println!("cargo:rustc-link-search=/usr/local/lib");
// Pass a cfg flag to Rust code
let target = env::var("TARGET").unwrap();
if target.contains("linux") {
println!("cargo:rustc-cfg=target_os_linux");
}
// Set environment variable for downstream crates
println!("cargo:rustc-env=MY_GENERATED_VAR=value");
// Generate bindings with bindgen
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
# GitHub Actions with sccache
- uses: Swatinem/rust-cache@v2
with:
cache-on-failure: true
shared-key: "release-build"
# Or manual cache
- uses: actions/cache@v3
with:
path: |
~/.cargo/registry/index/
~/.cargo/registry/cache/
~/.cargo/git/db/
target/
key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }}# Warm cache locally
cargo fetch # Download all deps without building
cargo build --tests # Build everything including test bins
# Check if incremental hurts release builds (it often does)
[profile.release]
incremental = false # Default; leave false for release5. cargo nextest (faster test runner)
# Install
cargo install cargo-nextest
# Run tests (parallel by default, better output)
cargo nextest run
# Run with specific filter
cargo nextest run test_name_pattern
# List tests without running
cargo nextest list
# Use in CI (JUnit output)
cargo nextest run --profile cinextest.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
# Check for security advisories
cargo install cargo-audit
cargo audit
# Deny specific licenses, duplicates, advisories
cargo install cargo-deny
cargo deny check
# Check for unused dependencies
cargo install cargo-machete
cargo machete
# Update dependencies
cargo update # Update to compatible versions
cargo update -p serde # Update single package
cargo upgrade # Update to latest (cargo-edit)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 = [] # List advisory IDs to ignore7. Useful cargo commands
# Build only specific binary
cargo build --bin myapp
# Build only specific example
cargo build --example myexample
# Run with arguments
cargo run -- --flag arg1 arg2
# Expand macros (for debugging proc macros)
cargo install cargo-expand
cargo expand module::path
# Tree of dependencies
cargo tree
cargo tree --duplicates # Show crates with multiple versions
cargo tree -i serde # Who depends on serde?
# Cargo.toml metadata
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-basicsfor compiler flags and profile configuration - Use
skills/rust/rust-debuggingfor debugging Cargo-built binaries - Use
skills/rust/rust-ffiforbuild.rswith C library bindings - Use
skills/build-systems/cmakewhen integrating Rust into a CMake build
Cargo Workspace Patterns Reference
Workspace Dependency Management
Centralizing versions
# Root Cargo.toml
[workspace.dependencies]
# Pin all workspace members to same versions
tokio = { version = "1.35", features = ["full"] }
serde = { version = "1.0", features = ["derive"] }
tracing = "0.1"
anyhow = "1.0"
thiserror = "1.0"
[workspace.package]
version = "0.1.0"
edition = "2021"
authors = ["team@example.com"]
license = "MIT OR Apache-2.0"
repository = "https://github.com/org/repo"# Member Cargo.toml
[package]
name = "myapp-core"
version.workspace = true
edition.workspace = true
authors.workspace = true
license.workspace = true
[dependencies]
tokio.workspace = true # Inherit, including features
serde = { workspace = true, features = ["derive"] } # Can add featuresFeature Resolution (resolver = "2")
With resolver = "2" (required in edition 2021 workspaces):
[workspace]
resolver = "2"- Build deps, dev-deps, and regular deps get independent feature resolution
- Prevents a dev-only dependency from enabling features in prod builds
target.cfg()conditional features respected independently
Virtual Manifest Pattern
A workspace without its own [package] — just orchestrates members:
# Root Cargo.toml (virtual manifest)
[workspace]
members = ["crates/*", "tools/*"]
resolver = "2"
[workspace.package]
version = "0.1.0"
edition = "2021"
[profile.release]
lto = "thin"Useful for monorepos where the root is not a published crate.
Path vs Registry Dependencies
[dependencies]
# Path (local development)
mylib = { path = "../mylib" }
# Registry (published)
mylib = { version = "1.0" }
# Git (unpublished / fork)
mylib = { git = "https://github.com/user/mylib", branch = "main" }
mylib = { git = "https://github.com/user/mylib", rev = "abc1234" }
# Override registry dep with local path (for development)
# In root Cargo.toml:
[patch.crates-io]
serde = { path = "../my-serde-fork" }Selective Build Commands
# Build only specific workspace member
cargo build -p myapp-core
cargo build -p myapp-cli --release
# Test specific member
cargo test -p myapp-core
# Test all members
cargo test --workspace
# Build all members
cargo build --workspace
# Exclude member
cargo build --workspace --exclude myapp-codegenCargo.lock Management
# Libraries: Cargo.lock in .gitignore (let users choose versions)
# Applications: Cargo.lock in version control (reproducible builds)
# Generate deterministic lock file
cargo generate-lockfile
# Update single dep
cargo update -p tokio --precise 1.35.1
# Show what would change
cargo update --dry-runCI Configuration Patterns
GitHub Actions matrix
strategy:
matrix:
rust: [stable, beta, nightly]
os: [ubuntu-latest, macos-latest, windows-latest]
steps:
- uses: dtolnay/rust-toolchain@master
with:
toolchain: ${{ matrix.rust }}
components: rustfmt, clippy
- uses: Swatinem/rust-cache@v2
- run: cargo check --workspace --all-features
- run: cargo test --workspace
- run: cargo clippy --workspace -- -D warnings
- run: cargo fmt --checkMSRV (minimum supported Rust version)
[package]
rust-version = "1.70" # MSRV declaration
[workspace.package]
rust-version = "1.70"# Test against MSRV
rustup install 1.70
cargo +1.70 check --workspacePublished Crate Checklist
[package]
name = "mycrate"
version = "1.0.0"
edition = "2021"
description = "Short description"
license = "MIT OR Apache-2.0"
repository = "https://github.com/..."
documentation = "https://docs.rs/mycrate"
readme = "README.md"
keywords = ["systems", "async"]
categories = ["network-programming"]
exclude = ["tests/fixtures/**", ".github/**"]# Verify what will be published
cargo package --list
# Dry run publish
cargo publish --dry-run
# Publish to crates.io
cargo publish