cargo.toml

Cargo.toml格式

1.package字段

设置包信息, cargo new <package-name>会自动生成Cargo.toml文件

[package]
name = "testA" # 包裹的名称
description = "this is a test package" # 包裹的描述
version = "0.0.1" # 软件包的版本
authors = ["Graydon Hoare", "Fnu Lnu <no-reply@rust-lang.org>"] # 该软件包的作者(此字段已弃用)
edition = '2024' # Rust版本
rust-version = "1.70" # 支持的最低Rust版本(至少需要 Rust 1.70 或更高版本)
documentation = "https://docs.rs/bitflags" # 软件包文档的 URL
readme = "README.md" # 软件包的README文件路径(相对Cargo.toml文件)
homepage = "https://serde.rs" # 软件包主页的 URL
repository = "https://github.com/rust-lang/cargo" # 软件包源代码仓库的URL
keywords = ["gamedev", "graphics"] # 包裹的关键词,最多设置5个关键字
categories = ["command-line-utilities", "development-tools::cargo-plugins"] # 包裹的类别,https://crates.io/category_slugs查询分类信息

build = "build.rs" # 构建脚本路径(相对于 Cargo.toml)
links = "my_native_lib"  # 链接的本地 C 库名称(用于与系统库交互)

## 发布操作
exclude = ["ci/", ".*", "*.md"] # 发布时排除的文件(支持 glob 模式)
include = ["src/**/*", "Cargo.toml", "LICENSE"] # 发布时显式指定只包含哪些文件(优先级高于 exclude),如果指定,默认的include规则将被忽略。

publish = false # 控制是否可发布到crates.io
publish = ["crates-io"] # 可发布到 crates.io


# 许可证设置(推荐使用第一中)
license = "MIT OR Apache-2.0" # 软件包许可证(# 使用 SPDX 标识符)
license-file = "LICENSE.txt" # 许可证文本的路径(相对Cargo.toml文件)

resolver说明

默认值1

resolver = "1"

包 A 依赖 serde = { version = "1.0", features = ["derive"] }
包 B 依赖 serde = { version = "1.0", features = ["std"] }
serde 会被同时启用 derive 和 std 特性


resolver = "2"
包 A 只在使用 serde 时启用 derive 特性
包 B 只在使用 serde 时启用 std 特性
更精确的特性控制


resolver = "3" # 需要Rust 1.84以上版本(Edition2024默认值3)
# 需要设置incompatible-rust-versions
当遇到不兼容的 Rust 版本要求时,会尝试回退到兼容的版本

[package.metadata]
resolver = { incompatible-rust-versions = "allow" } 

2.workspace字段

统一管理多个相互关联的 Rust 包(crates)。这是 Cargo 提供的一种组织大型项目的机制

2.1基础用法

[workspace]
members = ["crates/a", "crates/b"] # 必需字段,定义哪些目录下的包属于这个工作区
exclude = ["crates/deprecated"]  # 排除某些路径(不常用)
resolver = "2"                   # 控制依赖解析行为(1,2,3),和 package.resolver一样
default-members = ["crates/core"] # 默认构建的目标(当在工作区根执行 cargo build 时不指定 --all 时,默认构建的包列表)

2.2 workspace.package

所有成员包提供共享的元数据模板,成员包可以通过 workspace = true 继承

[workspace.package]
version = "0.1.0"
edition = "2021"
authors = ["author@example.com"]

crates/xxx/Cargo.toml继承

继承workspace.package

[package]
name = "my-package"
version.workspace = true    # 继承 workspace.package.version
edition.workspace = true    # 继承 workspace.package.edition

2.3 workspace.dependencies

定义全局依赖,成员包可通过{ workspace = true }引用,确保版本统一

[workspace.dependencies]
tokio = "1.0"
serde = { version = "1.0", features = ["derive"] }
my-local-crate = { path = "crates/local" }

crates/xxx/Cargo.toml继承

[dependencies]
tokio = { workspace = true }        # 使用 workspace.dependencies.tokio
my-local-crate = { workspace = true } # 使用 workspace.dependencies.my-local-crate

2.4 workspace.lints

定义全局 lint 规则,成员包可通过 [lints] workspace = true 继承

[workspace.lints.rust]
unexpected_cfgs = "warn"

[workspace.lints.clippy]
pedantic = "warn"

crates/xxx/Cargo.toml继承

[lints]
workspace = true  # 继承 workspace.lints 中的所有规则

3.dependencies

指定项目依赖关系

3.1 基本用法

[dependencies]
serde = "1.0"
tokio = { version = "1.0", features = ["full"] }

3.2 版本控制

[dependencies]
# 精确版本
serde = "1.0.197"

# 版本范围
serde = ">=1.0, <2.0"
serde = "1.0.*"  # 等同于 1.0.x

# 比较操作符
serde = "=1.0.197"  # 精确匹配
serde = ">1.0"      # 大于 1.0
serde = ">=1.0"     # 大于等于 1.0
serde = "<1.0"      # 小于 1.0
serde = "<=1.0"     # 小于等于 1.0

3.3 registry

要指定来自crates.io以外的注册表的依赖项,请将registry键设置为要使用的注册表的名称
在registry在.cargo/config.toml的配置中

[dependencies]
private-crate = { version = "1.0", registry = "my-registry" }

3.4 git仓库依赖

[dependencies]
serde = { git = "https://github.com/serde-rs/serde" }
serde = { git = "https://github.com/serde-rs/serde", rev = "abc123" }
serde = { git = "https://github.com/serde-rs/serde", tag = "v1.0.197" }
serde = { git = "https://github.com/serde-rs/serde", branch = "main" }

3.5 本地路径依赖

[dependencies]
my-local-crate = { path = "../my-local-crate" }
utils = { path = "./utils" }

3.6 功能特性(Features)

[dependencies]
tokio = { version = "1.0", features = ["rt-multi-thread", "macros"] }
serde = { version = "1.0", features = ["derive"], default-features = false }

3.7 指定平台的依赖

[target.'cfg(windows)'.dependencies]
winhttp = "0.4.0"

[target.'cfg(unix)'.dependencies]
openssl = "1.0.1"

[target.'cfg(target_arch = "x86")'.dependencies]
native-i686 = { path = "native/i686" }

[target.'cfg(target_arch = "x86_64")'.dependencies]
native-x86_64 = { path = "native/x86_64" }

3.8 package重命名

[dependencies]
foo = "0.1"
bar = { git = "https://github.com/example/project.git", package = "foo" }
baz = { version = "0.1", registry = "custom", package = "foo" }

3.9optional可选依赖

需要配合features使用

[dependencies]
# serde 不会自动被引入,除非用户明确启用相关的 feature
serde = { version = "1.0", optional = true }
[dependencies]
serde = { version = "1.0", optional = true }
serde_json = { version = "1.0", optional = true }
tokio = { version = "1.0", optional = true }

[features]
default = ["json"]  # 默认启用 json 功能
json = ["dep:serde", "dep:serde_json"]  # json 功能需要这两个库
async = ["dep:tokio"]
full = ["json", "async"]  # full 包含所有功能

3.10 build-dependencies

构建时依赖 - 仅在build.rs中使用

[build-dependencies]
cc = "1.0"  # C 编译器包装器
bindgen = "0.60"  # C/C++ 绑定生成器

3.11 dev-dependencies

只在运行测试、基准测试或文档测试时使用
cargo test、cargo bench、cargo doc、cargo check --test时测试、基准测试和文档测试的依赖

[dev-dependencies]
# 仅开发时使用的依赖
tokio-test = "0.4"          # 异步测试工具
serial_test = "2.0"         # 串行测试执行
pretty_assertions = "1.0"   # 更好的断言输出
mockito = "0.31"           # HTTP mocking
criterion = "0.5"          # 基准测试

4.patch替换

patch作用是把原本dependencies从create.io的查找的,去git、本地、私有仓库查找

4.1 替换来自crates.io的包

[patch.crates-io]

4.1.1 git替换

[dependencies]
my-package = "0.1.0"

[patch.crates-io]
# 基本 Git 仓库
my-package = { git = "https://github.com/user/repo" }

# 指定分支
my-package = { git = "https://github.com/user/repo", branch = "develop" }

# 指定标签
my-package = { git = "https://github.com/user/repo", tag = "v2.1.0" }

# 指定提交
my-package = { git = "https://github.com/user/repo", rev = "a1b2c3d4" }

# 带有子模块
my-package = { git = "https://github.com/user/repo", submodule = true }

4.1.2 本地路径替换

[dependencies]
serde = "0.1.0"
tokio = "0.1.0"


[patch.crates-io]
serde = { path = "../forks/serde" }
tokio = { path = "/home/user/local-tokio" }

4.2 替换指定git源的包

[patch.<URL>]

[dependencies]
# 来自 Git 仓库的依赖
lib-from-git = { git = "https://github.com/example/repo", rev = "original" }

# 想要替换来自 https://github.com/example/repo 的包
[patch."https://github.com/example/repo"]
lib-from-git = { git = "https://github.com/user/repo", rev = "improved" }

4.3 替换来自特定注册表的包

# ~/.cargo/config.toml
[registries]
internal = { index = "https://cargo.internal.company.com/index" }

# Cargo.toml
[dependencies]
internal-lib = { version = "2.0", registry = "internal" }

# patch
[patch."https://cargo.internal.company.com/index"]
internal-lib = { path = "../local-fixes/internal-lib" }

5.features

项目提供给他人使用的特性
一般填写别人的特性,如:feature1、feature2

5.1 核心命名惯例

5.1.1 default - 默认启用的特性

[features]
default = ["feature1", "feature2"]

5.1.2 std - 标准库支持

[features]
std = []  # 启用依赖标准库的功能
no_std = []  # 启用无标准库支持

5.1.3 full - 完整功能

[features]
default = ["std"]
full = ["std", "async", "serialize", "crypto"]  # 启用所有功能

5.1.4 组合功能

可以复用features中的key
⚠️dep:前缀的作用是明确告诉Cargo这里要启用的是依赖本身,而不是依赖内部的某个特性,能有效避免命名冲突的问题

[dependencies]
serde = { version = "1.0", optional = true }
serde_json = { version = "1.0", optional = true }
serde_yaml = { version = "0.9", optional = true }
tokio = { version = "1.0", optional = true }

[features]
# 基础功能
serialize = ["dep:serde"]

# 基于基础功能扩展
json = ["serialize", "dep:serde_json"]
yaml = ["serialize", "dep:serde_yaml"]

# 组合使用
all_formats = ["json", "yaml"]  

5.1.5 自定义命名

[features]

aa_bb = ["feature1", "feature2"]
test_aa = ["feature1-test", "feature2-test"]

5.1.6 案例说明

.
├── aaa
│   ├── Cargo.toml
│   └── src
│       └── lib.rs
└── bbb
    ├── Cargo.lock
    ├── Cargo.toml
    └── src
        └── main.rs

aaa/Cargo.toml

[package]
name = "aaa"
version = "0.1.0"
edition = "2024"
publish = ["aliyun"]

[features]
mytest = []

aaa/src/lib.rs

pub fn add(left: u64, right: u64) -> u64 {
    left + right
}

#[cfg(feature = "mytest")]
pub fn add_test(left: u64, right: u64) -> u64 {
    left + right
}

bbb/Cargo.toml

[package]
name = "bbb"
version = "0.1.0"
edition = "2024"
publish = ["aliyun"]

[dependencies]
aaa = {path = "../aaa"}

bbb/src/main.rs

use aaa;

fn main() {
    // 报错,未开启mytest特性
    println!("{}", aaa::add_test(1, 2));
}

5.1.7 #[cfg(feature = "xxx")]说明

xxx填的就是 [features]段里的键名(key值)

[features]
serialize   = ["dep:serde"]
my_json      = ["serialize", "dep:serde_json"]
my_yaml      = ["serialize", "dep:serde_yaml"]
all_formats = ["my_json", "my_yaml"]
#[cfg(feature = "serialize")]
#[cfg(feature = "my_json")]
#[cfg(feature = "my_yaml")]
#[cfg(feature = "all_formats")]      // 组合 feature 一样能判断

5.1.7.1 其他判断写法

#[cfg(feature = "my_json")]                                  // 开my_json
#[cfg(not(feature = "my_json"))]                             // 没开my_json
#[cfg(all(feature = "my_json", feature = "my_yaml"))]         // 都开
#[cfg(any(feature = "my_json", feature = "my_yaml"))]         // 任一开

#[cfg_attr(feature = "serialize", derive(serde::Serialize))] // 条件加属性
#[cfg_attr(docsrs, doc(cfg(feature = "my_json")))]            // doc文档标注


// 两个分支都会被编译`cfg!(feature = "my_json")`只返回true / false
fn f() {
    if cfg!(feature = "my_json") { /* xxx1 */ } else { /* xxx2 */}
}

5.1.7.2 条件加属性说明

情况 展开结果
启用了 serialize #[derive(serde::Serialize)] pub struct Config { … } → 有 Serialize 实现
没启用 pub struct Config { … } → 就是普通结构体,没有 Serialize
#[cfg_attr(feature = "serialize", derive(serde::Serialize))]
pub struct Config { pub name: String }


// 这样的写发错误
// 没开 feature 时 Config 整个不存在!
// #[cfg(feature = "serialize")]        
// #[derive(serde::Serialize)]
// pub struct Config { … }
// 可以一次性附加多个属性
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize), serde(rename_all = "camelCase"))]

5.1.7.3 doc文档标注说明

doc(cfg(feature = "my_json")):rustdoc 的标注属性,效果是在文档页上给这个 API 打一个标签
Available on crate feature my_json only.
①②是「一次性配置」,③是「按需重复」
| 步骤 | 粒度 | 作用 | 能省吗 |
| --- | --- | --- | --- |
| ① Cargo.toml 的 [package.metadata.docs.rs] | 每个要发布的 crate 一份 | 让 docs.rs 开全 feature + 传 --cfg docsrs | 不能(docsrs 要由它来定义) |
| ② #![cfg_attr(docsrs, feature(doc_cfg))] | 每个 crate 的 lib.rs 顶部一次 | 打开 rustdoc 的 doc_cfg 能力(否则 doc(cfg(...)) 在 stable 上编不过) | 不能 |
| ③ 每个 API 上的 #[cfg(feature=…)] + #[cfg_attr(docsrs, doc(cfg(…)))] | 每个需要标注的 API 各一次 | 决定「这个 API 存不存在」+「文档里打什么标签」 | 按需 |

  • Cargo.toml定义
[package.metadata.docs.rs]
all-features = true
rustdoc-args = ["--cfg", "docsrs"]
targets = [                            # 平台类(可选)
  "x86_64-unknown-linux-gnu",
  "x86_64-pc-windows-msvc",
  "aarch64-apple-darwin",
]
  • lib.rs
// 必须在顶部
#![cfg_attr(docsrs, feature(doc_cfg))]
mod xxx1;
mod xxx2;
  • xxx.rs
#[cfg(feature = "my_json")]                                  // 这个 API 只在开了 my_json 时存在
#[cfg_attr(docsrs, doc(cfg(feature = "my_json")))]           // 在 docs.rs 上标注「需要 my_json」
impl Config {
    pub fn to_json(&self) -> String { /* ... */ }
}
  • 命令说明
[package.metadata.docs.rs] 里的配置 等价于 docs.rs 执行的命令 文档里出现的 API
什么都不写 cargo doc(用 default features) 只有 default 打开的
all-features = true cargo doc --all-features 全部
features = ["my_json"] cargo doc --features my_json default + my_json
features = [...] + no-default-features = true cargo doc --no-default-features --features ... 只有列出的

6.profile

主要用来调整编译优化级别、调试信息、代码生成等参数

Cargo 提供几个预定义的 profile:

  • dev: 开发模式,默认 cargo build
  • release: 发布模式,默认 cargo check 和 cargo test
  • test: 测试专用
  • bench: 基准测试专用
  • doc: 文档生成专用

6.1 opt-level优化级别

  • 0: 无优化,编译快
  • 1: 基本优化
  • 2: 常规优化
  • 3: 最大优化(默认发布模式)
  • s: 优化代码大小
  • z: 更积极地优化代码大小
[profile.dev]
opt-level = 0  # 开发模式通常为 0,无优化
# opt-level = 3  # 发布模式默认为 3,最大优化

[profile.release]
opt-level = 3  # 0-3, s, z

6.2 debug调试信息

[profile.dev]
debug = true   # 包含完整调试信息

[profile.release]
debug = false  # 不包含调试信息
# debug = true # 可选,保留调试信息但优化代码

6.3 debug-assertions调试断言

[profile.dev]
debug-assertions = true


[profile.release]
debug-assertions = false

6.4 overflow-checks溢出检查

[profile.dev]
overflow-checks = true  # 开启整数溢出检查

[profile.release]
overflow-checks = false # 关闭以提升性能

6.5 lto链接时优化

[profile.release]
lto = false     # 关闭 LTO
# lto = true    # 开启 LTO
# lto = "fat"   # 全面 LTO
# lto = "thin"  # 薄 LTO

6.6 codegen-units代码生成单元

[profile.release]
codegen-units = 16  # 默认值
# codegen-units = 1 # 单元,更优优化但编译慢

6.6 panic恐慌处理策略

[profile.release]
panic = "unwind"  # 展开栈(默认)
# panic = "abort" # 直接终止

6.7 incremental增量编译

[profile.dev]
incremental = true  # 开启增量编译(开发模式默认)

[profile.release]
incremental = false # 关闭(发布模式默认)

6.8 默认配置

6.8.1 dev默认配置

[profile.dev]
opt-level = 0
debug = true
split-debuginfo = '...'  # Platform-specific.
strip = "none"
debug-assertions = true
overflow-checks = true
lto = false
panic = 'unwind'
incremental = true
codegen-units = 256
rpath = false

6.8.2 release默认配置

[profile.release]
opt-level = 3
debug = false
split-debuginfo = '...'  # Platform-specific.
strip = "none"
debug-assertions = false
overflow-checks = false
lto = false
panic = 'unwind'
incremental = false
codegen-units = 16
rpath = false

6.8.4 其他默认配置

  • test默认配置继承dev
  • bench默认配置继承release

6.9 构建依赖

build-override影响[build-dependencies], 也就是build.rs

[profile.dev.build-override]
opt-level = 0
codegen-units = 256
debug = false # when possible

[profile.release.build-override]
opt-level = 0
codegen-units = 256
posted @ 2026-09-29 10:38  lxd670  阅读(4)  评论(0)    收藏  举报