cargo-workflows

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Cargo Workflows

Cargo工作流

Purpose

目的

Guide agents through Cargo workspaces, feature management, build scripts (
build.rs
), CI integration, incremental compilation, and the Cargo tool ecosystem.
引导Agent完成Cargo工作区、特性管理、构建脚本(build.rs)、CI集成、增量编译以及Cargo工具生态系统的相关操作。

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?"
  • "如何设置包含多个crate的Cargo工作区?"
  • "Cargo中的特性是如何工作的?"
  • "如何编写build.rs脚本?"
  • "如何在CI中加速Cargo构建?"
  • "如何审计我的Rust依赖?"
  • "什么是cargo nextest,我应该使用它吗?"

Workflow

工作流

1. Workspace setup

1. 工作区设置

text
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
toml
undefined
text
my-project/
├── Cargo.toml           # 工作区根目录
├── Cargo.lock           # 所有成员共享一个锁文件
├── crates/
│   ├── core/
│   │   └── Cargo.toml
│   ├── cli/
│   │   └── Cargo.toml
│   └── server/
│       └── Cargo.toml
└── tools/
    └── codegen/
        └── Cargo.toml
toml
undefined

Workspace root Cargo.toml

工作区根目录的Cargo.toml

[workspace] members = [ "crates/core", "crates/cli", "crates/server", "tools/codegen", ] resolver = "2" # Feature resolver v2 (required for edition 2021)
[workspace] members = [ "crates/core", "crates/cli", "crates/server", "tools/codegen", ] resolver = "2" # 特性解析器v2(2021版本要求)

Shared dependency versions (workspace.dependencies)

共享依赖版本(workspace.dependencies)

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

Shared profile settings

共享配置文件设置

[profile.release] lto = "thin" codegen-units = 1

```toml
[profile.release] lto = "thin" codegen-units = 1

```toml

Member Cargo.toml

成员Cargo.toml

[package] name = "myapp-core" version.workspace = true edition.workspace = true
[dependencies] serde.workspace = true # Inherit from workspace anyhow.workspace = true
undefined
[package] name = "myapp-core" version.workspace = true edition.workspace = true
[dependencies] serde.workspace = true # 从工作区继承 anyhow.workspace = true
undefined

2. Feature flags

2. 特性标志

toml
[features]
default = ["std"]
toml
[features]
default = ["std"]

Simple flag

简单标志

std = []
std = []

Feature that enables another feature

启用其他特性的特性

full = ["std", "async", "serde-support"]
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 }

```bash
async = ["dep:tokio"] serde-support = ["dep:serde", "serde/derive"]
[dependencies] tokio = { version = "1", optional = true } serde = { version = "1", optional = true }

```bash

Build with specific features

使用特定特性构建

cargo build --features "async,serde-support"
cargo build --features "async,serde-support"

Build with no default features

不使用默认特性构建

cargo build --no-default-features
cargo build --no-default-features

Build with all features

使用所有特性构建

cargo build --all-features
cargo build --all-features

Check feature combinations

检查特性组合

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
cargo check --no-default-features cargo check --all-features

特性注意事项:

- 特性是累加的:一旦在依赖图中的任何位置启用,就会保持启用状态
- `resolver = "2"` 防止特性在开发依赖和常规依赖之间泄漏
- 使用`dep:optional_dep`语法(2021版本)避免隐式创建特性

3. Build scripts (build.rs)

3. 构建脚本(build.rs)

rust
// 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
rust
// build.rs(位于crate根目录,编译前运行)
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");

    // 向Rust代码传递cfg标志
    let target = env::var("TARGET").unwrap();
    if target.contains("linux") {
        println!("cargo:rustc-cfg=target_os_linux");
    }

    // 为下游crate设置环境变量
    println!("cargo:rustc-env=MY_GENERATED_VAR=value");

    // 使用bindgen生成绑定
    let bindings = bindgen::Builder::default()
        .header("wrapper.h")
        .generate()
        .expect("无法生成绑定");

    let out_path = PathBuf::from(env::var("OUT_DIR").unwrap());
    bindings.write_to_file(out_path.join("bindings.rs")).unwrap();
}
println!
指令
作用
cargo:rerun-if-changed=FILE
若文件更改则重新运行构建脚本
cargo:rerun-if-env-changed=VAR
若环境变量更改则重新运行
cargo:rustc-link-lib=NAME
链接库
cargo:rustc-link-search=PATH
添加库搜索路径
cargo:rustc-cfg=FLAG
在代码中启用
#[cfg(FLAG)]
cargo:rustc-env=KEY=VAL
在编译时设置
env!("KEY")
cargo:warning=MSG
发出构建警告

4. Incremental builds and CI caching

4. 增量构建与CI缓存

yaml
undefined
yaml
undefined

GitHub Actions with sccache

使用sccache的GitHub Actions

  • uses: Swatinem/rust-cache@v2 with: cache-on-failure: true shared-key: "release-build"
  • 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') }}

```bash
  • uses: actions/cache@v3 with: path: | ~/.cargo/registry/index/ ~/.cargo/registry/cache/ ~/.cargo/git/db/ target/ key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }}

```bash

Warm cache locally

本地预热缓存

cargo fetch # Download all deps without building cargo build --tests # Build everything including test bins
cargo fetch # 仅下载所有依赖而不构建 cargo build --tests # 构建所有内容包括测试二进制文件

Check if incremental hurts release builds (it often does)

检查增量构建是否影响发布构建(通常会有影响)

[profile.release] incremental = false # Default; leave false for release
undefined
[profile.release] incremental = false # 默认值;发布版本保持false
undefined

5. cargo nextest (faster test runner)

5. cargo nextest(更快的测试运行器)

bash
undefined
bash
undefined

Install

安装

cargo install cargo-nextest
cargo install cargo-nextest

Run tests (parallel by default, better output)

运行测试(默认并行,输出更友好)

cargo nextest run
cargo nextest run

Run with specific filter

使用特定过滤器运行测试

cargo nextest run test_name_pattern
cargo nextest run test_name_pattern

List tests without running

列出测试但不运行

cargo nextest list
cargo nextest list

Use in CI (JUnit output)

在CI中使用(JUnit输出)

cargo nextest run --profile ci

`nextest.toml`:

```toml
[profile.ci]
fail-fast = false
test-threads = "num-cpus"
retries = { backoff = "exponential", count = 2, delay = "1s" }

[profile.default]
test-threads = "num-cpus"
cargo nextest run --profile ci

`nextest.toml`:

```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

6. 依赖管理与审计

bash
undefined
bash
undefined

Check for security advisories

检查安全公告

cargo install cargo-audit cargo audit
cargo install cargo-audit cargo audit

Deny specific licenses, duplicates, advisories

拒绝特定许可证、重复项、公告

cargo install cargo-deny cargo deny check
cargo install cargo-deny cargo deny check

Check for unused dependencies

检查未使用的依赖

cargo install cargo-machete cargo machete
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`:

```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 ignore
cargo update # 更新到兼容版本 cargo update -p serde # 更新单个包 cargo upgrade # 更新到最新版本(需要cargo-edit)

`deny.toml`:

```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 = "使用rustls替代" }]

[advisories]
ignore = []  # 列出要忽略的公告ID

7. Useful cargo commands

7. 实用的cargo命令

bash
undefined
bash
undefined

Build only specific binary

仅构建特定二进制文件

cargo build --bin myapp
cargo build --bin myapp

Build only specific example

仅构建特定示例

cargo build --example myexample
cargo build --example myexample

Run with arguments

带参数运行

cargo run -- --flag arg1 arg2
cargo run -- --flag arg1 arg2

Expand macros (for debugging proc macros)

展开宏(用于调试过程宏)

cargo install cargo-expand cargo expand module::path
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 tree cargo tree --duplicates # 显示存在多个版本的crate cargo tree -i serde # 哪些依赖依赖serde?

Cargo.toml metadata

Cargo.toml元数据

cargo metadata --format-version 1 | jq '.packages[].name'

For workspace patterns and dependency resolution details, see [references/workspace-patterns.md](references/workspace-patterns.md).
cargo metadata --format-version 1 | jq '.packages[].name'

有关工作区模式和依赖解析的详细信息,请参阅[references/workspace-patterns.md](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
  • 有关编译器标志和配置文件配置,请使用
    skills/rust/rustc-basics
  • 有关调试Cargo构建的二进制文件,请使用
    skills/rust/rust-debugging
  • 有关使用C库绑定的build.rs,请使用
    skills/rust/rust-ffi
  • 当将Rust集成到CMake构建中时,请使用
    skills/build-systems/cmake