清单格式

每个包的 Cargo.toml 文件被称为它的清单。它以 TOML 格式编写。它包含编译包所需的元数据。有关 cargo 如何查找清单文件的更多详细信息,请查看 cargo locate-project 部分。

每个清单文件都包含以下部分

[package] 部分

Cargo.toml 中的第一部分是 [package]

[package]
name = "hello_world" # the name of the package
version = "0.1.0"    # the current version, obeying semver
authors = ["Alice <[email protected]>", "Bob <[email protected]>"]

Cargo 唯一需要的字段是 name。如果发布到注册表,注册表可能需要其他字段。有关发布到 crates.io 的要求,请参见以下说明和 发布章节

name 字段

包名称是用于引用包的标识符。当在另一个包中列为依赖项时以及作为推断的 lib 和 bin 目标的默认名称时,会使用它。

名称只能使用字母数字字符或 -_,并且不能为空。

请注意,cargo newcargo init 对包名称施加了一些额外的限制,例如强制要求它是有效的 Rust 标识符而不是关键字。crates.io 施加了更多限制,例如

  • 只允许使用 ASCII 字符。
  • 不要使用保留名称。
  • 不要使用特殊的 Windows 名称,例如“nul”。
  • 最大长度为 64 个字符。

version 字段

version 字段的格式符合 SemVer 规范

版本必须有三个数字部分:主版本、次版本和补丁版本。

可以在破折号后添加预发布部分,例如 1.0.0-alpha。预发布部分可以用句点分隔以区分不同的组件。数字组件将使用数字比较,而其他所有内容将按字典顺序比较。例如,1.0.0-alpha.11 高于 1.0.0-alpha.4

可以在加号后添加元数据部分,例如 1.0.0+21AF26D3。这仅用于提供信息,通常会被 Cargo 忽略。

Cargo 融入了语义版本控制的概念,因此如果它们的左侧非零主要/次要/补丁组件相同,则认为版本是 兼容的。有关 Cargo 如何使用版本解析依赖项的更多信息,请参阅 Resolver 章节。

此字段是可选的,默认为 0.0.0。发布包需要此字段。

MSRV: 在 1.75 之前,此字段是必需的

authors 字段

可选的 authors 字段在一个数组中列出了被认为是包“作者”的人员或组织。确切的含义可以解释——它可能列出原始或主要作者、当前维护者或包的所有者。可选的电子邮件地址可以包含在每个作者条目的末尾的尖括号内。

[package]
# ...
authors = ["Graydon Hoare", "Fnu Lnu <[email protected]>"]

此字段仅在包元数据和 build.rs 内的 CARGO_PKG_AUTHORS 环境变量中显示。它不会在 crates.io 用户界面中显示。

警告:包清单一旦发布就无法更改,因此此字段无法在已发布版本的包中更改或删除。

edition 字段

edition 键是一个可选键,它会影响你的包编译所使用的 Rust 版本。在 [package] 中设置 edition 键将影响包中的所有目标/ crate,包括测试套件、基准测试、二进制文件、示例等。

[package]
# ...
edition = '2021'

大多数清单的 edition 字段会自动被 cargo new 填充为最新的稳定版本。默认情况下,cargo new 会创建一个当前使用 2021 版本的清单。

如果 Cargo.toml 中不存在 edition 字段,则为了向后兼容,假定使用 2015 版本。请注意,使用 cargo new 创建的所有清单都不会使用此历史回退,因为它们会将 edition 显式指定为较新的值。

rust-version 字段

rust-version 字段告诉 cargo 你的包支持哪个版本的 Rust 工具链。有关更多详细信息,请参阅 Rust 版本章节

description 字段

描述是关于包的简短介绍。crates.io 将与你的包一起显示此内容。这应该是纯文本(不是 Markdown)。

[package]
# ...
description = "A short description of my package"

注意crates.io 要求设置 description

documentation 字段

documentation 字段指定一个 URL,指向托管 crate 文档的网站。如果在清单文件中未指定 URL,则当文档已构建并且可用时,crates.io 会自动将你的 crate 链接到相应的 docs.rs 页面(请参阅 docs.rs 队列)。

[package]
# ...
documentation = "https://docs.rs/bitflags"

readme 字段

readme 字段应该是包根目录中一个文件的路径(相对于此 Cargo.toml),该文件包含有关包的一般信息。当你发布时,此文件将传输到注册表。crates.io 将其解释为 Markdown,并在 crate 的页面上呈现它。

[package]
# ...
readme = "README.md"

如果未为此字段指定值,并且包根目录中存在名为 README.mdREADME.txtREADME 的文件,则将使用该文件的名称。你可以通过将此字段设置为 false 来禁止此行为。如果该字段设置为 true,则将假定默认值为 README.md

homepage 字段

homepage 字段应该是指向你包主页的 URL。

[package]
# ...
homepage = "https://serde.rs"

只有在 crate 有一个专门的网站(而不是源代码存储库或 API 文档)时,才应为 homepage 设置值。不要使 homepagedocumentationrepository 值重复。

repository 字段

repository 字段应该是指向你的包的源代码存储库的 URL。

[package]
# ...
repository = "https://github.com/rust-lang/cargo"

licenselicense-file 字段

license 字段包含包发布的软件许可证的名称。license-file 字段包含一个文件的路径,其中包含许可证的文本(相对于此 Cargo.toml)。

crates.iolicense 字段解释为 SPDX 2.3 许可证表达式。名称必须是 SPDX 许可证列表 3.20 中已知的许可证。有关更多信息,请参阅 SPDX 站点

SPDX 许可证表达式支持 AND 和 OR 运算符来组合多个许可证。1

[package]
# ...
license = "MIT OR Apache-2.0"

使用 OR 表示用户可以选择任一许可证。使用 AND 表示用户必须同时遵守两个许可证。WITH 运算符表示具有特殊例外的许可证。一些例子

  • MIT OR Apache-2.0
  • LGPL-2.1-only AND MIT AND BSD-2-Clause
  • GPL-2.0-or-later WITH Bison-exception-2.2

如果一个包使用非标准的许可证,那么可以指定 license-file 字段来代替 license 字段。

[package]
# ...
license-file = "LICENSE.txt"

注意crates.io 要求设置 licenselicense-file

1

之前可以使用 / 分隔多个许可证,但这种用法已被弃用。

keywords 字段

keywords 字段是一个字符串数组,用于描述此软件包。这有助于在注册表中搜索软件包,您可以选择任何有助于他人找到此 crate 的词语。

[package]
# ...
keywords = ["gamedev", "graphics"]

注意crates.io 最多允许 5 个关键词。每个关键词必须是 ASCII 文本,最多 20 个字符,以字母数字字符开头,并且只能包含字母、数字、_-+

categories 字段

categories 字段是一个字符串数组,表示此软件包所属的类别。

categories = ["command-line-utilities", "development-tools::cargo-plugins"]

注意crates.io 最多允许 5 个类别。每个类别都应与 https://crates.io/category_slugs 上提供的字符串之一完全匹配。

workspace 字段

workspace 字段可用于配置此软件包将成为其成员的工作区。如果未指定,则将推断为文件系统中向上第一个带有 [workspace] 的 Cargo.toml 文件。如果成员不在工作区根目录的子目录中,则设置此项非常有用。

[package]
# ...
workspace = "path/to/workspace/root"

如果清单已定义 [workspace] 表,则不能指定此字段。也就是说,一个 crate 不能既是工作区中的根 crate(包含 [workspace]),又是另一个工作区的成员 crate(包含 package.workspace)。

有关更多信息,请参阅工作区章节

build 字段

build 字段指定包根目录中的一个文件,该文件是用于构建本机代码的构建脚本。更多信息可以在构建脚本指南中找到。

[package]
# ...
build = "build.rs"

默认值为 "build.rs",它从包根目录中名为 build.rs 的文件加载脚本。使用 build = "custom_build_name.rs" 指定其他文件的路径,或使用 build = false 禁用自动检测构建脚本。

links 字段指定要链接到的本机库的名称。更多信息可以在构建脚本指南的links部分中找到。

例如,一个链接名为“git2”的本机库(例如,Linux 上的 libgit2.a)的 crate 可以指定

[package]
# ...
links = "git2"

excludeinclude 字段

excludeinclude 字段可用于显式指定在打包项目以进行发布时包含的文件,以及某些类型的更改跟踪(如下所述)。 exclude 字段中指定的模式标识一组不包含的文件,而 include 中的模式指定显式包含的文件。您可以运行 cargo package --list 以验证哪些文件将包含在包中。

[package]
# ...
exclude = ["/ci", "images/", ".*"]
[package]
# ...
include = ["/src", "COPYRIGHT", "/examples", "!/examples/big_example"]

如果未指定任何字段,则默认包含包根目录中的所有文件,但以下排除项除外。

如果未指定 include,则将排除以下文件

  • 如果包不在 git 存储库中,则所有以点开头“隐藏”文件将被跳过。
  • 如果包在 git 存储库中,则将跳过存储库和全局 git 配置的 gitignore 规则忽略的任何文件。

无论是否指定 excludeinclude,始终排除以下文件

  • 任何子包都将被跳过(任何包含 Cargo.toml 文件的子目录)。
  • 包根目录中名为 target 的目录将被跳过。

始终包含以下文件

  • 始终包含包本身的 Cargo.toml 文件,无需在 include 中列出。
  • 如果包包含二进制或示例目标,则会自动包含一个最小化的 Cargo.lock,有关更多信息,请参阅 cargo package
  • 如果指定了 license-file,则始终包含它。

这些选项是互斥的;设置 include 将覆盖 exclude。如果您需要在 include 文件集中排除某些文件,请使用下面描述的 ! 运算符。

模式应为 gitignore 风格的模式。简而言之

  • foo 匹配包中任何位置的任何名为 foo 的文件或目录。这等效于模式 **/foo
  • /foo 匹配包根目录中任何名为 foo 的文件或目录。
  • foo/ 匹配包中任何位置的任何名为 foo目录
  • 支持常见的 glob 模式,如 *?[]
    • * 匹配零个或多个字符,但不包括 /。例如,*.html 匹配包中任何位置的任何具有 .html 扩展名的文件或目录。
    • ? 匹配任何字符,但不包括 /。例如,foo? 匹配 food,但不匹配 foo
    • [] 允许匹配一系列字符。例如,[ab] 匹配 ab[a-z] 匹配字母 a 到 z。
  • **/ 前缀匹配任何目录中的内容。例如,**/foo/bar 匹配任何直接位于目录 foo 下的 文件或目录 bar
  • /** 后缀匹配内部的所有内容。例如,foo/** 匹配目录 foo 中的所有文件,包括 foo 下面的子目录中的所有文件。
  • /**/ 匹配零个或多个目录。例如,a/**/b 匹配 a/ba/x/ba/x/y/b 等。
  • ! 前缀否定模式。例如,模式为 src/*.rs!foo.rs 将匹配 src 目录中所有具有 .rs 扩展名的文件,但名为 foo.rs 的文件除外。

include/exclude 列表也用于某些情况下的更改跟踪。 对于使用 rustdoc 构建的目标,它用于确定要跟踪的文件列表,以确定是否应重建目标。 如果包具有不发出任何 rerun-if-* 指令的 构建脚本,则如果任何这些文件发生更改,则 include/exclude 列表用于跟踪是否应重新运行构建脚本。

publish 字段

publish 字段可用于控制可以将软件包发布到哪些注册表。

[package]
# ...
publish = ["some-registry-name"]

为防止软件包意外发布到注册表(如 crates.io),例如为了在公司中保持软件包私有,您可以省略version字段。如果您想更明确地说明,您可以禁用发布。

[package]
# ...
publish = false

如果 publish 数组包含单个注册表,则当未指定 --registry 标志时,cargo publish 命令将使用它。

metadata

默认情况下,Cargo 会警告 Cargo.toml 中未使用的键,以帮助检测错别字等。但是,Cargo 完全忽略 package.metadata 表,并且不会发出警告。此部分可用于希望在 Cargo.toml 中存储软件包配置的工具。例如

[package]
name = "..."
# ...

# Metadata used when generating an Android APK, for example.
[package.metadata.android]
package-name = "my-awesome-android-app"
assets = "path/to/static"

您需要查看工具的文档,了解如何使用此字段。对于使用 package.metadata 表的 Rust 项目,请参阅

workspace.metadata 处的工作区级别有一个类似的表。虽然 Cargo 没有指定这些表中任何一个的内容格式,但建议外部工具可能希望以一致的方式使用它们,例如在 package.metadata 中缺少数据时引用 workspace.metadata 中的数据,如果这对相关工具来说有意义。

default-run 字段

清单的 [package] 部分中的 default-run 字段可用于指定 cargo run 选择的默认二进制文件。例如,当同时存在 src/bin/a.rssrc/bin/b.rs

[package]
default-run = "a"

[lints] 部分

通过将不同工具的默认 lint 级别分配给表中的新级别来覆盖它们,例如

[lints.rust]
unsafe_code = "forbid"

这是以下内容的简写形式

[lints.rust]
unsafe_code = { level = "forbid", priority = 0 }

level 对应于 rustc 中的 lint 级别

  • forbid
  • deny
  • warn
  • allow

priority 是一个带符号的整数,用于控制哪些 lint 或 lint 组覆盖其他 lint 组

  • 较低(尤其是负数)的数字具有较低的优先级,会被较高的数字覆盖,并且在 rustc 等工具的命令行上首先显示。

要了解特定 lint 属于 [lints] 下的哪个表,它是 lint 名称中 :: 之前的部分。如果没有 ::,则该工具是 rust。 例如,关于 unsafe_code 的警告将是 lints.rust.unsafe_code,但关于 clippy::enum_glob_use 的 lint 将是 lints.clippy.enum_glob_use

例如

[lints.rust]
unsafe_code = "forbid"

[lints.clippy]
enum_glob_use = "deny"

通常,这些只会影响当前软件包的本地开发。 Cargo 只将这些应用于当前软件包,而不应用于依赖项。 对于依赖项,Cargo 会使用 --cap-lints 等功能抑制来自非路径依赖项的 lint。

MSRV: 自 1.74 起适用

[badges] 部分

[badges] 部分用于指定软件包发布时可以显示在注册表网站上的状态徽章。

注意:crates.io 以前在其网站上显示的 crate 旁边显示徽章,但该功能已被删除。软件包应将其徽章放置在 README 文件中,该文件将显示在 crates.io 上(请参阅readme 字段)。

[badges]
# The `maintenance` table indicates the status of the maintenance of
# the crate. This may be used by a registry, but is currently not
# used by crates.io. See https://github.com/rust-lang/crates.io/issues/2437
# and https://github.com/rust-lang/crates.io/issues/2438 for more details.
#
# The `status` field is required. Available options are:
# - `actively-developed`: New features are being added and bugs are being fixed.
# - `passively-maintained`: There are no plans for new features, but the maintainer intends to
#   respond to issues that get filed.
# - `as-is`: The crate is feature complete, the maintainer does not intend to continue working on
#   it or providing support, but it works for the purposes it was designed for.
# - `experimental`: The author wants to share it with the community but is not intending to meet
#   anyone's particular use case.
# - `looking-for-maintainer`: The current maintainer would like to transfer the crate to someone
#   else.
# - `deprecated`: The maintainer does not recommend using this crate (the description of the crate
#   can describe why, there could be a better solution available or there could be problems with
#   the crate that the author does not want to fix).
# - `none`: Displays no badge on crates.io, since the maintainer has not chosen to specify
#   their intentions, potential crate users will need to investigate on their own.
maintenance = { status = "..." }

依赖项部分

有关 [dependencies][dev-dependencies][build-dependencies] 和特定于目标的 [target.*.dependencies] 部分的信息,请参阅指定依赖项页面

[profile.*] 部分

[profile] 表提供了一种自定义编译器设置(如优化和调试设置)的方法。有关更多详细信息,请参阅配置文件章节