Cargo 目标

Cargo 包由可以编译成 crate 的源文件对应的*目标*组成。包可以有二进制示例测试基准测试目标。目标列表可以在Cargo.toml清单中配置,通常由源文件的目录布局自动推断

有关配置目标设置的详细信息,请参阅下面的配置目标

库目标定义了一个可以被其他库和可执行文件使用和链接的“库”。文件名默认为src/lib.rs,库的名称默认为包的名称。一个包只能有一个库。可以在Cargo.toml[lib]表中自定义库的设置。

# Example of customizing the library in Cargo.toml.
[lib]
crate-type = ["cdylib"]
bench = false

二进制文件

二进制目标是编译后可以运行的可执行程序。默认的二进制文件名是src/main.rs,默认为包的名称。其他二进制文件存储在src/bin/目录中。可以在Cargo.toml[[bin]]表中自定义每个二进制文件的设置。

二进制文件可以使用包库的公共 API。它们还与Cargo.toml中定义的[dependencies]链接。

您可以使用cargo run命令和--bin <bin-name>选项运行单个二进制文件。cargo install可用于将可执行文件复制到公共位置。

# Example of customizing binaries in Cargo.toml.
[[bin]]
name = "cool-tool"
test = false
bench = false

[[bin]]
name = "frobnicator"
required-features = ["frobnicate"]

示例

位于examples目录下的文件是库提供的功能的示例用法。编译后,它们将被放置在target/debug/examples目录中。

示例可以使用包库的公共 API。它们还与Cargo.toml中定义的[dependencies][dev-dependencies]链接。

默认情况下,示例是可执行的二进制文件(带有main()函数)。您可以指定crate-type字段以使示例编译为库。

[[example]]
name = "foo"
crate-type = ["staticlib"]

您可以使用cargo run命令和--example <example-name>选项运行单个可执行示例。可以使用cargo build--example <example-name>选项构建库示例。cargo install--example <example-name>选项可用于将可执行二进制文件复制到公共位置。默认情况下,cargo test会编译示例,以防止它们出现代码腐烂。如果您在要使用cargo test运行的示例中具有#[test]函数,请将test字段设置为true

测试

Cargo 项目中有两种测试风格:

  • *单元测试*,它们是在您的库或二进制文件(或任何启用了test字段的目标)中使用#[test]属性标记的函数。这些测试可以访问定义它们的目标中的私有 API。
  • *集成测试*,它是一个单独的可执行二进制文件,也包含#[test]函数,它与项目的库链接,并且可以访问其*公共* API。

测试使用 cargo test 命令运行。默认情况下,Cargo 和 rustc 使用 libtest harness,它负责收集使用 #[test] 属性 注释的函数并并行执行它们,报告每个测试的成功和失败。如果您想使用不同的 harness 或测试策略,请参阅 harness 字段

注意:Cargo 中还有另一种特殊类型的测试:文档测试。它们由 rustdoc 处理,并且执行模型略有不同。有关更多信息,请参阅 cargo test

集成测试

位于 tests 目录 下的文件是集成测试。当您运行 cargo test 时,Cargo 会将这些文件中的每一个编译为一个单独的 crate,并执行它们。

集成测试可以使用包库的公共 API。它们还与 Cargo.toml 中定义的 [dependencies][dev-dependencies] 链接。

如果您想在多个集成测试之间共享代码,可以将其放在一个单独的模块中,例如 tests/common/mod.rs,然后在每个测试中放入 mod common; 来导入它。

每个集成测试都会生成一个单独的可执行二进制文件,并且 cargo test 将串行运行它们。在某些情况下,这可能效率低下,因为它可能需要更长的编译时间,并且在运行测试时可能无法充分利用多个 CPU。如果您有很多集成测试,您可能需要考虑创建一个单独的集成测试,并将测试拆分为多个模块。libtest harness 将自动找到所有标有 #[test] 属性的函数并并行运行它们。您可以将模块名称传递给 cargo test 以仅运行该模块内的测试。

如果存在集成测试,则会自动构建二进制目标。这允许集成测试执行二进制文件以测试其行为。构建集成测试时会设置 CARGO_BIN_EXE_<name> 环境变量,以便它可以使用 env 来定位可执行文件。

基准测试

基准测试提供了一种使用 cargo bench 命令测试代码性能的方法。它们遵循与 测试 相同的结构,每个基准测试函数都使用 #[bench] 属性进行注释。与测试类似

  • 基准测试位于 benches 目录 中。
  • 在库和二进制文件中定义的基准测试函数可以访问它们定义的目标内的*私有* API。benches 目录中的基准测试可以使用*公共* API。
  • bench 字段 可用于定义默认情况下对哪些目标进行基准测试。
  • harness 字段 可用于禁用内置 harness。

注意#[bench] 属性 目前不稳定,仅在 nightly 频道 上可用。 crates.io 上有一些软件包可以帮助在稳定频道上运行基准测试,例如 Criterion

配置目标

Cargo.toml 中的所有 [lib][[bin]][[example]][[test]][[bench]] 部分都支持类似的配置,用于指定如何构建目标。像 [[bin]] 这样的双括号部分是 TOML 的表数组,这意味着您可以编写多个 [[bin]] 部分来在您的 crate 中创建多个可执行文件。您只能指定一个库,因此 [lib] 是一个普通的 TOML 表。

以下是每个目标的 TOML 设置概述,每个字段的详细说明如下。

[lib]
name = "foo"           # The name of the target.
path = "src/lib.rs"    # The source file of the target.
test = true            # Is tested by default.
doctest = true         # Documentation examples are tested by default.
bench = true           # Is benchmarked by default.
doc = true             # Is documented by default.
plugin = false         # Used as a compiler plugin (deprecated).
proc-macro = false     # Set to `true` for a proc-macro library.
harness = true         # Use libtest harness.
edition = "2015"       # The edition of the target.
crate-type = ["lib"]   # The crate types to generate.
required-features = [] # Features required to build this target (N/A for lib).

name 字段

name 字段指定目标的名称,该名称对应于将生成的文件的名称。对于库,这是依赖项将用于引用它的 crate 名称。

对于 [lib] 和默认二进制文件 (src/main.rs),这默认为包的名称,所有破折号都替换为下划线。对于其他 自动发现的 目标,它默认为目录或文件名。

[lib] 外,所有目标都需要此字段。

path 字段

path 字段指定 crate 源代码的位置,相对于 Cargo.toml 文件。

如果未指定,则根据目标名称使用 推断路径

test 字段

test 字段指示 cargo test 默认情况下是否测试目标。对于 lib、bin 和测试,默认值为 true

注意:默认情况下,cargo test 会构建示例以确保它们继续编译,但默认情况下不会对它们进行*测试*。为示例设置 test = true 也会将其构建为测试并运行示例中定义的任何 #[test] 函数。

doctest 字段

doctest 字段指示 cargo test 默认情况下是否测试 文档示例。这仅与库相关,对其他部分没有影响。库的默认值为 true

bench 字段

bench 字段指示 cargo bench 默认情况下是否对目标进行基准测试。对于 lib、bin 和基准测试,默认值为 true

doc 字段

doc 字段指示默认情况下目标是否包含在 cargo doc 生成的文档中。对于库和二进制文件,默认值为 true

注意:如果二进制文件的名称与 lib 目标的名称相同,则将跳过该二进制文件。

plugin 字段

此字段用于 rustc 插件,这些插件即将弃用。

proc-macro 字段

proc-macro 字段指示该库是 过程宏参考)。这仅对 [lib] 目标有效。

harness 字段

harness 字段指示将向 rustc 传递 --test 标志,这将自动包含 libtest 库,该库是用于收集和运行标有 #[test] 属性 的测试或标有 #[bench] 属性的基准测试的驱动程序。所有目标的默认值为 true

如果设置为 false,则您需要负责定义一个 main() 函数来运行测试和基准测试。

无论是否启用 harness,测试都启用了 cfg(test) 条件表达式

edition 字段

edition 字段定义目标将使用的 Rust 版本。如果未指定,则默认为 [package]edition 字段。此字段通常不应设置,并且仅用于高级场景,例如将大型包增量转换为新版本。

crate-type 字段

crate-type 字段定义目标将生成的 crate 类型。它是一个字符串数组,允许您为单个目标指定多个 crate 类型。这只能为库和示例指定。二进制文件、测试和基准测试始终是“bin”crate 类型。默认值为

目标Crate 类型
普通库“lib”
过程宏库“proc-macro”
示例“bin”

可用选项包括 binlibrlibdylibcdylibstaticlibproc-macro。您可以在 Rust 参考手册 中阅读有关不同 crate 类型的更多信息。

required-features 字段

required-features 字段指定了构建目标所需哪些 功能。如果任何必需的功能未启用,则目标将被跳过。这仅与 [[bin]][[bench]][[test]][[example]] 部分相关,对 [lib] 没有影响。

[features]
# ...
postgres = []
sqlite = []
tools = []

[[bin]]
name = "my-pg-tool"
required-features = ["postgres", "tools"]

目标自动发现

默认情况下,Cargo 会根据文件系统上 文件的布局 自动确定要构建的目标。目标配置表,例如 [lib][[bin]][[test]][[bench]][[example]],可用于添加不遵循标准目录布局的其他目标。

可以禁用自动目标发现,以便仅构建手动配置的目标。在 [package] 部分中将 autobinsautoexamplesautotestsautobenches 键设置为 false 将禁用相应目标类型的自动发现。

[package]
# ...
autobins = false
autoexamples = false
autotests = false
autobenches = false

仅在特殊情况下才需要禁用自动发现。例如,如果您有一个库,并且希望其中有一个名为 bin 的*模块*,这将出现问题,因为 Cargo 通常会尝试将 bin 目录中的任何内容编译为可执行文件。以下是这种情况下的示例布局

├── Cargo.toml
└── src
    ├── lib.rs
    └── bin
        └── mod.rs

为了防止 Cargo 将 src/bin/mod.rs 推断为可执行文件,请在 Cargo.toml 中设置 autobins = false 以禁用自动发现

[package]
# …
autobins = false

**注意**:对于使用 2015 版的包,如果在 Cargo.toml 中手动定义了至少一个目标,则自动发现的默认值为 false。从 2018 版开始,默认值始终为 true