Cargo之书

Cargo Logo

Cargo是 Rust 包管理器,能够下载、编译Rust所依赖的包 package, 能制作可分享的包,可以上传到crates.io(Rust 包注册中心 )。 您可以在 GitHub 为本书贡献内容。或者参与完善此 Cargo之书中文译本

章节

初步准备

开始使用Cargo,安装Cargo和Rust,并设置您的第一个crate

Cargo指南

本指南提供有关使用Cargo开发Rust包所需的知识。

Cargo参考

参考部分涵盖了Cargo的各个方面的细节。

Cargo 命令

这些命令将允许您使用其命令行界面与Cargo交互。

常见问题

附:

其他文档:

初步准备

开始使用Cargo,安装Cargo和Rust,配置你的第一个 crate

安装

安装 Rust 和 Cargo

获得 Cargo 最简单的方法是通过 rustup 来安装 Rust 当前的稳定版本,同时也会安装 cargo

在Linux和macOS系统中,可以这样:

curl https://sh.rustup.rs -sSf | sh

它将下载一个脚本,并开始安装。如果一切顺利,你会看到:

Rust is installed now. Great!

在Windows操作系统中,下载并运行 rustup-init.exe 。它将在控制台中开始安装,并在成功时显示上述消息。

之后,就可以使用 rustup 命令来安装 Rust 或 Cargo,也可以安装 beta "测试" 或 nightly "每日" 版本。

关于其他安装选项和信息,请访问 Rust 网站的 install 页面。

从源代码构建和安装Cargo

做为备选,你可以从源代码构建Cargo

Cargo起步

本节提供对 cargo 命令行工具的快速一览。展示其生成新 package 的功能, 其在包内编译 crate 的能力,以及运行所生成程序的功能。

使用 cargo new 可创建新包:

$ cargo new hello_world

Cargo 默认以 --bin 来构建二进制程序,可通过 --lib 来构建库。

让我们来查看 Cargo 所生成的内容:

$ cd hello_world
$ tree .
.
├── Cargo.toml
└── src
    └── main.rs

1 directory, 2 files

这就是创建的全部内容。先来查看一下 Cargo.toml :

[package]
name = "hello_world"
version = "0.1.0"
edition = "2021"

[dependencies]

其内容称为 manifest "配置清单",包含了Cargo编译包时所需的所有元数据。

以下为 src/main.rs 的内容:

fn main() {
    println!("Hello, world!");
}

Cargo 为我们生成了一个 "hello world" 程序,是 binary crate "二进制crate"。 编译这个程序:

$ cargo build
   Compiling hello_world v0.1.0 (file:///path/to/package/hello_world)

然后运行程序:

$ ./target/debug/hello_world
Hello, world!

可以使用 cargo run 来编译后运行,一步完成:

$ cargo run
     Fresh hello_world v0.1.0 (file:///path/to/package/hello_world)
   Running `target/hello_world`
Hello, world!

继续了解

关于Cargo的更多细节,查阅 Cargo 指南

Cargo指南

本指南提供了如何使用Cargo来开发Rust包的指导内容。

为何有Cargo

初识

在 Rust 中,一个类库或可执行程序称为一个 crate 。 使用 Rust 编译器 rustc 编译 Crate 。 刚开始学习 Rust 时,经典的 "hello world" 程序,可以通过 rustc 直接编译:

$ rustc hello.rs
$ ./hello
Hello, world!

请注意,上面的命令需要显式指定文件名。 如果直接使用 rustc 编译不同的程序,不同的文件就需要执行不同的命令。 如果需要指定编译选项或包含的外部依赖,就需要十分具体详尽的执行命令。

而且,大多数程序会有额外的外部依赖,这些外部依赖又会有其他依赖。 此时手动维护必要依赖的正确版本,并协调依赖版本更新会很困难。

相较于直接跟 crate 和 rustc 打交道,引入了更高层 "包(package)" 的抽象。 并使用 包管理器 来避免这些手动的乏味工作。

走进 Cargo

Cargo 是 Rust 的包管理器。它是工具,允许 Rust packages 声明其各种依赖关系,确保总是能得到一个可重复的构建。

Cargo 做了以下四件事来实现这个目标:

  • 引进两个文件,包含包的各类元数据信息。
  • 下载并构建包的依赖。
  • 调用 rustc 或其他构建工具及正确的参数来构建包。
  • 引进规范使 Rust 包的操作更简单。

Cargo 在很大程度的标准化了构建程序或包的命令,这是上述规范的一个方面。 从下文中可以看到,相同的命令可以构建名称不同的 artifacts "制品"。 相比直接调用 rustc ,可以调用 cargo build 等更加通用的命令,而让 cargo 正确的调用 rustc 去构建。 并且,Cargo 可以自动从 registry "注册中心"下载依赖,并将依赖合并到构建中。

夸张一点说,一旦你学会使用 Cargo 就可以构建 所有 项目。

创建新包

使用 cargo new 命令创建新的 package "包":

$ cargo new hello_world --bin

创建二进制程序,传递 --bin 参数,如果创建类库,传递 --lib 。 创建时会默认初始化为 git 仓库,如果不需要,可以传递 --vcs none

来看看 Cargo 所生成的文件:

$ cd hello_world
$ tree .
.
├── Cargo.toml
└── src
    └── main.rs

1 directory, 2 files

来看看 Cargo.toml 文件:

[package]
name = "hello_world"
version = "0.1.0"
edition = "2021"

[dependencies]

其内容称为 manifest "配置清单",包含Cargo编译时所需的所有元数据。 此文件采用 TOML (发音为 /tɑməl/) 格式书写。

这是 src/main.rs 的内容:

fn main() {
    println!("Hello, world!");
}

Cargo 生成了一个 "hello world" 程序,也称 binary crate "二进制crate"。编译它:

$ cargo build
   Compiling hello_world v0.1.0 (file:///path/to/package/hello_world)

然后运行:

$ ./target/debug/hello_world
Hello, world!

也可以使用 cargo run 命令来编译并运行,将编译与运行合成一步(如果相较上次编译没有进行过改动,不会看到 Compiling 信息输出):

$ cargo run
   Compiling hello_world v0.1.0 (file:///path/to/package/hello_world)
     Running `target/debug/hello_world`
Hello, world!

你会注意到出现一个名为 Cargo.lock 的新文件。它包含依赖的相关信息。 目前我们并没有任何依赖,所以它之中并没有多少有用的信息。

当你准备好要发布程序,可以使用 cargo build --release 命令来编译文件(此选项会开启编译优化):

$ cargo build --release
   Compiling hello_world v0.1.0 (file:///path/to/package/hello_world)

cargo build --release 命令会将产生的二进制文件放在 target/release 目录,而非 target/debug

开发过程中,编译会默认在调试模式(debug mode)下进行。 由于编译器不进行编译优化,能缩短编译耗时,但编译后的代码运行会更慢。 发布模式(release mode)下的编译耗时更长但代码运行更快。

拥有Cargo包

使用 Cargo 下载已存在的 package 非常简单。

首先,获取到包的代码。比如使用从 GitHub 克隆的 regex 包。

$ git clone https://github.com/rust-lang/regex.git
$ cd regex

使用 cargo build 命令构建包:

$ cargo build
   Compiling regex v1.5.0 (file:///path/to/package/regex)

这会下载并构建所有的依赖和包。

依赖

crates.io 是 Rust 社区主要的 包注册中心 。 是搜索和下载 packages 的仓库。 cargo 默认使用这个地址来搜索所需的包。

要添加 crates.io 上托管的库,你需要将库添加到 Cargo.toml

添加依赖

如果你的 Cargo.toml 还没有 [dependencies] 部分,添加上这个标记, 然后在标记下方列出你需要使用的 crate 的名称和版本。 下面这个例子展示了如何添加 time 依赖:

[dependencies]
time = "0.1.12"

描述版本的字符串要求使用 SemVer "语义化版本"规范。对此 specifying dependencies 部分有更多信息。

如果我们想添加一个 regex 依赖,则不需要为每个依赖都添加 [dependencies] 。 下面是 Cargo.toml 文件添加 timeregex 依赖的范例:

[package]
name = "hello_world"
version = "0.1.0"
edition = "2021"

[dependencies]
time = "0.1.12"
regex = "0.1.41"

重新执行 cargo build 命令,Cargo 会下载新的依赖以及依赖本身所需的依赖, 全部编译,并更新 Cargo.lock 文件:

$ cargo build
      Updating crates.io index
   Downloading memchr v0.1.5
   Downloading libc v0.1.10
   Downloading regex-syntax v0.2.1
   Downloading memchr v0.1.5
   Downloading aho-corasick v0.3.0
   Downloading regex v0.1.41
     Compiling memchr v0.1.5
     Compiling libc v0.1.10
     Compiling regex-syntax v0.2.1
     Compiling memchr v0.1.5
     Compiling aho-corasick v0.3.0
     Compiling regex v0.1.41
     Compiling hello_world v0.1.0 (file:///path/to/package/hello_world)

Cargo.lock 文件包含着所有依赖准确的版本信息。

如果 regex 依赖升级了,仍然会使用当前的版本进行构建,除非手动执行 cargo update 命令。

现在可以在 main.rs 中使用 regex 库了。

use regex::Regex;

fn main() {
    let re = Regex::new(r"^\d{4}-\d{2}-\d{2}$").unwrap();
    println!("Did our date match? {}", re.is_match("2014-01-01"));
}

运行它会输出:

$ cargo run
   Running `target/hello_world`
Did our date match? true

包的布局

Cargo 有一系列文件布局的约定,从而可以简便地创建新的包:

.                                       项目根目录
├── Cargo.lock                          存储构建成功后的准确版本信息
├── Cargo.toml                          包和构建需要的信息
├── src/                                源码目录
│   ├── lib.rs                          库 crate 的根
│   ├── main.rs                         二进制 cate 的根
│   └── bin/                            其他二进制crate
│       ├── named-executable.rs         命名的可执行crate根
│       ├── another-executable.rs       另一个可执行crate根
│       └── multi-file-executable/      多文件可执行crate根目录,目录名即可执行文件名
│           ├── main.rs                 crate 的根
│           └── some_module.rs          crate 的模块
├── benches/                            性能测试        与bin/目录结构相同
│   ├── large-input.rs                  
│   └── multi-file-bench/               
│       ├── main.rs                     
│       └── bench_module.rs             
├── examples/                           库的实例                  与bin/目录结构相同
│   ├── simple.rs
│   └── multi-file-example/
│       ├── main.rs
│       └── ex_module.rs
└── tests/                              集成测试                  与bin/目录结构相同
    ├── some-integration-tests.rs
    └── multi-file-test/
        ├── main.rs
        └── test_module.rs
  • Cargo.tomlCargo.lock 保储在包的根目录。
  • 源码在 src 目录。
  • 默认的库 crate 根文件是 src/lib.rs
  • 默认的可执行 crate 根文件是 src/main.rs
    • 其他可执行 crate 文件可以放在 src/bin/ 目录。
  • 性能测试放在 benches 目录。
  • 示例放在 examples 目录.
  • 集成测试文件放在 tests 目录.

如果一个binary、example、bench 或集成测试具有多个源文件,把 main.rs 和其他模块(modules)一起放在目录( src/binexamplesbenchestests )中的一个子目录下,可执行crate的名字就是该子目录的名字。

你可以在 the book 中了解更多关于Rust模块系统的知识。

参阅 Configuring a target 一节,有更多关于手动设置编译目标的细节。 参阅 Target auto-discovery 一节,有更多关于控制Cargo如何自动推断目标名的知识。

Cargo.toml 和 Cargo.lock

Cargo.tomlCargo.lock 具有不同的用途。在谈论之前,这里先概况一下:

  • Cargo.toml 用于宽泛地描述包的依赖,这个文件是由开发者来写。
  • Cargo.lock 包含依赖条目的更多额外信息。这个文件是由 Cargo 维护,不应手动编辑。

如果你构建的是一个非末端产品,比如一个其他 rust packages 会依赖的库,那么把 Cargo.lock 放进 .gitignore 即忽略 Cargo.lock 文件。 如果你构建是一个末端产品,比如像命令行工具或桌面应用,这样的可执行程序,或者是一个系统库 ( crate-type 为 staticlibcdylib ) , 那么就应该将 Cargo.lock 加入 git。想了解为什么要这样做, 参考 FAQ中的"为什么binary的版本控制中有 Cargo.lock ,library却没有?" 一节。

让我们更进一步。

Cargo.tomlmanifest "配置清单"文件,其中包含了一系列该包的元数据。比如,可以声明包依赖于另一个包:

[package]
name = "hello_world"
version = "0.1.0"

[dependencies]
regex = { git = "https://github.com/rust-lang/regex.git" }

包依赖简单的 regex 库。在这个例子中,我们声明包依赖于一个github上的仓库。 如果没有提供更多信息,Cargo 会假定使用该仓库 master 分支的最新 commit "提交"来构建包。

听起来不错?但是这里有一个问题:如果你今天构建了这个包,然后把代码复制一份发给了我,然后我第二天才去构建这个包,这时就可能有坏事发生。 在这期间,regex 库可能产生了更多的commit,而这些 commit 内容在你的构建中没有。 因此,构建会得到不同的结果。这一般很糟糕,因为构建总是希望一致可重复。

可以在 Cargo.toml 中定义一个 rev 字段,这样Cargo就会知道构建包时应该使用哪个具体的修订版本(revision)。

[dependencies]
regex = { git = "https://github.com/rust-lang/regex.git", rev = "9f9f693" }

现在我们两个的构建结果又一致了。但是这种方式有个很大的缺点:现在每次想更新库的时候,都必须手动来调整SHA-1字符串。这件事既无聊又容易出错。

于是 Cargo.lock 应运而生。因为它的存在,无需手动跟踪具体的修订版本。当有这样一个配置清单文件,Cargo会帮我们做这件事:

[package]
name = "hello_world"
version = "0.1.0"

[dependencies]
regex = { git = "https://github.com/rust-lang/regex.git" }

在进行第一次构建的时候,Cargo 会获取最新的commit并将信息写入 Cargo.lock 文件。 Cargo.lock 的内容如下:

[[package]]
name = "hello_world"
version = "0.1.0"
dependencies = [
 "regex 1.5.0 (git+https://github.com/rust-lang/regex.git#9f9f693768c584971a4d53bc3c586c33ed3a6831)",
]

[[package]]
name = "regex"
version = "1.5.0"
source = "git+https://github.com/rust-lang/regex.git#9f9f693768c584971a4d53bc3c586c33ed3a6831"

可以看到这个文件中有更多的信息,包括我们构建中使用的包的具体修订版本。现在当你把包发给其他人时,他们会使用完全相同的SHA,即使没有在 Cargo.toml 中标注版本号。

当我们准备切换到库的新版本时,Cargo可以重新计算依赖并帮我们更新。

$ cargo update            # 更新全部依赖
$ cargo update -p regex   # 只更新 "regex"

这会将新的版本信息覆写进 Cargo.lock 。注意, cargo update 的参数实际上是一个 Package ID Specification "包ID规格", regex 只是简写。

测试

可以使用 cargo test 命令来运行测试。Cargo 在两个地方查找测试内容: 1. src 中的每个文件;2. test 目录中的测试条目。 src 中的测试是单元测试和文档测试(documentation tests)。 tests 中的测试是集成测试, tests 中的文件需要导入 crate 。

下面的例子中对 package 执行 cargo test ,目前这个包里还没有任何测试项。

$ cargo test
   Compiling regex v1.5.0 (https://github.com/rust-lang/regex.git#9f9f693)
   Compiling hello_world v0.1.0 (file:///path/to/package/hello_world)
     Running target/test/hello_world-9c2b65bbb79eabce

running 0 tests

test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out

如果包中有测试项,就可以看到更多输出内容。

你也可以通过过滤,来运行指定的测试:

$ cargo test foo

这种情况会执行所有名字中包含 foo 的测试。

cargo test 将进行额外的检查。Cargo会编译每个示例,确保它们可以通过编译。同时也会运行文档测试来确保文档中的代码样例可以通过编译。 Rust文档中的 testing guide 部分可以获得更多关于组织测试的知识。Cargo Targets: Tests 中可以学到 Cargo 中更多不同的测试模式。

持续集成

Travis CI

为了在 Travis CI 测试你的包,这里有一个样例配置文件 .travis.yml :

language: rust
rust:
  - stable
  - beta
  - nightly
matrix:
  allow_failures:
    - rust: nightly

这将同时测试三个发布通道,每日构建中的问题不会导致整个构建的失败。 查看Travis CI Rust documentation获得更多信息。

GitHub Actions

为在Github Actions中测试你的包,这里有一个样例配置文件 .github/workflows/ci.yml :

name: Cargo Build & Test

on:
  push:
  pull_request:

env: 
  CARGO_TERM_COLOR: always

jobs:
  build_and_test:
    name: Rust project - latest
    runs-on: ubuntu-latest
    strategy:
      matrix:
        toolchain:
          - stable
          - beta
          - nightly
    steps:
      - uses: actions/checkout@v3
      - run: rustup update ${{ matrix.toolchain }} && rustup default ${{ matrix.toolchain }}
      - run: cargo build --verbose
      - run: cargo test --verbose
  

这将测试全部的三个发布通道(注意任意toolchain版本的失败会导致整个流程的失败)。 你也可以在Github界面中点击 "Actions" > "new workflow" , 并在其中选择Rust来为你的库添加 default configuration "默认设置"。 访问GitHub Actions documentation以获得更多信息。

GitLab CI

为在GitLab CI测试你的包,这里有一个样例配置文件 .gitlab-ci.yml :

stages:
  - build

rust-latest:
  stage: build
  image: rust:latest
  script:
    - cargo build --verbose
    - cargo test --verbose

rust-nightly:
  stage: build
  image: rustlang/rust:nightly
  script:
    - cargo build --verbose
    - cargo test --verbose
  allow_failure: true

这将测试 stable 通道和 nightly 通道,每日构建中的任何失败不会导致整个构建的失败。 请查看GitLab CI documentation获取更多信息。

builds.sr.ht

为在 sr.ht 测试你的包,这里有一个样例设置文件 .build.yml 。 注意将 <your repo><your project> 修改为你要clone的库以及其被clone到的目录。

image: archlinux
packages:
  - rustup
sources:
  - <your repo>
tasks:
  - setup: |
      rustup toolchain install nightly stable
      cd <your project>/
      rustup run stable cargo fetch
  - stable: |
      rustup default stable
      cd <your project>/
      cargo build --verbose
      cargo test --verbose
  - nightly: |
      rustup default nightly
      cd <your project>/
      cargo build --verbose ||:
      cargo test --verbose  ||:
  - docs: |
      cd <your project>/
      rustup run stable cargo doc --no-deps
      rustup run nightly cargo doc --no-deps ||:

这将为stable 通道和nightly 通道进行测试和构建文档,每日构建中的问题不会导致整个构建的失败。 请查看builds.sr.ht documentation以获取更多信息。

Cargo home

"Cargo home" 的功能是为下载和源代码提供缓存。 当构建crate时,Cargo会将下载的构建依赖保存在 Cargo home 中。你可以通过设置 CARGO_HOME environmental variable "环境变量" 来修改Cargo home的位置。 如果你需要在自己的crate中获取这个位置,home crate 提供了相关的API。

注意,Cargo home的内部结构规范还未稳定下来,可能会改变。

Cargo home由以下几个部分构成:

文件:

  • config.toml Cargo 的全局配置文件,参阅 参考部分的config 内容。

  • credentials.toml cargo login 的私有凭证,用于登陆某个 registry "注册中心" 。

  • .crates.toml, .crates2.json 这些隐藏文件包含通过 cargo install 下载的 package 的信息。不要手动修改这些文件!

目录:

  • bin bin目录中保存通过 cargo installrustup 下载的可执行文件。 方便在终端中直接使用这些二进制文件,可以把该目录添加到 $PATH 环境变量。

  • git Git源代码保存在这里:

    • git/db 当crate的依赖是git仓库,Cargo会将这个仓库clone到该目录下作为一个裸仓库 (只有.git文件夹中的内容) ,并在必要时更新该仓库。

    • git/checkouts 如果某个git源的代码被用到,实际的代码会从 git/db 内的仓库中checkout检出,保存在该目录下。 为编译器提供依赖指定的 commit 文件。从而可以检出同一个仓库的不同提交。

  • registry crate注册中心(比如crates.io)的元数据和下载的包保存在这个文件夹中。

    • registry/index index是一个裸仓库,其中包含着注册中心所有可用crate的元数据(版本、依赖等)。

    • registry/cache 下载的依赖项源代码保存在cache目录中。这些crate被压缩为gzip文件,以 .crate 为后缀。

    • registry/src 如果某个包需要已下载的 .crate 压缩文件,该文件会解压到 registry/src 目录,从而让rustc能找到相应的 .rs 文件。

在CI中缓存Cargo home

为避免在持续集成时重复下载所有crate依赖,你可以对 $CARGO_HOME 目录进行缓存。 但是,缓存整个Cargo home目录往往低效,因为它会把相同的代码保存两遍。 如果我们依赖一个crate叫做 serde 1.0.92 而缓存了整个 $CARGO_HOME,会把源代码存两遍( registry/cache 中的 serde-1.0.92.crate 以及解压到 registry/src.rs 文件)。 这会拖慢构建过程,下载、解压、压缩和重新上传cache到CI服务器都会消耗时间。

只需缓存以下的文件夹就足够了:

  • bin/
  • registry/index/
  • registry/cache/
  • git/db/

打包缓存项目的所有依赖

cargo vendor 子命令。

译者注:"vendor"这个词本身是个名词,意为"小贩、销售商",在软件领域往往表示"将源代码和其所依赖的第三方库统一管理"的意思。像npm的 node_modules 。 参考来源wiktionary-vendor

清除缓存

理论上,你可以删除cache的任何部分,当一个crate需要某些源码时,Cargo会帮你恢复,要么是解压已有的压缩文件或从裸仓库中检出,或从网上重新下载源文件。

另一种方法是,cargo-cache crate 提供了一个CLI工具来只清除cache中选中的部分和显示cache组成部分所占用的空间大小。

构建缓存

Cargo会把构建输出保存在 "target" 文件夹中。默认情况下这个文件夹是你的 workspace 根目录下的 target 文件夹。 如果要改变输出位置,可以设置 CARGO_TARGET_DIR environment variable "环境变量"、 build.target-dir config参数,或者 --target-dir 命令行标志(flag)。

这个文件夹的布局取决于你是否使用 --target 标志来为特定平台构建。如果没有设置 --target 标志,Cargo 会按宿主机的架构进行构建。 输出文件保存在target文件夹,每个特定编译设置 (profile) 的输出文件会在放在单独的子文件夹中。

文件夹描述
target/debug/包含 dev 编译设置的输出文件。
target/release/包含 release 编译设置 (构建时带 --release 选项) 的输出文件。
target/foo/包含 foo 编译设置 (构建时带 --profile=foo 选项) 的输出文件。

由于历史原因, devtest 编译设置的输出文件被放在 debug 文件夹中, releasebench 编译设置的输出文件被放在 release 文件夹。用户自定义编译设置的输出文件放在同名的文件夹中。

当为另一种架构 (非宿主架构,命令行带 --target 参数) 而构建,输出文件会放在带有目标架构名字的文件夹中:

文件夹例子
target/<triple>/debug/target/thumbv7em-none-eabihf/debug/
target/<triple>/release/target/thumbv7em-none-eabihf/release/

注意: 如果没有使用 --target,Cargo会把你的依赖共享给构建脚本(build scripts)和过程宏(proc macros)使用。 RUSTFLAGS 会在每次 rustc 调用时使用。 如果使用了 --target 标志,构建脚本和过程宏会为宿主架构单独构建,不会获取 RUSTFLAGS 中的参数。

在每个编译设置(profile)的输出文件夹中 (比如 debugrelease),制品会被放在以下几个文件夹中:

文件夹描述
target/debug/包含该包的制品 (二进制可执行文件库文件).
target/debug/examples/包含示例的制品 example targets.

一些命令会把生成文件放在 target目录的顶层:

目录描述
target/doc/包含 rustdoc 生成的文档 (cargo doc 命令)。
target/package/包含 cargo packagecargo publish 命令生成的文件。

Cargo还会生成构建过程需要的其他文件和文件夹,它们的组织结构看做Cargo内部项,可能会更改。其中几个文件夹:

目录描述
target/debug/deps/依赖以及其他制品。
target/debug/incremental/rustc 增量编译输出,加速构建过程的一些缓存文件。
target/debug/build/构建脚本 的输出。

Dep-info files

还有一个后缀为 .d 的 "依赖信息" 文件(dep info),类似Makefile,记录了再次构建所需的文件依赖。 这个文件用于提供给外部的构建系统,判断是否需要再次执行Cargo。文件中的文件路径在默认情况下都是绝对路径。如何设置为相对路径见 build.dep-info-basedir

# dep-info 文件的例子: target/debug/foo.d
/path/to/myproj/target/debug/foo: /path/to/myproj/src/lib.rs /path/to/myproj/src/main.rs

共享缓存

第三方工具 sccache 可以跨工作空间共享构建依赖。

通过 cargo install sccache 下载 sccache。在执行Cargo前,将 RUSTC_WRAPPER 环境变量设置为 sccache。 如果你用的是bash,那么可以把 export RUSTC_WRAPPER=sccache 添加到 .bashrc 。 或者你可以在 Cargo配置文件 中设置 build.rustc-wrapper 。查看sccache的文档来获取更多细节。

Cargo 参考

参考涵盖Cargo各个领域的细节。

指定依赖

你的crate能够依赖于其他库,其库可以来自 crates.io 、其他注册中心、git仓库、本地文件系统中的子目录。 你可以暂时覆盖某个依赖的路径,从而在本地检查和修复依赖的bug。 对于不同目标平台可以指定不同的依赖,也可以仅在开发阶段指定使用某个依赖。

指定crate.io中的依赖

Cargo默认从 crates.io 查找依赖。之前在 cargo指南 中指定了 time crate 作为依赖:

[dependencies]
time = "0.1.12"

"0.1.12" 这个字符串表示限定的版本,虽然貌似表示一个具体的 time 版本,但实际上表示一个范围,接受 SemVer 语义化兼容的更新。 具体来说,接受不改变 主版本号.次版本号.修订号第一个非零数字 的所有更新。 如果运行 cargo update -p time ,Cargo 会把 time 更新到 0.1.13 (假设 0.1.z 表示的最新版本),但不会更新到 0.2.0。 如果指定版本为 1.0 ,那么Cargo 会将其更新到 1.1 (假设 1.y 表示的最新版本),但不会更新到 2.00.0.x 版本和其他版本都不兼容。

下面是一些书写示例,以及符合要求的版本范围:

1.2.3  :=  >=1.2.3, <2.0.0
1.2    :=  >=1.2.0, <2.0.0
1      :=  >=1.0.0, <2.0.0
0.2.3  :=  >=0.2.3, <0.3.0
0.2    :=  >=0.2.0, <0.3.0
0.0.3  :=  >=0.0.3, <0.0.4
0.0    :=  >=0.0.0, <0.1.0
0      :=  >=0.0.0, <1.0.0

这种兼容规则与SemVer规则有所不同,SemVer认为在1.0.0之前都不兼容,而Cargo认为 0.x.y0.x.z兼容 (只要 y ≥ zx > 0)。

可以通过一些特殊操作符来调整选择兼容版本的逻辑,但在大多数情况不需要。

使用 ^ 符号

^ 符号表示默认策略,^1.2.31.2.3 的意义相同。

使用 ~ 符号

~ 符号表示在某个最小版本的基础上可以做指定更新。 如果指定了如 主.次.修 或者 主.次 的版本,那么可以做修订级别的改变。 如果是只指定了主版本号,那么次版本号和修订号可以改变。

~1.2.3 的例子:

~1.2.3  := >=1.2.3, <1.3.0
~1.2    := >=1.2.0, <1.3.0
~1      := >=1.0.0, <2.0.0

使用 * 通配符

通配符出现的位置表示任意数字。

比如 *1.*1.2.*

*     := >=0.0.0
1.*   := >=1.0.0, <2.0.0
1.2.* := >=1.2.0, <1.3.0

注意: crates.io 不允许单独的 *

使用比较符号

使用比较符号可以手动指定版本范围或一个具体的版本。

下面是一些例子:

>= 1.2.0
> 1
< 2
= 1.2.3

多重约束

参考上面的示例,多个版本约束可以用逗号分隔,如 >= 1.2, < 1.5

指定来自其他注册中心的依赖

要指定非 crates.io 的依赖,首先须在 .cargo/config.toml 中设置该注册中心,参见 registries documentation 。 在依赖中,将 registry 字段设置为要使用的注册中心。

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

注意: crates.io 发布包不允许带有其他注册中心的依赖。

指定来自 git 的依赖

要指定位于 git 仓库的依赖,需要的最少信息是在 git 字段中给出该仓库的地址:

[dependencies]
regex = { git = "https://github.com/rust-lang/regex.git" }

Cargo 会 fetch 该 git 仓库,并在仓库中查找所需crate对应的 Cargo.toml 文件(该文件不要求必须在地址根目录下,比如说指定的是工作空间某个成员crate,这时 git 字段只需给出工作空间的地址)。

因为没有指定其他信息,Cargo会假设使用该仓库主分支的最新提交。 也可以在 git 字段后加上 revtagbranch 字段,来指定想要的提交。下面是一个指定 next 分支上最新提交的例子:

[dependencies]
regex = { git = "https://github.com/rust-lang/regex.git", branch = "next" }

如果想要指定的依赖版本不是某个分支或标签,那么用 rev 来指定。 rev 字段可以是 rev = "4c59b707" 这样的提交hash,也可以是 rev = "refs/pull/493/head" 这样的名称。 哪些引用是合法的取决于这个git仓库具体的管理组织。 Github 公开每个 pull requeset 最新提交的引用,其他git组织一般也提供类似的信息,只是可能有不同的命名规则。

一旦添加某个 git 依赖,Cargo会立即锁定到该依赖最新的提交。 之后即使有新的提交,Cargo也不会自动拉取。可以通过 cargo update 命令来手动拉取。

对于私有仓库的身份验证,参考 Git 身份验证

注意: crates.io 发布的包不允许带有 git 依赖 (git dev-dependencies 除外) 。关于备用方案,参考 Multiple locations

指定路径依赖

经过一段时间,指南 中的 hello_world 包内容增多了。可能需要把其中一部分拆出来。 Cargo 为此提供了指定路径依赖的功能,常见的情况是一个 git 仓库中有很多个子 crate 。 首先在 hello_world 项目里面创建一个新的 crate :

# hello_world/ 目录中
$ cargo new hello_utils

这将创建新的 hello_utils 文件夹,其中已经设置好了 Cargo.tomlsrc 文件夹。 为了让Cargo知道新crate的存在,需要在 hello_world/Cargo.toml 中将 hello_utils 添加为依赖:

[dependencies]
hello_utils = { path = "hello_utils" }

这会告诉Cargo依赖了一个名为 hello_utils 的crate,在 hello_utils 文件夹中(相对于 Cargo.toml 的位置)。

搞定!下次执行 cargo build 会自动构建 hello_utils 和它的所有依赖,其他包也可以使用这个crate。 但 crates.io 发布的包不允许以路径指定某个依赖。 如果我们想发布 hello_world,就必须把 hello_utils 发布到 crates.io,然后在 hello_word 配置中指定依赖版本:

[dependencies]
hello_utils = { path = "hello_utils", version = "0.1.0" }

注意: crates.io 不允许发布带 path 依赖的包( path dev-dependencies 除外)。对于备用选择,参考Multiple locations

多依赖位置

可以同时指定注册中心、 gitpath 位置的依赖项。 gitpath 依赖项用于本地( version 会与本地副本进行对比), 而要发布到一个注册中心 (比如crates.io) 时,需要使用注册中心中的版本,不允许其他组合。例如:

[dependencies]
# 在本地时使用 `my-bitflags`
# 而上传后使用 crates.io 中的 1.0 版本
bitflags = { path = "my-bitflags", version = "1.0" }

# 在本地时使用给定的 git 仓库
# 而上传后使用 crates.io 中的1.0 版本
smallvec = { git = "https://github.com/servo/rust-smallvec.git", version = "1.0" }

# 如果 version 不能匹配,Cargo 会编译失败!

比如这种使用场景,当你把一个库拆分成工作空间中的多个包, 在开发阶段,可以用 path 指定工作空间内的本地包做为依赖,而将其发布后,就可以使用 crates.io 上的版本了。

平台特定依赖

平台特定依赖的书写格式没什么变化,但是要列在 target 部分。 通常使用与rust代码类似的 #[cfg] 语法:

[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" }

如同rust代码一样,语法支持 notanyall 操作符,从而组合不同的cfg键值对。

如果你想知道自己的平台支持哪些cfg目标,可以运行 rustc --print=cfg 来获取。 如果你想知道其他平台可用的cfg目标,可以使用 rustc --print=cfg --target=x86_64-pc-windows-msvc

与rust代码不同,你不能使用 [target.'cfg(feature = "fancy-feature")'.dependencies] 根据特性指定依赖,而应该使用 features

[dependencies]
foo = { version = "1.0", optional = true }
bar = { version = "1.0", optional = true }

[features]
fancy-feature = ["foo", "bar"]

cfg(debug_assertions)cfg(test)cfg(proc_macro) 也是同样的,这些值不生效。 总是有 rustc --print=cfg 返回的默认值。目前,无法根据这些设置添加依赖。

#[cfg] 标志,Cargo支持直接写出target全名来指定依赖:

[target.x86_64-pc-windows-gnu.dependencies]
winhttp = "0.4.0"

[target.i686-unknown-linux-gnu.dependencies]
openssl = "1.0.1"

为自定义目标指定依赖

如果使用自定义构建目标 (比如 --target foo/bar.json ),使用不含 .json 后缀的文件名:

[target.bar.dependencies]
winhttp = "0.4.0"

[target.my-special-i686-platform.dependencies]
openssl = "1.0.1"
native = { path = "native/i686" }

注意: 在稳定版不支持自定义目标依赖。

开发依赖

你可以在 Cargo.toml 中添加 [dev-dependencies] ,格式与 [dependencies] 一致:

[dev-dependencies]
tempdir = "0.3"

在构建包时不会使用开发依赖,而是用在编译测试、实例和性能测试。

这些依赖 不会 传播给依赖此包的那些包。

你也可以为特定目标指定开发依赖,只需要把 dependencies 换成 dev-denpendencies

[target.'cfg(unix)'.dev-dependencies]
mio = "0.0.1"

注意: 当发布包时,只有那些以 version 指定的开发依赖才会包含在发布的包中。 大部分情况下,包发布后就不需要开发依赖了,但是也有一些使用者(比如操作系统包)希望在crate中运行一些测试,所以给开发依赖提供一个 version 也是有益处。

构建依赖

你可以在构建脚本中使用其他基于cargo的crate。在配置清单中指定 build-dependencies 来声明依赖。

[build-dependencies]
cc = "1.0.3"

你也可以为特定目标指定构建依赖,只需将 dependencies 替换为 build-dependencies 。例如:

[target.'cfg(unix)'.build-dependencies]
cc = "1.0.3"

这样,只有当主机平台满足指定目标要求时,才会构建相关依赖。

构建脚本无法使用 dependenciesdev-dependencies 中列出的依赖。 同样的,除非依赖放在 dependencies 中,包也无法使用构建依赖 (build-dependencies) 中的。 一个包和它的构建脚本是各自分开编译的,因此它们的依赖项不需要相同。 Cargo 不同目的使用各自的依赖,以保持简洁。

选择特性

如果你依赖的包提供了可选的特性(feature),可以选择使用:

[dependencies.awesome]
version = "1.3.5"
default-features = false # 不使用默认特性
                         # 手动选择单独的特性
features = ["secure-password", "civet"]

关于特性的更多信息,参考 features chapter

Cargo.toml 中重命名依赖

当你在 Cargo.toml 中添加 [dependencies] 时,依赖名称就是导入代码的crate名称。 但在某些项目中,可能想要用另一个名称来引用这个crate,而不是它在crates.io上的名称。比如,你想:

  • 避免在代码中使用 use foo as bar
  • 同时使用某个crate的多个版本。
  • 依赖不同注册中心同名的包。

Cargo 通过在 [dependencies] 加入package 字段来支持此功能。

[package]
name = "mypackage"
version = "0.0.1"

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

在这个例子中,这三个crate都在代码中可用:

extern crate foo; // crates.io
extern crate bar; // git repository
extern crate baz; // registry `custom`

这三个crate在自身的 Cargo.toml 里都名为 foo ,用 package 来可以声明想要的那个 foo 包,在本地用另一个别名。 如果没有指定 package ,则认为包的名称与依赖名称一致。

注意,如果你有一个可选依赖:

[dependencies]
bar = { version = "0.1", package = 'foo', optional = true }

你依赖的是 crates.io 上的 foo 包,但是,需要指定的是 bar 的特性,而不是 foo 的特性。 即,如果你给一个依赖改了名,需要使用新的名称,而不是原本的名称。

依赖传递也是如此。比如,可以把下面的条目加入配置清单:

[features]
log-debug = ['bar/log-debug'] # 用 'foo/log-debug' 会报错!

从工作空间中继承依赖

可以在工作空间的 [workspace.dependencies] 字段指定依赖, 然后在 crate 的 [dependencies] 中添加 workspace = true 就可以继承这个依赖。

除了 workspace 字段,还可以加入:

  • optional: 注意 [workspace.dependencies] 不允许使用 optional
  • features: 这是对于 [workspace.dependencies] 中声明的依赖的补充。

optionalfeatures 之外,继承依赖不允许使用任何其他字段 (比如 versiondefault-features) 。

[dependencies][dev-dependencies][build-dependencies][target."...".dependencies] 都可以引用 [workspace.dependencies] 中定义的依赖。

[package]
name = "bar"
version = "0.2.0"

[dependencies]
regex = { workspace = true, features = ["unicode"] }

[build-dependencies]
cc.workspace = true

[dev-dependencies]
rand = { workspace = true, optional = true }

覆盖依赖

在很多场景下可能会希望覆盖一个依赖。大部分情况是在包发布到 crates.io 之前覆盖。比如:

  • 你正在写的一个crate被另一个更大的应用(app)使用,而你希望在这个app中测试对该crate的一个bug修复。
  • 一个不属于你的上游crate在其git仓库的master分支增加了一些新特性,或修复了一些bug,你想要测试一下。
  • 你准备给自己的crate发布一个新的主版本(major version),但是你想先在整个包上做一下集成测试来确保正确性。
  • 你已经给一个上游crate提交了bug修复,但是现在想立刻让你的app使用这个修复后的crate,避免等待这个bug修复合并。

这些问题都可以通过配置清单中的 [patch] 部分来解决。

本章将从几种不同使用案例出发,详细介绍各种覆盖依赖的方法。

注意: 也可以参考使用 multiple locations 多位置依赖来指定依赖条目,这个方法可以在本地覆盖依赖的源。

测试bugfix

例如,你正在使用 uuid crate 却发现bug。你打算自己修复这个bug!配置清单初始可能是这样:

[package]
name = "my-library"
version = "0.1.0"

[dependencies]
uuid = "1.0"

我们首先要做的是把 uuid 仓库 clone下来:

$ git clone https://github.com/uuid-rs/uuid.git

然后修改自己的 my-library 包的配置清单来包含clone下来的uuid:

[patch.crates-io]
uuid = { path = "../path/to/uuid" }

这里我们声明用新的依赖 覆盖 (patching) crates-io 源。 这会将我们刚下载到本地的 uuid 添加到 crates.io 中(仅仅针对这个本地项目)。

接着我们需要更新 lock file ,以保证我们使用的是下载到本地的 uuid[patch] 的原理是加载位于 ../path/to/uuid 的依赖,当需要从 crates.io 中获取 uuid 的某个版本时,而返回本地的版本。

这意味着本地版本的版本号是很重要的,会影响是否实际选用本地版本。 我们配置清单中声明 uuid = "1.0" ,表示请求 >= 1.0.0, < 2.0.0 的包, Cargo的"贪婪策略"意味着会得到这个范围内最高版本。 一般无需关心这点,因为 git 仓库里的版本总是高于或者等于 crates.io 中的最高版本,但需明白原理!

你现在需要做的是:

$ cargo build
   Compiling uuid v1.0.0 (.../uuid)
   Compiling my-library v0.1.0 (.../my-library)
    Finished dev [unoptimized + debuginfo] target(s) in 0.32 secs

搞定。现在构建使用的就是本地版本的 uuid (注意构建输出中括号中的路径)。 如果构建的不是本地版本,那可能需要运行 cargo update -p uuid --precise $version$version 是本地版本 uuid 的版本号。

当你解决了之前发现的bug,接下来要做的事可能是将其通过 pull request 提交给 uuid 仓库。 之后,pull request 被合并后,可以更新 [patch] 部分,可以把 path 依赖改为 git 依赖, [patch] 中条目的功能和 [dependencies] 一样:

[patch.crates-io]
uuid = { git = 'https://github.com/uuid-rs/uuid.git' }

使用未发布的crate次要版本

现在让我们从修复bug转到添加特性。在写 my-library 时你发现需要在 uuid 里加新特性。 你已经实现了这个特性并在本地通过 [patch] 进行了测试,然后提交了 pull request。 现在我们来看,怎样在这个crate实际发布前继续测试和使用它。

假设 uuid 目前在crates.io上的最新版为 1.0.0,但 git 仓库上的最新版是 1.0.1,也就是你之前提交的新特性。为了使用这个版本,我们把 Cargo.toml 改成了这样:

[package]
name = "my-library"
version = "0.1.0"

[dependencies]
uuid = "1.0.1"

[patch.crates-io]
uuid = { git = 'https://github.com/uuid-rs/uuid.git' }

我们的 uuid 本地版本是 1.0.1,这也是当这个crate被发布后我们所需的版本。 目前这个版本在 crates.io 中还不存在,所以需要使用 [patch] 来声明。

现在,当我们构建库时,Cargo会从git仓库fetch这个 uuid ,解析版本为 1.0.1,而不是尝试从 crates.io 下载。而当 1.0.1 在crates.io发布后,就可以删除这个 [patch] 了。

值得一提的是 [patch] 支持传递依赖。比如我们在另一个更大的包中使用了之前的 my-library :

[package]
name = "my-binary"
version = "0.1.0"

[dependencies]
my-library = { git = 'https://example.com/git/my-library' }
uuid = "1.0"

[patch.crates-io]
uuid = { git = 'https://github.com/uuid-rs/uuid.git' }

注意,[patch] 将传递,但是只能在 顶层 定义,所以作为 my-library 的用户我们必要时需要重复写一遍 [patch] 。 在本例中,新的 uuid crate 同时作用于 uuidmy-library -> uuid 这两个依赖。 整个依赖图中,uuid 只使用了我们从git仓库拉下来的 1.0.1 这个版本。

覆盖git仓库的URL

如果你想要覆盖的依赖不在crates.io上,那么就需要改变使用 [patch] 的方法。比如说一个位于git仓库的依赖,你需要这样覆盖为本地路径:

[patch."https://github.com/your/repository"]
my-library = { path = "../my-library/path" }

OK了。

预发布一个破坏性更新

更新主版本一般来说会有破坏性的更新(breaking change)。拿之前的crate举例,我们创建 uuid 的2.0.0版。把所有改动提交给上游后,更新 my-library 的配置清单为:

[dependencies]
uuid = "2.0"

[patch.crates-io]
uuid = { git = "https://github.com/uuid-rs/uuid.git", branch = "2.0.0" }

很好。就像之前的例子一样,因为crates.io中实际上没有2.0.0版,我们实际上通过 [patch] 使用了git仓库中的版本。 作为练习,再看看 my-binary 的配置清单:

[package]
name = "my-binary"
version = "0.1.0"

[dependencies]
my-library = { git = 'https://example.com/git/my-library' }
uuid = "1.0"

[patch.crates-io]
uuid = { git = 'https://github.com/uuid-rs/uuid.git', branch = '2.0.0' }

注意,这里会解析出两个版本的 uuidmy-binary 会继续使用 1.x.y 版的 uuid ,而 my-library 会使用 2.0.0 版。 这种解析逻辑允许你在依赖图中逐步应用某个crate的破坏性更新,而不是强制把这个破坏性更新一次性应用到整个依赖图。

多版本情况下使用 [patch]

你可以通过 package 重命名来对同一个crate有多个patch。比如说我们想使用 serde 一个 1.* 版的bug修复(还没发布到crates.io),同时也想使用git仓库中 serde2.0.0 版来构建原型。这时可以设置:

[patch.crates-io]
serde = { git = 'https://github.com/serde-rs/serde.git' }
serde2 = { git = 'https://github.com/example/serde.git', package = 'serde', branch = 'v2' }

第一个 serde = ... 命令指示从git仓库中下载 serde 1.* 版 (我们需要的bug修复),第二个 serde2 = ... 指示从 https://github.com/example/serdev2 分支中下载serde的 2.0.0 版 (我们假设git仓库中该分支中的 Cargo.toml 中声明这个crate的版本是 2.0.0)。

注意,这里 serde2 用到了 package ,从而会忽略 serde2 标识符,只是一个和其他patch不冲突的占位。

[patch] 部分

Cargo.toml 中的 [patch] 部分可以用其他版本覆盖某个依赖。语法与 [dependencies] 相似。

[patch.crates-io]
foo = { git = 'https://github.com/example/foo.git' }
bar = { path = 'my/local/bar' }

[dependencies.baz]
git = 'https://github.com/example/baz.git'

[patch.'https://github.com/example/baz']
baz = { git = 'https://github.com/example/patched-baz.git', branch = 'my-branch' }

注意: [patch] 也可以被设置为 configuration option ,比如 .cargo/config.toml 文件或者命令行选项,如 --config 'patch.crates-io.rand.path="rand"'。 这对于你不打算 commit 的本地修改,或是临时测试某个 patch 很方便。(译者注:因为这样就不用写到Cargo.toml里面,不修改现有文件的内容)。

[patch] 表和 dependencies 表很类似。[patch] 的key是源的URL,或者是注册中心的名称。 crates-io 用于覆盖默认的注册中心 crates.io。 上面的例子里第一个 [patch] 用于展示对 crates.io 的覆盖,第二个 [patch] 展示对一个git源的覆盖。

[patch] 表中的条目就是普通的依赖项,与[dependencies] 里的一样。这些依赖用于覆盖 URL 指定源中的相应crate。 上面例子中覆盖了 crates-io 源中的 foo crate 和 bar brate。 同时,其也用另一个git仓库中的 my-branch 分支覆盖了 https://github.com/example/baz 源。

可以对源中某个crate尚不存在的版本进行覆盖,也可以对存在的版本进行覆盖。 如果覆盖的是源中crate的已存在版本,则实际上是把这个版本替换掉了。

Cargo 只读取工作空间中顶层 Cargo.toml 中的 [patch] 设置,会忽略依赖中的patch设置。

[replace] 部分

注意: [replace] 已经废弃,你应该使用 [patch]

Cargo.toml的这个部分用来以其他拷贝来覆盖某个依赖。语法与 [dependencies] 相似。

[replace]
"foo:0.1.0" = { git = 'https://github.com/example/foo.git' }
"bar:1.0.2" = { path = 'my/local/bar' }

[replace] 表中的每个key都是 package ID specification,其可以覆盖依赖图中的任意一个节点 (需要以三数字格式标明版本号)。 每个key对应的value与 [dependencies] 中依赖格式相同 (除了不能使用 feature 字段以外)。用于覆盖的crate必须与被覆盖的crate版本相同,但是可以来自不同的源 (比如git或本地路径)。

Cargo 仅读取工作空间中顶层 Cargo.toml 中的 [replace] 设置,会忽略依赖中的设置。

paths 覆盖

有时你仅仅想临时使用一个crate,而不想修改 Cargo.toml (比如[patch] 字段),为此 Cargo 提供了一个更简单但功能有限的 路径覆盖 (path overrides) 功能。

路径覆盖可以通过 .cargo/config.toml 而不是 Cargo.toml 来指定。在 .cargo/config.toml 中,你可以指定一个名为 paths 的key:

paths = ["/path/to/uuid"]

这个数组中应该填写一系列包含一个 Cargo.toml 文件的路径。在这个例子中,我们只添加了 uuid ,所以只有这个ctate被覆盖。这个路径可以是绝对地址,也可以是 包含.cargo目录 那个文件夹的相对路径。

译者注:举例来说:

比如你的路径格式为:

rust
├── .cargo
│   └── config.toml
├── .rustup
└── overrides
    └── uuid
        └── Cargo.toml

那么相应的在 config.toml 中应该写:

paths = ["overrides/uuid"]

而且paths字段应写在文件的最上方,不在任何一个 [xxx] 的下面,才能生效。

路径覆盖比 [patch] 更严格,其无法改变依赖图的结构。替换路径后,之前所有的依赖必须满足新 Cargo.toml 的要求。 这意味着路径覆盖无法在测试时给某个crate添加依赖,这种情况只能使用 [patch] 。因此,路径覆盖一般只用于孤立地修改某个crate,以快速修复其中的bug,而不应用于更大规模的修改。

注意:用本地设置来进行路径覆盖,仅能用于那些已经发布在 crates.io 上的包。你无法把这个功能用于让Cargo查找本地的未发布crate。

配置清单格式

每个包的 Cargo.toml 内容称为 manifest "配置清单" ,以TOML格式编写。 其包含编译包时所需的元数据。要了解更多关于cargo如何查找配置清单文件的细节,请查看 cargo locate-project 部分。

配置清单内容由以下部分组成:

[package] 部分

Cargo.toml 中首先的部分就是 [package]

[package]
name = "hello_world" # 包的名称
version = "0.1.0"    # 当前的语义化版本。
authors = ["Alice <a@example.com>", "Bob <b@example.com>"]

Cargo 仅需要的字段是 nameversion 。 如果发布到注册中心,那么可能需要额外的字段。 关于发布到crates.io的要求,请参见下面的注释和发布章节

name 字段

包的名称是用来引用包的标识符。 可被列为另一个包的依赖,并作为lib和bin目标所推断的默认名称。

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

需注意, cargo newcargo init 对包名有一些额外的限制,如强制要求为有效的Rust标识符,而不能是关键字。 crates.io有更多的限制,比如说:

  • 仅允许ASCII字符。
  • 不能使用保留名称。
  • 不要使用特殊的Windows名称,如 "nul" 。
  • 最长使用64个字符。

version 字段

Cargo 遵循 语义化版本 的概念,遵循一些基本规则:

  • 在达到1.0.0之前,可以任意演进,但如果做了破坏性的改变,就要增加次要版本。在Rust中,破坏性修改包括向结构体添加字段或向枚举添加变体。
  • 在1.0.0之后,只有在递增主版本的时候才可以进行破坏性的修改。不要破坏构建。
  • 1.0.0之后,不要在补丁版本中添加任何新的公共API(即没有新的 pub 接口)。如果添加任何新的 pub 结构体、trait、字段、类型、函数、方法或其他内容,总是递增次要版本。
  • 使用有三个数字部分的版本号,如1.0.0而不是1.0。

请参阅 Resolver 章节,了解更多关于Cargo如何使用版本号来解析依赖,以及自己设置版本号的指南。 参阅 语义化兼容性 一章,以了解更多关于什么是破坏性变化的细节。

authors 字段

可选的 authors 字段,以数组形式列出包的 "作者" 人或组织。 确切的意思有多种解释--可以列出原始或主要的作者、当前的维护者或者包的所有者。 可以在每个作者条目末尾的斜方括号内包含可选的电子邮件。

[package]
# ...
authors = ["Graydon Hoare", "Fnu Lnu <no-reply@rust-lang.org>"]

这个字段仅在包的metadata 和 build.rs 中的 CARGO_PKG_AUTHORS 环境变量中出现。不显示在 crates.io 用户界面中。

警告: 包的配置一旦发布就不能改变,所以不能在包已发布版本中改变或删除这个字段。

edition 字段

edition 是可选的键,影响包编译的 Rust Edition "版次"。 在 [package] 中设置 edition 键会影响到包中的所有targets/crates,包括测试套件、性能测试、二进制文件、实例等。

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

大多数配置清单的 edition 字段由 cargo new 自动填充,为最新的稳定版本。 cargo new 默认创建的是2021版。

如果 Cargo.toml 中没有 edition 字段,那么为了向后兼容,将假定为2015版。 请注意,凡是用 cargo new 创建的配置清单不会使用这种历史版次,而会将 edition 指定为一个较新的值。

rust-version 字段

rust-version 字段是可选的键,它告知cargo包可以用哪个版本的Rust语言和编译器来编译。 如果当前选择的Rust编译器的版本比声明的版本早,cargo会退出,并告诉用户需要什么版本。

第一个支持这个字段的Cargo版本是随着Rust 1.56.0发布的。 在旧版本中,这个字段会被忽略,Cargo会显示一个警告。

[package]
# ...
rust-version = "1.56"

Rust版本必须是由两或三个部分组成的基础版本号,不能包括语义化操作符或预发布标识符。 在检查Rust版本时,将忽略编译器的预发布标识符,如-nightly。 rust-version 必须等于或高于首次引入配置的 edition 的版本。

可以使用 --ignore-rust-version 选项忽略 rust-version

[package] 中设置 rust-version 键将影响包中的所有 target/crates ,包括测试套件、性能测试、二进制文件、实例等。

description 字段

是包的简介。crates.io会在包中显示这个内容,需是纯文本(不是Markdown)。

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

注意: crates.io 需要 description 设置。

documentation 字段

documentation 字段指定托管了crate文档网站的URL。 如果配置清单文件中没有指定URL,则 crates.io 会自动将你的crate链接到相应的 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/"

repository 字段

repository 字段应是包的源存储库的URL。

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

licenselicense-file 字段

license 字段包含软件许可证的名称,包根据该许可证发布。 license-file 字段包含许可证文本的文件路径(相对于当前 Cargo.toml )。

crates.iolicense 字段解释为 SPDX 2.1 license expression 。 该名称必须是 SPDX license list 3.11 中的一个已知许可证。 目前不支持括号。更多信息请参见 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][link] 部分找到。

例如,可以指定链接名为 "git2" 的本地库crate (如Linux上的 libgit2.a )。

[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目录
  • 支持常见的通配符模式,如 *? ,和 []
    • * 匹配除 / 以外的零个或多个字符。例如, *.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-* 指令的 build script ,那么 include/exclude 列表就用来跟踪这些文件变化,推断构建脚本是否应该重新运行。

publish 字段

publish 字段可以用来防止一个包被错误地发布到包注册中心(如crates.io),比如,在公司里需要保持包为私密的。

[package]
# ...
publish = false

该值也可以是一个字符串数组,这些字符串是允许发布的注册中心的名称。

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

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

metadata

默认情况下,Cargo会对 Cargo.toml 中未使用的键发出警告,以帮助检测错别字之类的。 然而,Cargo 完全忽略 package.metadata 表,不会警告。 这一部分可以用于一些包工具在 Cargo.toml 中存储配置。比如说:

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

# 例如,生成Android APK时使用的元数据。
[package.metadata.android]
package-name = "my-awesome-android-app"
assets = "path/to/static"

在工作空间层级也有类似的表,位于 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"

[badges] 部分

[badges] 部分用于指定状态标志,当包发布时可以在注册中心网站上显示。

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

[badges]
# `maintenance` 表表示crate的维护状态。
# 这可能被一个注册中心使用,但目前crates.io没有使用。
# 参阅 https://github.com/rust-lang/crates.io/issues/2437 和 https://github.com/rust-lang/crates.io/issues/2438。
#
# `status` 字段是必填字段。可用的选项有:
# - `actively-developed`: 新功能正在添加,bug正在修复。
# - `passively-maintained`: 目前还没有新功能的计划,但维护者打算对提交的问题作出回应。
# - `as-is`:  这个板块的功能是完整的,维护者不打算继续工作或提供支持,但它可以满足它所设计的目的。
# - `experimental`: 作者希望与社区分享,但并不打算满足任何人的特定使用情况。
# - `looking-for-maintainer`: 目前的维护者想把这个crate转让给其他人。
# - `deprecated`: 维护者不建议使用这个crate (crate的描述可以说明原因,可能有更好的解决方案,或者crate可能存在作者不想修复的问题)。
# - `none`: 在crates.io上未显示标志,因为维护者没有选择说明他们的意图,潜在的crate用户需要自己去查寻。
maintenance = { status = "..." }

依赖部分

参阅 指定依赖[dependencies] , [dev-dependencies] , [build-dependencies] , 和 target-specific [target.*.dependencies] 部分.

[profile.*] 部分

[profile] 表提供了一种定制编译器设置的方法,如优化和调试设置。 更多细节请参见编译设置章节

Cargo 构建目标

Cargo 包主要在于 构建目标 ,对应于可以编译成 crate 的源文件。 构建目标包括 library, binary, example, testbenchmark 。 可以在 Cargo.toml 配置清单中设置构建目标列表,但总是会通过源文件的 目录结构 自动推断

关于构建目标的配置,参阅下面的 配置构建目标 部分。

定义 "library" 库目标 ,可以被其他库和可执行程序使用和链接。 默认的根文件是 src/lib.rs ,库的名称默认就是包的名称。 包仅能有一个库。可以在 Cargo.toml[lib]自定义 设置。

# 在 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 将可执行文件拷贝到共享目录。

# 在 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 <实例名> 参数,来运行指定实例。 使用 cargo install 命令,带 --example <实例名> 参数,将二进制可执行文件复制到共享目录。 使用 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多个核心。 如果你需要进行大量集成测试,推荐创建单个集成测试,并将测试分割成多个模块。 库测试 harness "控制" 会自动寻找和并行执行所有 #[test] 标记的函数。 你可以将模块名传递给 cargo test 来将测试的范围限定在模块内。

二进制构建目标的集成测试是自动构建的。这样集成测试可以检验二进制文件执行的行为。 集成测试在构建时会设置 CARGO_BIN_EXE_<name> environment variable 环境变量,这样就可以使用 env macro 来确定可执行文件的位置。

性能测试

使用 cargo bench 命令来测试代码的性能。它与 tests 遵循相同的结构,需要性能测试的函数要用 #[bench] 标记。 以下几点与测试相似:

  • 性能测试的文件放置在 benches 目录 下。
  • 库和二进制文件中定义的性能测试可以访问构建目标中定义的 私有 API。 benches 目录下的性能测试仅能访问 公有 API 。
  • bench 字段 可以用来定义默认对哪个构建目标进行性能测试。
  • harness 字段 可以用来禁用内置的 harness 。

注意: #[bench] attribute 目前还不稳定并且仅在 每日构建通道 中提供。 crates.io 提供的一些包也许有助于在 stable channel 中运行性能测试, 比如 Criterion

配置构建目标

对于指定构建目标应该如何构建,Cargo.toml 中所有的 [lib], [[bin]], [[example]], [[test]][[bench]] 标记都支持相似的配置。 比如 [[bin]] 这种双层括号标记代表 array-of-table of TOML, 意味着你可以在 crate 添加多个 [[bin]] 来生成多个可执行文件。 比如 [lib] 代表普通 TOML 列表,意味着仅可以设置库。

下面是 TOML 中构建目标设置的概览,针对每个字段都有详细介绍。

[lib]
name = "foo"           # 构建目标的名称
path = "src/lib.rs"    # 构建目标的源文件相对路径
test = true            # 是否默认进行测试
doctest = true         # 文档示例是否默认进行测试
bench = true           # 是否默认进行性能测试
doc = true             # 是否默认带有文档
plugin = false         # 是否用作编译器插件(已弃用)
proc-macro = false     # proc-macro 库要设置为 `true`
harness = true         # 是否使用库测试harness
edition = "2015"       # 构建目标的版本
crate-type = ["lib"]   # 要生成的 crate 类型
required-features = [] # 构建此目标需要使用的特性 (库不适用)

name 字段

name 字段指定构建目标的名称,它对应着自动生成的制品的文件名。 对库来说,这个字段是它的 crate 名称,其他依赖会使用这个名称而引用该库。

对于 [lib] 和默认的二进制程序(src/main.rs)来说,这个字段默认就是包的名称, 其中的破折号会被替换成下划线。对于其他 auto discovered 构建目标,默认是目录或文件的名称。

这个字段对所有构建目标是必填的,除了 [lib]

path 字段

path 字段指定 crate 的源代码相对于 Cargo.toml 的相对路径。

若此字段未指定,则默认会使用 inferred path 基于构建目标的名称自动填充。

test 字段

test 字段指明构建目标是否默认使用 cargo test 命令进行测试。 对库、可执行程序和测试来说,默认为 true

注意: 默认会使用 cargo test 构建实例来保证它们可以通过编译, 但是默认情况下,它们不 测试 运行时是否符合预期。 为实例设置 test = true 也会将其构建为测试并且运行实例中所有带有 #[test] 标记的方法。

doctest 字段

doctest 字段指明 文档测试 是否默认使用 cargo test 测试。 这个字段只与库有关,它对其他部分的配置没有任何作用。 对库来说,此字段默认为 true

bench 字段

bench 字段指明构建目标是否默认使用 cargo bench 进行性能测试。 对库、二进制程序和性能测试程序来说,此字段默认为 true

doc 字段

doc 字段指明构建目标是否包括在 cargo doc 默认生成的文档中。 对库和二进制程序来说,此字段默认为 true

注意: 若二进制程序的名称与库的名称相同,则会跳过二进制程序。

plugin 字段

此字段用于 rustc 的插件,现在已被弃用。

proc-macro 字段

proc-macro 字段指明库是过程宏 procedural macro 。 此字段仅适用于 [lib] 构建目标。

harness 字段

harness 字段指明 --test 标记 会传递给 rustc 令其自动包含libtest类库。 libtest 库用来收集并运行标有 #[test] 属性 的测试或标有 #[bench] 属性的性能测试。 对所有构建目标来说,此字段默认为 true

如果此字段设置为 false ,则需要你负责定义 main() 函数来运行测试和性能测试。

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

edition 字段

edition 字段定义了构建目标将会使用的 Rust 版次 。 若未指定,默认会使用 [package]edition 字段 。 此字段通常不需设置,它只用于类似大型包增量迁移到一个新版本这样的高级场景。

crate-type 字段

crate-type 字段定义了构建目标将生成的 crate 类型 。 它是字符串数组,用于在一个构建目标中指定多个 crate 类型 。 此字段仅用于库和实例。对于二进制程序,测试和性能测试,此字段总是为 "bin" crate 类型。 默认值为:

构建目标Crate Type
普通类库"lib"
Proc-macro 类库"proc-macro"
示例"bin"

此字段可用的值有 bin, lib, rlib, dylib, cdylib, staticlibproc-macro 。 关于各种 crate 类型的更多信息在 Rust Reference Manual

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] 部分将 autobins, autoexamples, autotestsautobenches 设置为 false

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

禁用自动探测应该仅用于一些特殊场景。 比如,如果你想在库中给一个 模块 命名为 bin , 这样是不行的,因为 Cargo 通常会将 bin 目录下的文件编译为可执行文件。 这个例子的文件结构如下:

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

Cargo.toml 中声明 autobins = false 禁用自动探测来防止 Cargo 将 src/bin/mod.rs 推断为可执行文件:

[package]
# …
autobins = false

注意: 对于 2015 版本的包,如果 Cargo.toml 中手动设置了构建目标, 则自动推断字段默认会设置为 false 。 自从 2018 版本,此字段默认设置为 true

工作空间

工作空间 是一个或多个包的集合,这些包称为 工作空间成员 ,它们被统一管理。

工作空间的关键目标是:

  • 常规命令可以对所有工作空间成员运行,比如 cargo check --workspace
  • 所有包共享 Cargo.lock 文件,该文件在 工作空间根 下。
  • 所有包共享 输出目录 ,默认为 工作空间根 下的 target
  • 共享包的metadata,比如 workspace.package
  • [patch] , [replace][profile.*] 仅识别 配置清单 Cargo.toml 中的,忽略其成员 crate 配置清单中的。

Cargo.toml 中, [workspace] 表支持以下部分:

  • [workspace]](#the-workspace-section) — 工作空间的定义。
    • resolver — 设置要使用的依赖解析器。
    • members — 包含在工作空间的包。
    • exclude — 从工作空间排除的包。
    • default-members — 当没有选择特定的包时,操作默认项。
    • package — 可被成员继承的键。
    • dependencies — 可被成员继承的依赖。
    • metadata — 外部插件的附加设置。
  • [patch] — 覆盖依赖。
  • [replace] — 覆盖依赖(已废弃)。
  • [profile] — 编译器设置和优化。

[workspace] 部分

要创建工作空间,你需要在 Cargo.toml 中添加 [workspace] 表:

[workspace]
# ...

工作空间至少要有一个成员,要么是一个根package,或者是虚拟配置清单。

Root package

如果在已定义 [package]Cargo.toml 中,添加 [workspace] 部分 ,该package就是工作空间的 Root package工作空间根 指的是工作空间 Cargo.toml 所在的目录。

[workspace]

[package]
name = "hello_world" # 包的名称
version = "0.1.0"    # 当前语义化版本
authors = ["Alice <a@example.com>", "Bob <b@example.com>"]

虚拟工作空间

或者,创建 Cargo.toml 的文件中,有 [workspace] 表,没有 [package] 表,则称为 虚拟配置清单 。 这通常在没有 "主" 包时很有用,可把拥有的各个包放在不同的目录里。

# [PROJECT_DIR]/Cargo.toml
[workspace]
members = ["hello_world"]
# [PROJECT_DIR]/hello_world/Cargo.toml
[package]
name = "hello_world" # package名称
version = "0.1.0"    # 当前的语义化版本
authors = ["Alice <a@example.com>", "Bob <b@example.com>"]

membersexclude 字段

membersexclude 字段定义哪些包是工作空间的成员:

[workspace]
members = ["member1", "path/to/member2", "crates/*"]
exclude = ["crates/foo", "path/to/other"]

工作空间目录中的所有 path 依赖 自动成为成员。 可以用 Cargo.tomlmembers 键,以字符串数组列出其他成员。

members 列表支持用 globs 通配符来匹配多个路径,使用典型的文件名通配符模式 *?

exclude 键可以防止路径自动包含到工作空间,排除某些路径依赖,可用通配符模式。

当在工作空间子目录内操作时,Cargo会自动搜索父目录中的 Cargo.toml 文件,以其中的 [workspace] 定义,来确定使用的工作空间。 在工作空间成员可以使用 package.workspace 配置键来配置工作空间根,以覆盖向上自动搜索。当成员不在工作空间根的子目录内时,就需要手动设置。

Package 部分

在工作空间中,与包有关的cargo命令,如 cargo build ,可以使用 -p / -package-workspace 命令行标志来选择成员进行操作。 如果这两个标志都没有指定,Cargo将使用当前工作目录的包。如果是无根包的 虚拟工作空间 , 命令将应用于所有成员 (同指定 --workspace 一样) 。 另请参阅 default-members

default-members 字段

default-members 键可选,在未使用工作空间根包和选择包的标志时,默认操作的成员:

[workspace]
members = ["path/to/member1", "path/to/member2", "path/to/member3/*"]
default-members = ["path/to/member2", "path/to/member3/foo"]

当指定 default-members 时,添加的必须是 members 的子集。

package

workspace.package 表可以定义工作空间成员继承的键。这些键可以通过在成员包配置清单中定义 {key}.workspace = true 的方式继承。

支持的键:

authorscategories
descriptiondocumentation
editionexclude
homepageinclude
keywordslicense
license-filepublish
readmerepository
rust-versionversion
  • license-filereadme 是相对于工作空间根。
  • includeexclude 是相对于包的根。

示例:

# [PROJECT_DIR]/Cargo.toml
[workspace]
members = ["bar"]

[workspace.package]
version = "1.2.3"
authors = ["Nice Folks"]
description = "A short description of my package"
documentation = "https://example.com/bar"
# [PROJECT_DIR]/bar/Cargo.toml
[package]
name = "bar"
version.workspace = true
authors.workspace = true
description.workspace = true
documentation.workspace = true

dependencies

workspace.dependencies 是可以定义工作空间成员所能继承的依赖。

指定工作空间依赖与 package依赖 类似,除了:

  • 此表中的依赖不能声明为 optional 可选的。
  • 在此表中声明的 features 特性将与来自 [dependencies]features 相加。

从而,就可以把工作区的依赖作为包的依赖来继承

示例:

# [PROJECT_DIR]/Cargo.toml
[workspace]
members = ["bar"]

[workspace.dependencies]
cc = "1.0.73"
rand = "0.8.5"
regex = { version = "1.6.0", default-features = false, features = ["std"] }
# [PROJECT_DIR]/bar/Cargo.toml
[package]
name = "bar"
version = "0.2.0"

[dependencies]
regex = { workspace = true, features = ["unicode"] }

[build-dependencies]
cc.workspace = true

[dev-dependencies]
rand.workspace = true

metadata

Cargo忽略对 workspace.metadata 表的检查,不会发出警告。一些工具插件可以在 Cargo.toml 的这一部分中存储配置。比如:

[workspace]
members = ["member1", "member2"]

[workspace.metadata.webcontents]
root = "path/to/webproject"
tool = ["npm", "run", "build"]
# ...

在包中也有类似的表 package.metadata 。虽然cargo没有为表的内容指定格式, 但建议外部工具以一致的方式使用,对工具来说有意义就好,在 package.metadata 中缺少数据时,会参考 workspace.metadata 中的数据。

特性

Cargo的通过 "特性" 这一机制来实现 条件编译可选依赖 。 在包 Cargo.toml[features] 表中定义一组命名特性,启用或禁用每个特性。 构建包时,可以在命令行中用 --features 标志启用特性。可以在 Cargo.toml 的依赖声明中启用其依赖的特性。

参阅 特性实例 章节,有关于如何使用特性的一些例子。

[features] 部分

特性在 Cargo.toml[features] 表中定义。 每个特性都指定了一个其他特性的数组,或者它所启用的可选依赖。 下面的例子说明了如何将特性应用于二维图像处理库,其中对不同图像格式的支持可以选择性地包含在内:

[features]
# 定义了一个名为 `webp` 的特性,未传递启用其他特性。
webp = []

有了这个特性的定义,可以用 cfg 表达式 ,在编译时有条件的包含代码,以支持所要求的特性。例如,在包的 lib.rs 里面可以这样:

#![allow(unused)]
fn main() {
// 有条件的包含模块源码,以支持实现WEBP特性。
#[cfg(feature = "webp")]
pub mod webp;
}

Cargo使用 rustc --cfg flag 在包中设置特性,源代码中可以用 cfg 属性cfg 检测特性是否存在。

特性可以列出需要关联启用的其他特性。例如,ICO格式关联包含BMP和PNG图像,当启用ico时,应该确保启用其他关联特性:

[features]
bmp = []
png = []
ico = ["bmp", "png"]
webp = []

特性名称可以包括 Unicode XID standard (大多数文字)中的字符,并允许以 _ 或数字 09 开头,在第一个字符之后还可以包含 -+.

注意: crates.io对特性名称的语法有额外的限制,只能是 ASCII字母数字 字符或 _- ,或 +

default 特性

默认情况下,除非明确启用,禁用所有特性。可以通过指定 default 特性来更改:

[features]
default = ["ico", "webp"]
bmp = []
png = []
ico = ["bmp", "png"]
webp = []

当构建包时,将启用 default 特性,从而又启用了所列出的其他特性。可以通过以下方式来改变这种默认行为:

注意: 选择默认特性要小心。默认特性更容易让用户使用包,而不需要强迫用户仔细选择启用哪些常用特性,但也有一些缺点。 除非指定 default-features = false ,否则依赖会自动启用默认特性。 但这可能会难以确保默认特性不被启用,特别是对于在依赖图中出现多次的依赖。 只有每个包都必须确保指定 default-features = false 才能避免启用它们。 另一个问题是,从默认集合中删除特性将可能是语义化不兼容的变化,所以你应该有信心时才保留这些特性。

可选依赖

依赖可以标记为 "optional" "可选的",这表示默认不会编译它们。 例如,假设2D图像处理库使用一个外部包来处理GIF图像。可以这样表达:

[dependencies]
gif = { version = "0.11.1", optional = true }

默认,这个可选依赖隐式地定义了一个看起来像这样的特性。

[features]
gif = ["dep:gif"]

这表示只有启用 gif 特性时才会包含这个依赖。 对应的,可以在代码中使用 cfg(feature = "gif") 语法。可以像特性一样启用该依赖, 例如 --features gif (参阅下面的 命令行特性选项)。

有时,你可能不想让特性与可选依赖同名。 比如,这个可选依赖是一个内部的细节,或者你想把多个可选依赖组合在一起,或者想使用更好的名字。 那么在 [features] 表中用 dep: 前缀来指定可选依赖,将禁用该隐式特性。

注意: dep: 语法仅从Rust 1.60开始可用。以前的版本只能使用隐式的特性名称。

例如,假设为了支持AVIF图像格式,库需要启用另外两个依赖项:

[dependencies]
ravif = { version = "0.6.3", optional = true }
rgb = { version = "0.8.25", optional = true }

[features]
avif = ["dep:ravif", "dep:rgb"]

在这个例子中, avif 特性将启用两个列出的依赖。 这也避免了创建隐式的 ravifrgb 特性,避免了单独启用这些特性,使其成为了crate的内部细节。

注意: 另一种可选的包含依赖的方法是使用 特定平台依赖 。 是以目标平台为条件,而不是特性。

依赖特性

包的依赖项的特性可以在其依赖声明中启用。 features 键列出要启用的特性。

[dependencies]
# 启用serde的 `derive` 特性。
serde = { version = "1.0.118", features = ["derive"] }

可以用 default-features = false 来禁用 default 特性

[dependencies]
flate2 = { version = "1.0.3", default-features = false, features = ["zlib"] }

注意: 这将无法确保禁用默认特性。 如果另一个依赖包含 flate2 而没有指定 default-features = false ,那么将启用默认特性。 更多细节请参阅下面的 特性联合

依赖项的特性也可以在 [features] 表中启用。 语法为 "package-name/feature-name" ,例如:

[dependencies]
jpeg-decoder = { version = "0.1.20", default-features = false }

[features]
# 通过启用 jpeg-decoder 的 "rayon" 特性来支持 parallel 。
parallel = ["jpeg-decoder/rayon"]

"package-name/feature-name" 语法将启用 package-name 这个可选的 "依赖" 包。并不想这样做, 那么可以在 "package-name?/feature-name" 中添加一个 ? ,使其只有在其他项启用了可选依赖时,才会启用其特性。

注意: ? 语法仅从Rust 1.60开始可用。

比如,假设在库中添加序列化支持,它需要在一些可选的依赖中启用相应的特性。 可以像这样做:

[dependencies]
serde = { version = "1.0.133", optional = true }
rgb = { version = "0.8.25", optional = true }

[features]
serde = ["dep:serde", "rgb?/serde"]

在这个例子中,启用 serde 特性将启用serde依赖。 它也将启用 rgb 依赖的 serde 特性,但只有在其他项已经启用了 rgb 依赖的情况下。

命令行特性选项

以下命令行标志可以用来控制启用哪些特性:

  • --features FEATURES: 启用列出的特性。多个特性可以用逗号或空格分开。 若使用空格,如果从shell中运行Cargo,请确保在所有特性周围使用引号(例如 ---features "foo bar" )。 如果在 工作空间 中构建多个包,可以使用 package-name/feature-name 语法来指定特定工作空间成员的特性。

  • --all-features: 激活在命令行上选择的所有包的所有特性。

  • --no-default-features: 不激活所选包的 default 特性

特性联合

特性对于定义它们的包来说是唯一的。在包上启用一个特性,不会在其他包上启用相同名称的特性。

当依赖被多个包使用时,Cargo会在构建时使用该依赖上联合启用特性。 这有助于只使用该依赖的一个副本。 更多细节请参阅解析器文档中的 特性部分

比如,查看 winapi 包,发现它使用了 大量 的特性。 如果你的包依赖于 foo ,它启用了 winapi 的 "fileapi" 和 "handleapi" 特性, 而另一个依赖包 bar 启用了 winapi 的 "std" 和 "winnt" 特性,那么 winapi 包将在联合启用四种特性后构建。

winapi features example

因而,特性表现出 增加性 ,启用特性不应该有禁用功能的效果, 而且启用任意特性的组合通常都是安全的。一个特性不应该引入 语义化不兼容的改变

例如,如果你想选择性地支持 no_std ,那么 不要 使用 no_std 特性,而是应该使用 "std" 特性,以选择性 启用 std 。比如说:

#![allow(unused)]
#![no_std]

fn main() {
#[cfg(feature = "std")]
extern crate std;

#[cfg(feature = "std")]
pub fn function_that_requires_std() {
    // ...
}
}

互斥特性

在极少数情况下,特性之间可能相互不兼容。那么协调依赖图中所有使用的包,以避免同时启用, 如果作不到,可以考虑增加一个编译错误来检测。比如说:

#[cfg(all(feature = "foo", feature = "bar"))]
compile_error!("feature \"foo\" and feature \"bar\" cannot be enabled at the same time");

与其使用相互排斥的特性,不如考虑一些其他选择:

  • 将功能分成独立的包。
  • 当有冲突时,选择其中之一。用 cfg-if 包帮助编写更复杂的 cfg 表达式。
  • 源代码允许同时启用这些特性,而使用运行时选项来控制使用哪个特性。比如,使用一个配置文件、命令行参数或环境变量来选择启用哪种行为。

检查特性解析

在复杂的依赖图中,有时很难理解如何在不同的包上启用不同的特性。 cargo tree 命令提供了几个选项来帮助检查和可视化所启用特性。可以尝试:

  • cargo tree -e features: 这将显示依赖图中的特性。每个特性都会出现,显示哪个包启用了它。
  • cargo tree -f "{p} {f}": 这是更紧凑的视图,显示每个包上启用的特性的逗号分隔的列表。
  • cargo tree -e features -i foo: 这将反转树形图,显示特性如何流入给定的包 "foo"。这可能很有用,因为查看整个图表可能相当大,而且令人不知所措。当你试图弄清楚哪些特性在特定的包上被启用以及为什么要这样做时,可以使用这个方法。请看 cargo tree 页面底部的例子,了解阅读。

特性解析版本2

可以用 Cargo.toml 中的 resolver 字段指定不同的特性解析器,像这样:

[package]
name = "my-package"
version = "1.0.0"
resolver = "2"

关于指定解析器版本的更多细节,请参见 解析器版本 部分。

版本 "2" 的解析器在一些不需要联合的情况下避免了联合的特性。 具体的情况在 解析器章节 中有描述,简而言之,它避免在这些情况下进行联合。

在某些情况下,有必要避免联合。 例如,如果build-dependency启用了 std 特性,而同一个依赖被用作 no_std 环境的常规依赖,启用 std 会破坏构建。

然而,一个缺点是,这可能会增加构建时间,因为依赖会被构建多次(每次都有不同的特性)。 当使用版本 "2" 解析器时,建议检查那些被多次构建的依赖,以减少整体构建时间。 如果不是 必须 要用单独的特性来构建这些重复的包,可以考虑在 依赖声明 中的 features 列表中添加特性, 这样重复的包最后就会有相同的特性(因此Cargo只会构建一次)。 你可以用 cargo tree --duplicates 命令检测这些重复的依赖。它将显示哪些包被多次构建,寻找列出相同版本的条目。 参阅 Inspecting resolved features 获取更多关于解析特性的信息。 对于构建依赖,如果你使用 --target 标志进行交叉编译,则没有必要这样做,因为在这种情况下,构建依赖总是与普通依赖分开构建。

解析器版本2命令行标记

resolver = "2" 的设置也改变了 --features--no-default-features 命令行选项 的行为。

在版本 "1" 中,你只能为当前工作目录中的包启用特性。 例如,在一个有 foobar 包的工作空间中,如果你在 foo 包的目录下,运行 cargo build -p bar --features bar-feat 命令,就会失败, 因为 --features 标志只允许启用 foo 的特性。

resolver = "2" 的情况下,特性标志允许启用任何在命令行中用 -p--workspace 标志选择的包的特性。比如说:

# 这个命令在 resolver = "2" 的情况下是允许的,无论你在哪个目录下。
cargo build -p foo -p bar --features foo-feat,bar-feat

# 这个明确的等价形式适用于任何解析器版本:
cargo build -p foo -p bar --features foo/foo-feat,bar/bar-feat

此外,在 resolver = "1" 的情况下,--no-default-features 标志只停用当前目录下包的默认特性。 如果版本为 "2" ,它将禁用所有工作空间成员的默认特性。

构建脚本

构建脚本 可以通过检查 CARGO_FEATURE_<name> 环境变量来检测包上启用了哪些特性,其中 <name> 是转换为大写的特性名称, - 转换为 _

必须特性

如果没有启用某个特性,可以用 required-features 字段 禁用特定的 Cargo 目标 。 更多细节请参阅链接的文档。

语义化版本兼容

启用特性不应该引入语义化不兼容的变化。 例如,该特性不应该以可能破坏现有用途的方式改变现有的API。 关于哪些变化是兼容的,可以在 语义化版本兼容性章节 中了解更多细节。

在添加和删除特性定义和可选的依赖时应该小心,因为这些有时可能是向后不兼容的变化。 更多细节可以在语义化版本兼容性章节的 Cargo 部分 中找到。简而言之,遵循这些规则:

注意事项和实例见链接。

特征文档和发现

我们鼓励你记录你的包中有哪些特性。 这可以通过在 lib.rs 的顶部添加 doc comments 来实现。 请查看 regex crate source 例子,它被渲染后可以在 docs.rs 上查看。 如果你有其他的文档,比如用户指南,考虑将文档添加到那里 (比如,参阅 serde.rs) 。 如果你有一个二进制项目,考虑在README或项目的其他文档中记录这些特性 (比如,参阅sccache) 。

明确记录特性的设计期望,记录那些认为是 "不稳定" 或不应该使用的特性。 例如,如果有一个可选的依赖,但你不希望用户明确地把这个可选依赖列为特性,那么就把它从记录的列表中排除。

docs.rs 上发布的文档可以使用 Cargo.toml 中的元数据来控制文档构建时启用哪些特性。 更多细节请参见 docs.rs metadata documentation

注意: Rustdoc 实验性地支持对文档进行注释,以表明使用某些API需要哪些特性。 更多细节见 doc_cfg 文档。一个例子是 syn documentation ,你可以看到彩色的方框,其中指出需要使用哪些特性。

发现特性

当特性被记录在库的API中时,这可以使用户更容易发现哪些特性是可用的以及它们的作用。 如果一个包的特性文档不容易获得,你可以看看 Cargo.toml 文件,但有时会很难追踪到它。 如果存在, crates.io 上的 crate 页面有一个指向源码库的链接。 像 cargo vendorcargo-clone-crate 这样的工具可以用来下载源码并检查它。

特性组合

因为特性是一种条件编译的形式,它们需要指数级的配置和测试案例才能100%覆盖。 默认情况下,测试、文档和其他工具,如 Clippy 将只在默认的特性集下运行。

我们鼓励充分考虑策略及工具对于不同特性的组合: 每个项目将有不同的需求,结合时间、资源和覆盖特定场景的成本效益。 常见的配置考虑可能是有/无默认特性,特定的特性组合,或所有的特性组合。

特性示例

下面说明一些实际中的特性示例。

最大限度地减少构建时间和文件大小

一些包使用了特性,如果不启用这些特性,就会减小crate的大小并减少编译时间。一些例子是:

  • syn 是用于解析Rust代码的crate,对于减少编译时间很有帮助,是个流行的项目。 它有一个 清晰记录列表 的特性,可以用来减少所包含的代码量。
  • regex几个特性 ,这些特性都有 很好的文档 。 移除Unicode支持,将删除一些很大表,可以减少产生文件的大小。
  • winapi大量 的特性,以限制它支持哪些Windows API绑定。
  • web-sys 是另一个类似于 winapi 的例子,它提供了 大量 的API绑定,可以使用特性限制这些绑定。

扩展行为

serde_json 包有 preserve_order 特性 ,它 改变JSON映射行为 ,以保持键的插入顺序。 请注意,它启用了一个可选的依赖 indexmap 来实现新的行为。

当改变这样的行为时,要注意确保这些改变是 语义化兼容 的。 也就是说,启用该特性不应该破坏通常在该特性关闭时构建的代码。

no_std 支持

一些包希望同时支持 no_stdstd 环境。 这对于支持嵌入式和资源受限的平台是很有用的,在对于支持完整标准库的平台,仍然需要扩展功能。

wasm-bindgen 包定义了 std 特性默认启用 。 在库的顶部,它 非可选的启用 no_std 属性 。 这确保了 stdstd prelude 不会自动进入作用域。 然后,在代码的不同地方( example1 , example2 ),它使用 #[cfg(feature = "std")] 属性,有条件地启用需要 std 的附加功能。

重新导出依赖特性

从依赖中重新导出特性可能是很方便的。 这允许依赖于 crate 的用户控制这些特性,而不需要直接指定这些依赖。 例如, regex 重新导出特性 来自 regex_syntax 包。 regex 的用户不需要知道 regex_syntax 包,但他们仍然可以访问它所包含的功能。

C库支持

一些包提供了与普通C库的绑定(有时被称为 "sys" crates) 。 有时,这些包让你选择使用系统上安装的C库,或者从源代码中构建它。 例如, openssl 包有一个 vendored 特性 ,它可以启用 openssl-sys 的相应 vendored 特性。 openssl-sys 构建脚本有一些 条件逻辑 ,使其从OpenSSL源代码的本地副本构建,而不是使用系统版本。

curl-sys 包是另一个例子, static-curl 特性 导致其从源码构建libcurl。 注意它也有 force-system-lib-on-osx 特性,强制 使用系统libcurl ,推翻了static-curl的设置。

特性优先级

一些包可能有相互排斥的特性。处理这个问题的选项是,一个特性优先于另一个。 log 包是一个例子。它有 几个特性 ,用于在编译时选择最大的日志级别,描述在 这里 。 它使用 cfg-if选择优先级 。如果启用了多个特性,较高的 "max" 级别将优先于较低的级别。

过程宏协同包

有些包有一个与之紧密相连的过程宏。然而,并不是所有的用户都需要使用这个过程宏。 通过使过程宏成为可选的依赖,这允许你方便地选择是否包含它。 这很有帮助,因为有时过程宏的版本必须与父包保持同步,而你不想强迫用户必须指定两个依赖并保持它们同步。

一个例子是 serde ,它有一个 derive 特性,可以启用 serde_derive 过程宏。 serde_derive crate与 serde 紧密关联,所以它使用 相同版本要求 来确保它们保持同步。

每日构建特性

一些包想要试验只有在 Rust nightly channel 上才有的API或语言特性。 然而,他们可能不希望要求用户也使用nightly频道。 一个例子是 wasm-bindgen ,它有一个 nightly 特性 , 它启用了 扩展的API ,使用 Unsize 标记特性,在写这篇文章时,只有在nightly频道中才有。

请注意,在crate的root,它使用了 cfg_attr 来启用每日特性 。 要知道, feature 属性 与Cargo特性无关,它是用来选择加入实验性语言特性的。

rand 包的 simd_support 特性 是另一个例子,它依赖于一个只在每日频道构建的依赖。

实验特性

一些包有新的特性,他们可能想进行实验,而不必承诺这些API的稳定性。 这些特性通常被记录在案,它们是实验性的,因此在未来可能会发生变化或损坏,甚至是在一个次要的版本中。 一个例子是 [async-std] 包,它有一个 [unstable] 特性 async-std-unstablegates new APIs ,人们可以选择使用,但可能还没有完全准备好被依赖。

编译设置

Profile "编译设置" 提供了一种修改编译器设置的方法,从而影响代码优化和调试符号等。

Cargo 内置的编译设置有4种: devreleasetestbench 。 如果命令行中并未指定具体的编译设置,Cargo会根据当前运行的命令来自动选择。 除了内置,用户也可以自定义。

编译设置可以在 Cargo.toml 文件 [profile] 表中进行修改。 具体某个名称的编译设置中,单独的设置条目可以用键值对来修改:

[profile.dev]
opt-level = 1               # 使用较好的优化级别。
overflow-checks = false     # 关闭整数溢出检查。

Cargo只会扫描工作空间根目录下 Cargo.toml 配置清单中的编译设置。 在依赖中定义的编译设置会被忽略。

此外,可以通过 config 的定义来覆盖编译设置。 在config文件或环境变量中指定编译设置将会覆盖 Cargo.toml 中的。

编译设置条目

下面是可以在编译设置中进行控制的设置条目列表。

opt-level

opt-level 设置控制 -C opt-level flag 优化级别。高优化级别通过更长的编译时间换来生成后更快的运行时代码。 更高的优化级别同时也可能改变或者重新布局编译过的代码,从而更难调试。

有效选项:

  • 0 : 无优化
  • 1 : 基础优化
  • 2 : 适量优化
  • 3 : 优化全开
  • "s" : 优化二进制大小
  • "z" : 优化二进制大小,同时关闭循环向量化

建议你的项目尝试用不同的优化级别,从而找到合理的平衡。也许你有时会惊讶级别 3 会比级别 2 慢,或者 "s""z" 级别未能压缩二进制的大小。 在开发的过程中,由于 rustc 版本更新可能改变了优化行为,也许你也需要重新评估设置。

另请参阅Profile Guided Optimization了解更多的高级优化技巧。

debug

debug 设置控制 [ -C debuginfo flag] 编译后的二进制调试的信息量。

有效选项:

  • 0false: 无调试信息
  • 1 : 只包含行号表
  • 2true : 包含完整的调试信息

也许根据需要,同时配置 split-debuginfo 选项。

split-debuginfo

split-debuginfo 设置控制 -C split-debuginfo flag 调试信息,如果产生的话,是放在可执行文件本身,还是放在其旁边。

这个选项是字符串,可接受的值与编译器接受的相同。 在macOS上,这个选项的默认值是 unpacked ,用于已启用调试信息的编译设置。 否则,这个选项的默认值是 rustc文档,并且是特定平台的。 有些选项只在 每日构建通道 中可用。 一旦进行了更多的测试,并且对DWARF的支持稳定下来,Cargo的默认值可能会在未来发生变化。

strip

strip 选项控制 [ -C strip flag] 从而告知 rustc 从二进制文件中去除符号或调试信息。可以像这样启用:

[package]
# ...

[profile.release]
strip = "debuginfo"

可能的 strip 字符串值包括 "none""debuginfo""symbols" 。默认值是 "none"

你还可以使用布尔值 true false 配置此选项。 strip = true 等同于 strip = "symbols"strip = false 等同于 strip = "none" 并完全禁用 strip

debug-assertions

debug-assertions 设置控制 [ -C debug-assertions flag] ,从而可以打开或关闭 cfg(debug_assertions) conditional compilation "条件编译"。 调试断言旨在包含仅在调试或开发版本可用的运行时验证。这些对于发布版本来说可能消耗过高或者并不需要。调试断言会开启标准库中的 debug_assert! macro

有效选项:

  • true : 开启
  • false : 禁用

overflow-checks

overflow-checks 设置控制[ -C overflow-checks flag] ,控制 runtime integer overflow 的行为。当启用溢出检查时,溢出将导致系统发生严重错误,从而panic恐慌。

有效选项:

  • true : 开启
  • false : 禁用

lto

lto 设置控制 -C lto flag,控制LLVM link time optimizations "链接时优化"。 LTO可以使用全过程分析,以更长的链接时间换取生成更好的优化后的代码。

有效选项:

  • false : 执行 "thin local LTO",仅在本地的所有crate上执行 "thin" LTOcodegen units。如果codegen单位为1或opt-level是0,则不会进行LTO优化。
  • true"fat" :执行 "fat" LTO,尝试对依赖图中的所有crate执行优化。
  • "thin" :执行 "thin" LTO。这与 "fat" 类似,但运行时间缩短,同时仍能获得类似于 "fat" 的性能提升。
  • "off" : 禁用 LTO。

另请参阅[ -C linker-plugin-lto] rustc 跨语言LTO标志。

panic

panic 设置控制 [ -C panic flag] ,控制使用哪种恐慌策略。

有效选项:

  • "unwind" :panic时进行栈解旋。
  • "abort" :panic时终止进程。

当设置为 "unwind" 时,实际值取决于目标平台的默认值。例如,NVPTX平台不支持栈解旋,所以它总是使用 "abort"

测试、性能测试、构建脚本、过程宏会忽略 panic 设置。 rust 测试工具目前需要 unwind 行为。 见 panic-abort-tests 未稳定的标志启用 abort 行为。

此外,当使用 abort 策略和构建测试时,所有依赖也将强制使用 unwind 策略来构建。

incremental

incremental 设置控制[ -C incremental flag],控制是否启用增量编译。 增量编译会使 rustc 将额外的信息保存到磁盘,这些额外信息在重新编译crate时可重复使用,从而缩短重新编译时间。附加信息存储在 target 目录中。

有效选项:

  • true : 开启
  • false : 禁用

增量编译仅用于工作空间成员和 "path" 依赖。

增量值可以用 CARGO_INCREMENTAL environment variable 或者 [ build.incremental ] config 变量来进行全局覆盖。

codegen-units

codegen-units 设置控制[ -C codegen-units flag],控制着crate分割到多少个"代码生成单元"。 更多的代码生成单元允许并行处理更多的crate,这可能会减少编译时间,但可能会生成较慢的代码。

此选项接受大于0的整数。

默认值为256 incremental构建 ,16用于非增量构建。

rpath

rpath 设置控制[ -C rpath flag],控制是否启用 [ rpath ] 。

默认编译设置

dev

dev 编译设置用于日常的开发和调试。它是构建指令如[ cargo build ]的默认参数,并且用于 cargo install --debug

dev 编译设置的默认设置有:

[profile.dev]
opt-level = 0
debug = true
split-debuginfo = '...'  # 平台指定。
debug-assertions = true
overflow-checks = true
lto = false
panic = 'unwind'
incremental = true
codegen-units = 256
rpath = false

release

release 编译设置旨在发布和产生优化后的制品,当使用 --release 标志时启用,是[ cargo install ]的默认设置。

release 编译设置的默认条目有:

[profile.release]
opt-level = 3
debug = false
split-debuginfo = '...'  # 平台指定。
debug-assertions = false
overflow-checks = false
lto = false
panic = 'unwind'
incremental = false
codegen-units = 16
rpath = false

test

test 编译设置是 cargo test 的默认配置。 test 编译设置继承了 dev 编译设置项。

bench

bench 编译配置是 [ cargo bench ] 的默认编译配置。 bench 编译配置继承了 release 编译配置中的设置。

构建依赖

默认情况下,所有的编译设置都不会优化构建依赖(构建脚本、过程宏、它们的依赖)。构建覆盖的默认设置为:

[profile.dev.build-override]
opt-level = 0
codegen-units = 256

[profile.release.build-override]
opt-level = 0
codegen-units = 256

构建依赖项以其他方式继承正在使用的编译设置条目,如Profile selection所描述。

自定义编译设置

除了内置编译设置,还可以自定义。在需要划分多个工作流和构建模式时,可能会用到自定义编译设置。 在自定义编译设置时,必须指定 inherits 键,以便在条目没有指定时,可以找到自定义继承了的哪个编译设置。

举例来说,假如你想将一个普通的发布构建与使用LTO优化的构建做比较,那么可以如下在 Cargo.toml 指定:

[profile.release-lto]
inherits = "release"
lto = true

--profile 标志可用来选择自定义编译设置:

cargo build --profile release-lto

每个编译设置的输出会放在target directory下和编译设置同名的文件夹下。对于上面的例子来说,编译设置产生的输出会放置在路径为 target/release-lto 文件夹下。

编译设置选择

编译设置的使用依赖于指令、命令行标志如 --release--profile 和包(比如overrides)。如果未指定那么默认的编译设置为:

可以使用 --profile=NAME 来切换到不同的编译设置。 --release 标志等价于 --profile=release

选择的编译设置作用于Cargo所有的生成目标,包括 library, binary, example, test, benchmark

对于特定包的编译设置可以使用overrides来指定,描述如下。

覆盖

编译设置可对特定包和构建时的crate进行覆盖。如需对特定的包进行覆盖,使用 package 表来更改已命名的包的编译设置:

# `foo` 包会使用 -Copt-level=3 标志。
[profile.dev.package.foo]
opt-level = 3

包的名字实际为Package ID Spec,所以可以使用如 [profile.dev.package."foo:2.1.0"] 的语法定位到某个版本的包。

如需覆盖所有依赖的设置(但是并非任意工作空间的成员),使用 "*" 包名 :

# 为所有配置设定默认设置。
[profile.dev.package."*"]
opt-level = 2

如需覆盖构建脚本、过程宏和相关依赖的设置,使用 build-override 表:

# 为构建脚本和过程宏设置配置。
[profile.dev.build-override]
opt-level = 3

注意:当依赖既是普通依赖而且是构建依赖时, 如果 --target 未指定,Cargo 会试图只构建一次。 当使用 build-override 时,依赖可能需要构建两次, 一次作为正常依赖项,一次使用覆盖的构建设置。这可能会增加初始构建的时间。

使用值的优先顺序如下(先匹配到的优先):

  1. [profile.dev.package.name] — 命名的包。
  2. [profile.dev.package."*"] — 对于任何非工作空间成员。
  3. [profile.dev.build-override] — 仅适用于构建脚本、过程宏及其依赖项。
  4. [profile.dev]Cargo.toml 中的设置。
  5. Cargo中内置的默认值。

覆盖不能指定 panicltorpath 设置。

覆盖和泛型

实例化泛型代码的位置会影响用于该泛型代码的优化配置。 当使用编译配置覆盖去更改特定crate的优化级别时,这可能会导致微妙的影响。 如果试图提高定义泛型函数依赖的优化级别,在本地crate中使用这些泛型函数时可能无法进行优化。 这是因为代码可能会在其实例化的crate中生成,因而可能会使用该crate的优化设置。

举例来说, nalgebra 是一个定义向量和矩阵的库,并且大量使用了泛型参数。 如果你的本地代码定义了具体的nalgebra类型,比如 Vector4<f64> 并使用他们的方法,相应的nalgebra代码将被实例化并构建在你的crate中。 因此,如果你试图使用覆盖编译配置来提高nalgebra的优化级别的话,可能并不会带来更快的性能。

更复杂的是, rustc 有一些优化尝试在crate之间共享单态化的泛型。如果优化级别是2或3, 那么crate将不会使用其他crate中单态化的泛型,也不会导出本地定义的与其他crate共享的单态化内容。

配置

此文档解释Cargo的配置系统,以及可用的键或配置项。关于包的配置清单,参阅manifest format

层次结构

Cargo允许对特定的包进行本地配置和全局配置,会在当前目录和所有父目录下寻找配置文件。 比如,如果在 /projects/foo/bar/baz 中调用Cargo,那么以下的配置文件会被探测到,并按照这个顺序统一管理:

  • /projects/foo/bar/baz/.cargo/config.toml
  • /projects/foo/bar/.cargo/config.toml
  • /projects/foo/.cargo/config.toml
  • /projects/.cargo/config.toml
  • /.cargo/config.toml
  • $CARGO_HOME/config.toml 默认为:
    • Windows: %USERPROFILE%\.cargo\config.toml
    • Unix: $HOME/.cargo/config.toml

按照这种结构,可以指定每个包的配置,可以将其检出到版本控制中。可以在主目录下用一个配置文件指定个人的默认值。

如果一个键在多个配置文件中被指定,将合并这些值。数字、字符串和布尔值将使用更深层级配置目录中的值,其优先于祖先目录中的,主目录的优先级最低。数组将连接在一起。

目前,当从工作空间调用时,Cargo不会从工作空间的crate中读取配置文件,比如,工作空间有两个crate,分别为 /projects/foo/bar/baz/mylib/projects/foo/bar/baz/mybin , 并且存在 /projects/foo/bar/baz/mylib/.cargo/config.toml/projects/foo/bar/baz/mybin/.cargo/config.toml ,如果从工作空间根(/projects/foo/bar/baz/)调用,Cargo就不会读取这些配置文件。

注意: Cargo 也可以读取没有 .toml 扩展名的配置文件,如.cargo/config。 对 .toml 扩展的支持是在1.39版本中加入的,是首选的形式。如果两个文件都存在,Cargo 将使用没有扩展名的文件。

配置格式

配置文件是以 TOML格式 编写,在表内有简洁的键值对。以下是对所有设置的概述,详细说明见下文。

paths = ["/path/to/override"] # 路径依赖覆盖

[alias] # 命令别名 b = "build" c = "check" t = "test" r = "run" rr = "run --release" recursive_example = "rr --example recursions" space_example = ["run", "--release", "--", ""command list""]

[build] jobs = 1 # 并行任务数, 默认为 CPU 数 rustc = "rustc" # rust 编译器工具 rustc-wrapper = "…" # 运行这个包装器,而不是 rustc rustc-workspace-wrapper = "…" # 运行这个包装器,而不是 rustc ,对于工作空间成员 rustdoc = "rustdoc" # 文档生成工具 target = "triple" # 构建目标三元组 (被 cargo install 忽略) target-dir = "target" # 放置所有生成制品的路径 rustflags = ["…", "…"] # 要传递给所有编译器调用的自定义标志 rustdocflags = ["…", "…"] # 传递给rustdoc的自定义标志 incremental = true # 是否启用增量编译 dep-info-basedir = "…" # 开发文件中目标的基础目录路径

[doc] browser = "chromium" # 与 cargo doc --open 一起使用的浏览器,覆盖 BROWSER 环境变量。

env

为Cargo运行的任何进程设置ENV_VAR_NAME=value

ENV_VAR_NAME = "value"

即使环境中已经存在,也将设置

ENV_VAR_NAME_2 = { value = "value", force = true }

该值是相对于包含 config.toml 的.cargo目录而言的,设置为绝对的。

ENV_VAR_NAME_3 = { value = "relative/path", relative = true }

[future-incompat-report] frequency = 'always' # 何时显示关于未来不兼容报告的通知

[cargo-new] vcs = "none" # VCS 便用 ('git', 'hg', 'pijul', 'fossil', 'none')

[http] debug = false # HTTP 调试 proxy = "host:port" # libcurl格式的HTTP代理 ssl-version = "tlsv1.3" # 要使用的TLS版本 ssl-version.max = "tlsv1.3" # TLS 最大版本 ssl-version.min = "tlsv1.1" # TLS 最小版本 timeout = 30 # 每个HTTP请求的超时,单位为秒 low-speed-limit = 10 # 网络超时阈值(字节/秒)。 cainfo = "cert.pem" # CA证书绑定的路径 check-revoke = true # 检查SSL证书是否被撤销 multiplexing = true # HTTP/2 多路复用 user-agent = "…" # user-agent 头

[install] root = "/some/path" # cargo install 目标目录

[net] retry = 2 # 网络重试 git-fetch-with-cli = true # 使用 git 可执行文件进行git操作 offline = true # 不接入网络

[patch.]

与Cargo.toml中 [patch] 的键相同。

[profile.] # 通过配置来修改编译设置。 opt-level = 0 # 优化级别。 debug = true # 包括调试信息。 split-debuginfo = '...' # 调试信息拆分行为。 debug-assertions = true # 启用调试断言。 overflow-checks = true # 启用运行时的整数溢出检查。 lto = false # 设置链接时优化。 panic = 'unwind' # 恐慌策略。 incremental = true # 增量编译。 codegen-units = 16 # 代码生成单元的数目。 rpath = false # 设置rpath链接选项。 [profile..build-override] # 覆盖build-script的设置。

profile下的键是一样的。

[profile..package.] # 覆盖包的配置文件。

profile下的键是一样的 (没有 panic, lto, 和 rpath)。

[registries.] # crates.io外的其他注册中心 index = "…" # 注册中心的URL索引 token = "…" # 注册中心的认证令牌

[registry] default = "…" # 默认注册中心的名称 token = "…" # crates.io的认证令牌

[source.] # 源的定义和替换 replace-with = "…" # 用给定命名的源替换这个源 directory = "…" # 目录源的路径 registry = "…" # 注册中心源的 URL local-registry = "…" # 本地注册源的路径 git = "…" # git 源的 URL branch = "…" # git 仓库的分支名称 tag = "…" # git 仓库的 tag 名称 rev = "…" # git 仓库的修订

[target.] linker = "…" # 要使用的链接器 runner = "…" # 运行可执行文件的包装器 rustflags = ["…", "…"] # rustc 的自定义标记

[target.] runner = "…" # 运行可执行文件的包装器 rustflags = ["…", "…"] # rustc 的自定义标记

[target..] # links 构建脚本覆盖 rustc-link-lib = ["foo"] rustc-link-search = ["/path/to/foo"] rustc-flags = ["-L", "/some/path"] rustc-cfg = ['key="value"'] rustc-env = {key = "value"} rustc-cdylib-link-arg = ["…"] metadata_key1 = "value" metadata_key2 = "value"

[term] quiet = false # cargo是否输出静默 verbose = false # cargo是否提供详细输出 color = 'auto' # cargo是否着色输出 progress.when = 'auto' # cargo是否显示进度条 progress.width = 80 # 进度条的宽度


### 环境变量

除了TOML配置文件,Cargo还可以通过环境变量进行配置。对于每个形如 `foo.bar` 的配置键,也可以用环境变量 `CARGO_FOO_BAR` 定义值。
键将转换为大写字母,点和破折号将转换为下划线。例如,`target.x86_64-unknown-linux-gnu.runner` 键也可以由 `CARGO_TARGET_X86_64_UNKNOWN_LINUX_GNU_RUNNER` 环境变量定义。

环境变量将优先于TOML配置文件。目前只有整数、布尔值、字符串和一些数组值支持由环境变量定义。
[下面描述](#configuration-keys)表明哪些键支持环境变量,否则由于[技术问题](https://github.com/rust-lang/cargo/issues/5416)而不受支持。

除了上述系统外,Cargo还能识别一些其他特定的[环境变量][env]。

### 命令行覆盖

Cargo也可以通过 `--config` 命令行选项接受任意的配置覆盖。参数应是TOML语法中的 "KEY=VALUE" 。

```console
cargo --config net.git-fetch-with-cli=true fetch

--config 选项可以多次指定,在这种情况下,这些值将按照从左到右的顺序合并,合并逻辑与多个配置文件时相同。 以这种方式指定的配置值优先于环境变量,环境变量优先于配置文件。

一些看起像什么Bourne shell语法使用的例子:

# 多数 shells 请求将转义。
cargo --config http.proxy=\"http://example.com\" …

# 可以使用空格。
cargo --config "net.git-fetch-with-cli = true" …

# TOML数组例子。单引号使其更容易读写。
cargo --config 'build.rustdocflags = ["--html-in-header", "header.html"]' …

# 一个复杂的TOML键的例子。
cargo --config "target.'cfg(all(target_arch = \"arm\", target_os = \"none\"))'.runner = 'my-runner'" …

# 覆盖一个配置文件设置的例子。
cargo --config profile.dev.package.image.opt-level=3 …

--config 选项也可以用来传递额外的配置文件的路径,Cargo应该在特定的调用中使用这些文件。 通过这种方式加载的配置文件中的选项与直接用 --config 指定的其他选项遵循同样的优先级规则。

Config相对路径

配置文件中的路径可以是绝对的、相对的,或者是没有任何路径分隔符的无修饰名称。 没有路径分隔符的可执行文件的路径将使用 PATH 环境变量来搜索可执行文件。 非可执行文件的路径将相对于配置值定义位置。

具体来说,规则是:

  • 对于环境变量,路径是相对于当前工作目录的。
  • 对于直接从 --config KEY=VALUE 选项加载的配置值,路径是相对于当前工作目录的。
  • 对于配置文件,路径是相对于定义配置文件的目录的父目录而言的,无论这些文件是来自 层级检索 还是 --config <path> 选项。

注意: 为了与现有的 .cargo/config.toml 检索行为保持一致,在设计上,通过 --config <path> 传递的配置文件中的路径是相对于配置文件本身两级。 为了避免意外的结果,经验方法是把你的额外配置文件放在项目中发现的 .cargo/config.toml 的同一级别。 例如,给定项目 /my/project ,建议把配置文件放在 /my/project/.cargo 下,或者在同一级别上新建一个目录,如 /my/project/.config

# 相对路径例子。

[target.x86_64-unknown-linux-gnu]
runner = "foo"  # 在 `PATH` 中搜索 `foo` .

[source.vendored-sources]
# 目录是相对于 `.cargo/config.toml` 所在的父目录而言的。
# 比如, `/my/project/.cargo/config.toml` 会在 `/my/project/vendor` 。
directory = "vendor"

带参数的可执行路径

一些Cargo命令调用外部程序,可以为其配置路径和一些参数。

该值可以是一个字符串数组,如 ['/path/to/program', 'somearg'] 或一个空格分隔的字符串,如 '/path/to/program somearg' 。 如果可执行文件的路径包含空格,则必须使用列表形式。

如果Cargo向程序传递其他参数,比如打开或运行的路径,它们将在这种格式的选项值中最后指定的参数之后传递。 如果指定的程序没有路径分隔符,Cargo会在 PATH 中搜索其可执行文件。

证书

带有敏感信息的配置值存储在 $CARGO_HOME/credentials.toml 文件中。 这个文件由 cargo login 自动创建和更新。它遵循与Cargo配置文件相同的格式。

[registry]
token = "…"   # crates.io 访问 token

[registries.<name>]
token = "…"   # 具名注册中心访问 token

一些Cargo命令使用令牌,例如 cargo publish ,用于与远程注册中心进行认证。 应该注意保护令牌,使其私密。

与其他大多数配置值一样,令牌可以用环境变量来指定。 crates.io的令牌可以用 CARGO_REGISTRY_TOKEN 环境变量来指定。 其他注册中心的令牌可以用 CARGO_REGISTRIES_<name>_TOKEN 形式的环境变量来指定,其中 <name> 是大写的注册中心的名称。

配置键

本节记录了所有的配置键。带有可变部分的键的描述用角括号标注,如 target.<triple> , 其中 <triple> 部分可以是任意目标三元组,如 target.x86_64-pc-windows-msvc

paths

  • Type: 字符串数组 (paths)
  • Default: none
  • Environment: 不受支持

一个本地包的路径数组,这些包将用作依赖覆盖。 更多信息请参阅 覆盖依赖指南

[alias]

  • Type: 字符串或字符串数组
  • Default: 参阅下面
  • Environment: CARGO_ALIAS_<name>

[alias] 表定义了CLI命令的别名。例如,运行 cargo b 是运行 cargo build 的别名。表中的每个键是子命令,而值是实际要运行的命令。 值可以是一个字符串数组,其中第一个元素是命令,后面的元素是参数。它也可以是一个字符串,按空格分割成子命令和参数。以下是Cargo内置的别名:

[alias]
b = "build"
c = "check"
d = "doc"
t = "test"
r = "run"
rm = "remove"

别名不允许重新定义现有的内置命令。

别名可递归:

[alias]
rr = "run --release"
recursive_example = "rr --example recursions"

[build]

[build] 表控制构建时的操作和编译器设置。

build.jobs
  • Type: 整数
  • Default: 逻辑CPU的数量
  • Environment: CARGO_BUILD_JOBS

设定并行运行的最大编译器进程数。如果是负数,它将编译器进程的最大数量设置为逻辑CPU的数量加上所提供的值。不应为0。

可以用 --jobs CLI选项覆盖。

build.rustc
  • Type: 字符串 (程序路径)
  • Default: "rustc"
  • Environment: CARGO_BUILD_RUSTCRUSTC

设置用于 rustc 的可执行文件。

build.rustc-wrapper
  • Type: 字符串 (程序路径)
  • Default: none
  • Environment: CARGO_BUILD_RUSTC_WRAPPERRUSTC_WRAPPER

设置包装器来代替 rustc 执行。传递给包装器的第一个参数是要使用的实际可执行文件的路径(即 build.rustc ,如果它被设置了,或者 "rustc" 以其它方式)。

build.rustc-workspace-wrapper
  • Type: 字符串 (程序路径)
  • Default: none
  • Environment: CARGO_BUILD_RUSTC_WORKSPACE_WRAPPERRUSTC_WORKSPACE_WRAPPER

设置包装器来代替 rustc 执行,仅适用于工作空间成员。 传递给包装器的第一个参数是要使用的实际可执行文件的路径(即 build.rustc ,如果它被设置了,或 "rustc" 以其它方式)。 它影响文件名hash,以便包装器产生的制品被单独缓存。

build.rustdoc
  • Type: 字符串 (程序路径)
  • Default: "rustdoc"
  • Environment: CARGO_BUILD_RUSTDOCRUSTDOC

设置用于 rustdoc 的可执行文件。

build.target
  • Type: 字符串或字符串数组
  • Default: 主机平台
  • Environment: CARGO_BUILD_TARGET

默认的目标平台三元组编译。

这允许传递字符串或字符串数组。每个字符串值是目标平台三元组。将为每个选定的架构构建目标。

该字符串值也可以是 .json 目标规格文件的相对路径。

可以用 --target CLI选项覆盖。

[build]
target = ["x86_64-unknown-linux-gnu", "i686-unknown-linux-gnu"]
build.target-dir
  • Type: 字符路 (path)
  • Default: "target"
  • Environment: CARGO_BUILD_TARGET_DIRCARGO_TARGET_DIR

放置所有编译器输出的路径。如果没有指定,默认是位于工作空间根名为 target 的目录。

可以用 --target-dir CLI选项覆盖。

build.rustflags
  • Type: 字符串或字符串数组
  • Default: none
  • Environment: CARGO_BUILD_RUSTFLAGSCARGO_ENCODED_RUSTFLAGSRUSTFLAGS

额外的命令行标志,传递给 rustc 。该值可以是字符串数组或以空格分隔的字符串。

有四个互相排斥的额外标志来源,依次检查,首先使用第一个:

  1. CARGO_ENCODED_RUSTFLAGS 环境变量。
  2. RUSTFLAGS 环境变量。
  3. 所有匹配的 target.<triple>.rustflagstarget.<cfg>.rustflags 配置项连接在一起。
  4. build.rustflags 配置值。

额外的标志也可以通过 cargo rustc 命令传递。

如果使用 --target 标志(或build.target),那么这些标志将只传递给目标的编译器。为主机构建的内容,如构建脚本或过程宏,将不会收到这些参数。 如果不使用 --target ,标志将被传递给所有编译器调用(包括构建脚本和过程宏),因为依赖是共享的。 如果你有不想传递给构建脚本或过程宏的参数,并且是为主机构建的,请将 --target 与主机三元组一起传递。

我们不建议传入Cargo本身通常管理的标志。 例如,由profiles决定的标志,最好通过设置适当的配置文件来处理。

警告: 由于直接向编译器传递标志的低阶特性,这可能会与未来版本的Cargo产生冲突,后者可能会自行发布相同或类似的标志,这可能会干扰你指定的标志。 这是Cargo可能总是不会向后兼容的领域。

build.rustdocflags
  • Type: 字符串或字符串数组
  • Default: none
  • Environment: CARGO_BUILD_RUSTDOCFLAGSCARGO_ENCODED_RUSTDOCFLAGSRUSTDOCFLAGS

额外的命令行标志,传递给 rustdoc 。该值可以是字符串数组或以空格分隔的字符串。

有三个相互排斥的额外标志来源。依次检查它们,首先使用第一个:

  1. CARGO_ENCODED_RUSTDOCFLAGS 环境变量。
  2. RUSTDOCFLAGS 环境变量。
  3. build.rustdocflags 配置值。

附加标志也可以通过 cargo rustdoc 命令传递。

build.incremental
  • Type: bool
  • Default: 来自配置文件
  • Environment: CARGO_BUILD_INCREMENTALCARGO_INCREMENTAL

是否执行[增量编译]。如果没有设置,默认是使用 profile 中的值。否则这将覆盖所有配置文件的设置。

CARGO_INCREMENTAL 环境变量可以设置为 1 以强制启用所有配置文件的增量编译,或 0 以禁用它。这个环境变量覆盖配置设置。

build.dep-info-basedir
  • Type: 字符串 (path)
  • Default: none
  • Environment: CARGO_BUILD_DEP_INFO_BASEDIR

dep info文件路径中分割指定的路径前缀。 这个配置的目的是为需要相对路径的工具,将绝对路径转换成相对路径。

这个设置自身是与配置相对的路径。举例来说,"." 的值将分割所有以 .cargo 目录的父目录为起点的路径。

build.pipelining

这个选项已被废弃,未使用。Cargo总是启用流水线。

[doc]

[doc] 表定义了 cargo doc 命令的选项。

doc.browser
  • Type: 字符串或字符串数组 (带参数的程序路径)
  • Default: BROWSER 环境变量,如果缺少该变量,则以系统特定的方式打开链接

这个选项设置 cargo doc 使用的浏览器,在用 --open 选项打开文档时,覆盖 BROWSER 环境变量。

[cargo-new]

[cargo-new] 表定义了 cargo new 命令的默认值。

cargo-new.name

该选项已被废弃,未被使用。

cargo-new.email

该选项已被废弃,未被使用。

cargo-new.vcs
  • Type: 字符串
  • Default: "git" 或 "none"
  • Environment: CARGO_CARGO_NEW_VCS

指定初始化新版本库时使用的源码控制系统。 有效值是 githg (用于Mercurial) 、 pijulfossil ,或 none 以禁用此行为。默认为 git ,如果已经在一个VCS仓库内,则默认为 none 。可以用 --vcs CLI选项来覆盖。

[env]

[env] 部分允许你为构建脚本、rustc调用、 cargo runcargo build 设置附加的环境变量。

[env]
OPENSSL_DIR = "/opt/openssl"

默认情况下,指定的变量将不会覆盖环境中已经存在的值。可以通过设置 force 标志来改变这种行为。

设置 relative 标志会将该值评估为相对配置路径,它是相对于包含 config.toml 文件的 .cargo 目录的父目录而言的。环境变量的值将是完整的绝对路径。

[env]
TMPDIR = { value = "/home/tmp", force = true }
OPENSSL_DIR = { value = "vendor/openssl", relative = true }

[future-incompat-report]

[future-incompat-report] 表控制 未来不匹配的报告 的设置。

future-incompat-report.frequency

  • Type: 字符串
  • Default: "always"
  • Environment: CARGO_FUTURE_INCOMPAT_REPORT_FREQUENCY

控制当未来不兼容报告可用时,多长时间向终端显示一次通知。可能的值为:

  • always (默认): 当命令(例如 cargo build)产生未来不兼容报告时,总是显示通知。
  • never: 永不显示通知

[http]

[http] 表定义了HTTP行为设置。包括获取crate的依赖和访问远程git仓库。

http.debug
  • Type: boolean
  • Default: false
  • Environment: CARGO_HTTP_DEBUG

如果 true ,启用对HTTP请求的调试。调试信息可以通过设置 CARGO_LOG=cargo::ops::registry=debug 环境变量查看(或者使用 trace 获取更多信息) 。

当把这个输出的日志发布到公开位置时,要小心谨慎。该输出可能包括带有认证令牌的头信息,你不希望泄漏这些信息。在发布日志之前,一定要审查日志。

http.proxy
  • Type: 字符串
  • Default: none
  • Environment: CARGO_HTTP_PROXYHTTPS_PROXYhttps_proxyhttp_proxy

设置一个要使用的HTTP和HTTPS代理。其格式为 [libcurl格式] ,如 [protocol://]host[:port] 。 如果没有设置,Cargo也会检查你全局git配置中的 http.proxy 设置。 如果这些都没有设置, HTTPS_PROXYhttps_proxy 环境变量为HTTPS请求设置代理, http_proxy 为HTTP请求设置。

http.timeout
  • Type: 整数
  • Default: 30
  • Environment: CARGO_HTTP_TIMEOUTHTTP_TIMEOUT

设置每个HTTP请求的超时,单位为秒。

http.cainfo
  • Type: 字符串 (path)
  • Default: none
  • Environment: CARGO_HTTP_CAINFO

CA证书绑定文件的路径,用于验证TLS证书。如果没有指定,Cargo会尝试使用系统证书。

http.check-revoke
  • Type: boolean
  • Default: true (Windows) false (all others)
  • Environment: CARGO_HTTP_CHECK_REVOKE

这决定了是否应该进行TLS证书撤销检查。仅适用于Windows。

http.ssl-version
  • Type: string or min/max table
  • Default: none
  • Environment: CARGO_HTTP_SSL_VERSION

此设置要使用的最小TLS版本。它需要一个字符串,可能的值是 "default"、"tlsv1"、"tlsv1.0"、"tlsv1.1"、"tlsv1.2"、"tlsv1.3" 之一。

这可能是有两个键的表, minmax ,每个键都有相同的字符串值,指定要使用的TLS版本的最小和最大范围。

默认情况下,最小版本为 "tlsv1.0" ,最大版本为你的平台上支持的最新版本,通常为 "tlsv1.3" 。

http.low-speed-limit
  • Type: 整数
  • Default: 10
  • Environment: CARGO_HTTP_LOW_SPEED_LIMIT

此设置控制过慢连接超时行为。 如果以字节/秒为单位的平均传输速度低于http.timeout秒的给定值(默认为30秒),那么该连接被认为太慢,Cargo将中止并重试。

http.multiplexing
  • Type: boolean
  • Default: true
  • Environment: CARGO_HTTP_MULTIPLEXING

true 时,Cargo将尝试使用多路复用的HTTP2协议。 这允许多个请求使用同一个连接,通常可以提高获取多文件的性能。 如果 false ,Cargo将使用HTTP1.1,没有管道。

http.user-agent
  • Type: 字符串
  • Default: Cargo的版本
  • Environment: CARGO_HTTP_USER_AGENT

指定要使用的自定义user-agent 头。如果没有指定,默认是一个包括Cargo版本的字符串。

[install]

[install] 表定义了 cargo install 命令的默认值。

install.root
  • Type: 字符串 (path)
  • Default: Cargo的主目录
  • Environment: CARGO_INSTALL_ROOT

cargo install 设置安装可执行文件的根目录的路径。可执行文件会进入根目录下的 bin 目录。

为了跟踪已安装的可执行文件的信息,一些附加文件,如 .crates.toml.crates2.json 也会在这个根下创建。

如果没有指定,默认是Cargo的主目录 (默认为你的主目录中 .cargo ) 。

可以用 --root 命令行选项来覆盖。

[net]

[net] 表控制网络配置。

net.retry
  • Type: 整数
  • Default: 2
  • Environment: CARGO_NET_RETRY

可能是虚假网络的错误重试次数。

net.git-fetch-with-cli
  • Type: boolean
  • Default: false
  • Environment: CARGO_NET_GIT_FETCH_WITH_CLI

如果这是 true ,那么Cargo将使用 git 可执行程序来获取注册中心索引和git依赖。如果是 false ,那么它将使用内置的 git 库。

如果你有特殊的认证要求,而Cargo不支持的话,将此设置为 true 会有帮助。 参阅 Git Authentication以了解更多关于设置git认证的信息。

net.offline
  • Type: boolean
  • Default: false
  • Environment: CARGO_NET_OFFLINE

如果是 true ,那么Cargo将避免访问网络,并尝试使用本地缓存的数据。 如果是 false ,Cargo将根据需要访问网络,如果遇到网络错误,将产生一个错误。

可以用 --offline 命令行选项来覆盖。

[patch]

就像你可以用[patch] in Cargo.toml覆盖依赖一样, 你可以在cargo配置文件中覆盖它们,将这些补丁应用于任何受影响的构建。其格式与 Cargo.toml 中的格式相同。

由于 .cargo/config.toml 文件通常不会检出到源代码控制中,你应该尽可能选择使用 Cargo.toml 来打补丁,以确保其他开发者可以在自己的环境中编译你的crate。 一般来说,只有当补丁部分由外部构建工具自动生成时,才合适通过cargo配置文件进行修补。

如果特定的依赖在cargo配置文件和 Cargo.toml 文件中都有补丁,则使用配置文件中的补丁。 如果多个配置文件对同一个依赖打了补丁,则使用标准的cargo配置合并,它更倾向于使用离当前目录最近的定义值。 $HOME/.cargo/config.toml 的优先级最低。

在这样的 [patch] 部分中的相对的 path 依赖是相对于它们出现的配置文件。

[profile]

[profile] 表可以用来全局改变编译设置,并覆盖 Cargo.toml 中指定的设置。 它的语法和选项与 Cargo.toml 中指定的编译设置相同。 关于选项的详细信息,请参阅 [编译设置章节] 。

[profile.<name>.build-override]
  • Environment: CARGO_PROFILE_<name>_BUILD_OVERRIDE_<key>

build-override 表覆盖构建脚本、过程宏和其依赖的设置。 它的键值与常规profile相同。参见 覆盖部分 以了解更多细节。

[profile.<name>.package.<name>]
  • Environment: 不支持

包的表覆盖特定包的设置。它和常规的profile有相同的键,除了 panicltorpath 设置。 参阅 overrides section 以了解更多细节。

profile.<name>.codegen-units
  • Type: 整数
  • Default: 参阅配置文件文档。
  • Environment: CARGO_PROFILE_<name>_CODEGEN_UNITS

参阅 codegen-units

profile.<name>.debug
  • Type: 整数或布尔
  • Default: 参阅配置文件文档。
  • Environment: CARGO_PROFILE_<name>_DEBUG

参阅 debug

profile.<name>.split-debuginfo
  • Type: 字符串
  • Default: 参阅配置文件文档。
  • Environment: CARGO_PROFILE_<name>_SPLIT_DEBUGINFO

参阅 split-debuginfo

profile.<name>.debug-assertions
  • Type: 布尔
  • Default: 参阅配置文件文档。
  • Environment: CARGO_PROFILE_<name>_DEBUG_ASSERTIONS

参阅 debug-assertions

profile.<name>.incremental
  • Type: 布尔
  • Default: 参阅配置文件文档。
  • Environment: CARGO_PROFILE_<name>_INCREMENTAL

参阅 incremental.

profile.<name>.lto
  • Type: 字符串或布尔
  • Default: 参阅配置文件文档。
  • Environment: CARGO_PROFILE_<name>_LTO

参阅 lto

profile.<name>.overflow-checks
  • Type: 布尔
  • Default: 参阅配置文件文档。
  • Environment: CARGO_PROFILE_<name>_OVERFLOW_CHECKS

参阅 overflow-checks

profile.<name>.opt-level
  • Type: 字符串或布尔
  • Default: 参阅配置文件文档。
  • Environment: CARGO_PROFILE_<name>_OPT_LEVEL

参阅 opt-level

profile.<name>.panic
  • Type: 字符串
  • default: 参阅配置文件文档。
  • Environment: CARGO_PROFILE_<name>_PANIC

参阅 panic

profile.<name>.rpath
  • Type: 布尔
  • default: 参阅配置文件文档。
  • Environment: CARGO_PROFILE_<name>_RPATH

参阅 rpath

[registries]

[registries] 表用于指定额外的[注册中心]。它由各个命名的注册中心的子表组成。

registries.<name>.index
  • Type: 字符串 (url)
  • Default: none
  • Environment: CARGO_REGISTRIES_<name>_INDEX

指定注册中心git索引的URL。

registries.<name>.token
  • Type: 字符串
  • Default: none
  • Environment: CARGO_REGISTRIES_<name>_TOKEN

指定特定注册中心的认证令牌。 这个值应该只出现在 credentials 文件中。 这用于需要认证的注册中心命令,如 cargo publish

可以用 --token 命令行选项来覆盖。

[registry]

[registry] 表控制在没有指定的情况下使用的默认注册中心。

registry.index

不再接受此值,不应使用。

registry.default
  • Type: 字符串
  • Default: "crates-io"
  • Environment: CARGO_REGISTRY_DEFAULT

注册中心的名称(来自 registries),默认用于 cargo publish 等注册中心命令。

可以用 --registry 命令行选项来覆盖。

registry.token
  • Type: 字符串
  • Default: none
  • Environment: CARGO_REGISTRY_TOKEN

指定 crates.io 的认证令牌。 这个值应该只出现在 credentials 文件中。 这用于像 cargo publish 这样的需要认证的注册中心命令。

可以用 --token 命令行选项来覆盖。

[source]

[source] 表定义了可用的注册中心源。更多信息见源替换。 它由每个命名的源的子表组成。源应该只定义为目录、注册中心、本地注册或git中的一种。

source.<name>.replace-with
  • Type: 字符串
  • Default: none
  • Environment: 不支持

如果设置,用给定的命名源或命名注册中心替换这个源。

source.<name>.directory
  • Type: 字符串 (path)
  • Default: none
  • Environment: 不支持

设置目录路径,作为目录源使用。

source.<name>.registry
  • Type: 字符串 (url)
  • Default: none
  • Environment: 不支持

设置用于注册中心源的URL。

source.<name>.local-registry
  • Type: 字符串 (path)
  • Default: none
  • Environment: 不支持

设置目录路径,用作本地注册源。

source.<name>.git
  • Type: 字符串 (url)
  • Default: none
  • Environment: 不支持

设置用于git仓库源的URL。

source.<name>.branch
  • Type: 字符串
  • Default: none
  • Environment: 不支持

设置用于git仓库的分支名称。

如果没有设置 branchtagrev ,则默认为 master 分支。

source.<name>.tag
  • Type: 字符串
  • Default: none
  • Environment: 不支持

设置用于git仓库的tag名称。

如果没有设置 branchtagrev ,则默认为 master 分支。

source.<name>.rev
  • Type: 字符串
  • Default: none
  • Environment: 不支持

设置用于git仓库的revision

如果没有设置 branchtagrev ,则默认为 master 分支。

[target]

[target] 表用于指定特定平台目标的设置。 它由子表组成,这个子表是平台三元组或 cfg() 表达式 。 如果目标平台与 <triple> 值或 <cfg> 表达式匹配,将使用给定的值。

[target.thumbv7m-none-eabi]
linker = "arm-none-eabi-gcc"
runner = "my-emulator"
rustflags = ["…", "…"]

[target.'cfg(all(target_arch = "arm", target_os = "none"))']
runner = "my-arm-wrapper"
rustflags = ["…", "…"]

cfg 值来自编译器内置的值 (运行 rustc --print=cfg 查看),由[构建脚本]设置的值,以及传递给 rustc 的附加 --cfg 标志(例如在 RUSTFLAGS 中定义的标志)。 不要在 debug_assertions 或 Cargo 特性(如 feature="foo" )上尝试match匹配。

如果使用目标规格的JSON文件,<triple> 值是文件名。例如, --target foo/bar.json 将匹配 [target.bar]

target.<triple>.ar

该选项已被废弃,未被使用。

target.<triple>.linker
  • Type: 字符串 (程序路径)
  • Default: none
  • Environment: CARGO_TARGET_<triple>_LINKER

指定在编译 <triple> 时传递给 rustc (通过-C linker) 的链接器。默认情况下,链接器不可覆盖。

target.<triple>.runner
  • Type: 字符串或者字符串数组 (带参数的程序路径)
  • Default: none
  • Environment: CARGO_TARGET_<triple>_RUNNER

如果提供了运行器,目标 <triple> 的可执行文件将通过调用指定的运行器和作为参数传递的实际可执行文件来执行。 这适用于 cargo run, cargo testcargo bench 命令。 默认情况下,编译后的可执行文件被直接执行。

target.<cfg>.runner

这类似于 target runner ,但使用 cfg() 表达式 。 如果同时有 <triple><cfg> 运行器匹配, <triple> 将优先使用。 如果有一个以上的 <cfg> 运行器与当前目标匹配,则错误。

target.<triple>.rustflags
  • Type: 字符串或字符串数组
  • Default: none
  • Environment: CARGO_TARGET_<triple>_RUSTFLAGS

为这个 <triple> 向编译器传递一组自定义标志。该值可以是字符串数组或以空格分隔的字符串。

参阅 build.rustflags ,以了解更多关于特定附加标志的不同方式的细节。

target.<cfg>.rustflags

这类似于 target rustflags ,但使用 cfg() 表达式 。 如果有几个 <cfg><triple> 条目与当前的目标相匹配,这些标志就会被关连在一起。

链接子表提供了一种[覆盖构建脚本]的方法。 当指定时,给定的 links 库的构建脚本将不会运行,而会使用给定的值。

[target.x86_64-unknown-linux-gnu.foo]
rustc-link-lib = ["foo"]
rustc-link-search = ["/path/to/foo"]
rustc-flags = "-L /some/path"
rustc-cfg = ['key="value"']
rustc-env = {key = "value"}
rustc-cdylib-link-arg = ["…"]
metadata_key1 = "value"
metadata_key2 = "value"

[term]

[term] 表控制终端输出和交互。

term.quiet
  • Type: 布尔
  • Default: false
  • Environment: CARGO_TERM_QUIET

控制Cargo是否显示日志信息。

指定 --quiet 标志将覆盖和强制静默输出。 指定 --verbose 标志将覆盖和禁用静默输出。

term.verbose
  • Type: 布尔
  • Default: false
  • Environment: CARGO_TERM_VERBOSE

控制Cargo是否显示附加的详细信息。

指定 --quiet 标志将覆盖并禁用信息输出。 指定 --verbose 标志将覆盖并强制进行信息输出。

term.color
  • Type: 字符串
  • Default: "auto"
  • Environment: CARGO_TERM_COLOR

控制是否在终端中使用彩色输出。可能的值:

  • auto (默认): 自动检测终端是否有颜色支持。
  • always: 允许显示颜色。
  • never: 不允许显示颜色。

可以用 --color 命令行选项来覆盖。

term.progress.when
  • Type: 字符串
  • Default: "auto"
  • Environment: CARGO_TERM_PROGRESS_WHEN

控制是否在终端中显示进度条。可能的值:

  • auto (默认): 智能地猜测是否显示进度条。
  • always: 允许显示进度条。
  • never: 不允许显示进度条。
term.progress.width
  • Type: 整数
  • Default: none
  • Environment: CARGO_TERM_PROGRESS_WIDTH

设置进度条的宽度。

环境变量

Cargo设置和读取一些环境变量,你的代码可以检测或覆盖这些变量。 下面是Cargo设置的变量列表,按照与之交互的时间次序排列:

Cargo读取环境变量

你可以覆盖这些环境变量在系统中改变Cargo的行为:

  • CARGO_LOG - Cargo 使用 env_logger crate 来显示调试日志信息。 CARGO_LOG 环境变量可以设置为启用调试日志,其值为 tracedebugwarn 。 通常,其只在调试时使用。更多细节请参考Debug logging
  • CARGO_HOME — Cargo 维护着注册中心索引和git签出crate的本地缓存。 默认情况下,这些数据存储在 $HOME/.cargo 下(Windows下为 %USERPROFILE%\.cargo ),但这个变量可以覆盖这个目录位置。 一旦crate被缓存,就不会被clean命令删除。更多细节请参考 指南
  • CARGO_TARGET_DIR — 放置所有生成制品的位置,相对于当前工作目录。见build.target-dir通过配置来设置。
  • CARGO - 如果设置了这个值,Cargo在构建crate以及执行构建脚本和外部子命令时,将转发这个值,而不是设置为自己的自动检测路径。 这个值不会被Cargo直接执行,它应该总是指向一个行为与 cargo 完全相同的命令,因为这也是使用该值的用户所期望的。
  • RUSTC — Cargo将执行这个指定的编译器,而不是运行 rustc 。见build.rustc通过配置来设置。
  • RUSTC_WRAPPER — Cargo将执行这个指定的包装器,而不是简单地运行 rustc ,将rustc的调用作为其命令行参数,第一个参数是实际rustc的路径。 这对设置构建缓存工具(如 sccache)很有用。见 build.rustc-wrapper 通过配置来设置。 将其设置为空字符串会覆盖配置,并将crate重置为不使用包装器。
  • RUSTC_WORKSPACE_WRAPPER — 对于工作空间成员,Cargo将执行这个指定的包装器,而不是简单地运行 rustc ,将rustc的调用作为其命令行参数,第一个参数是实际rustc的路径。 它影响文件名hash,以便单独缓存包装器产生制品。参见 build.rustc-workspace-wrapper 通过配置来设置。 将其设置为空字符串会覆盖配置,并将crate重置为不对工作空间成员使用包装器。
  • RUSTDOC — Cargo将执行这个指定的 rustdoc 实例,而不是运行 rustdoc 。见 build.rustdoc 通过配置来设置。
  • RUSTDOCFLAGS — 以空格分隔的自定义标志列表,用于传递给Cargo执行的所有 rustdoc 调用。 与 cargo rustdoc 不同的是,这对于向 所有 rustdoc 实例传递标志很有用。 参见 build.rustdocflags 以了解更多设置标志的方法。这个字符串用空格分割;如果要对多个参数进行更健壮的编码,请参见 CARGO_ENCODED_RUSTDOCFLAGS
  • CARGO_ENCODED_RUSTDOCFLAGS - 用 0x1f (ASCII单位分隔符)分隔的自定义标志列表,用于传递给Cargo执行的所有 rustdoc 调用。
  • RUSTFLAGS — 以空格分隔的自定义标志列表,用于传递给Cargo执行的所有编译器调用。 与 cargo rustc 不同的是,这对于向 所有 编译器实例传递标志很有用。 参见 build.rustflags 以了解更多设置标志的方法。这个字符串是由空格分割;如果要对多个参数进行更健壮的编码,见 CARGO_ENCODED_RUSTFLAGS
  • CARGO_ENCODED_RUSTFLAGS - 用 0x1f (ASCII单元分隔符) 分隔的自定义标志列表,用于传递给Cargo执行的所有编译器调用。
  • CARGO_INCREMENTAL — 如果设置为1,那么Cargo将强制在当前编译中启用incremental compilation ,设置为0时, 将强制禁用增量编译。如果这个环境变量不存在,那么将使用cargo的默认值。另请参见 build.incremental 配置值。
  • CARGO_CACHE_RUSTC_INFO — 如果这个设置为0,那么Cargo将不会尝试缓存编译器版本信息。
  • HTTPS_PROXY or https_proxy or http_proxy — 要使用的HTTP代理,更多细节见 http.proxy
  • HTTP_TIMEOUT — HTTP超时,以秒为单位,详见 http.timeout
  • TERM — 如果这个设置为 dumb ,将禁用进度条。
  • BROWSER — 用 cargo doc--open 标志打开文档时要执行的网络浏览器,更多细节见 doc.browser
  • RUSTFMT — 代替 rustfmtcargo fmt 将执行这个指定的 rustfmt 实例。

配置环境变量

Cargo会读取一些配置值的环境变量。详情见配置章节。概括起来,支持的环境变量有:

环境变量Cargo的crate集

Cargo在编译时将这些环境变量暴露给你的crate。 注意,这也适用于用 cargo runcargo test 运行二进制文件。 要在Rust程序中获得这些变量的值,请这样做:

let version = env!("CARGO_PKG_VERSION");

version 现在将包含 CARGO_PKG_VERSION 的值。

请注意,如果配置清单中没有提供这些值之一,则相应的环境变量将被设置为空字符串 ""

  • CARGO — 执行构建的 cargo 二进制文件的路径。
  • CARGO_MANIFEST_DIR — 包含你的包配置清单的目录。
  • CARGO_PKG_VERSION — 你的包的完整版本。
  • CARGO_PKG_VERSION_MAJOR — 你的包的主要版本。
  • CARGO_PKG_VERSION_MINOR — 你的包的次要版本。
  • CARGO_PKG_VERSION_PATCH — 你的包的补丁版本。
  • CARGO_PKG_VERSION_PRE — 你的包的预发布版本。
  • CARGO_PKG_AUTHORS — 冒号分隔的作者名单,来自你的包的配置清单。
  • CARGO_PKG_NAME — 你的包的名称。
  • CARGO_PKG_DESCRIPTION — 你的包配置清单的描述。
  • CARGO_PKG_HOMEPAGE — 你的包的配置清单中的主页。
  • CARGO_PKG_REPOSITORY — 你的包配置清单中的存储库。
  • CARGO_PKG_LICENSE — 你的包的配置清单中的许可证。
  • CARGO_PKG_LICENSE_FILE — 你的包的配置清单中的许可证文件。
  • CARGO_PKG_RUST_VERSION — 你的包的配置清单中的Rust版本。 注意,这是包支持的最小Rust版本,而不是当前的Rust版本。
  • CARGO_CRATE_NAME — 当前正在编译的crate的名称。
  • CARGO_BIN_NAME — 当前正在编译的二进制文件的名称(如果它是一个二进制文件)。这个名字不包括任何文件扩展名,如 .exe
  • OUT_DIR — 如果该包有构建脚本,这将被设置为构建脚本应该放置其输出的文件夹。更多信息见下文。(只在编译过程中设置)。
  • CARGO_BIN_EXE_<name> — 二进制目标的可执行文件的绝对路径。这只在构建集成测试或性能测试时设置。这可以与env macro一起使用,以找到为测试目的运行的可执行文件。 <name> 是二进制目标的名称,完全按原样。例如, CARGO_BIN_EXE_my-program 代表一个名为 my-program 的二进制文件。当测试建立时,二进制文件会自动建立,除非二进制文件有未启用的必要特性。
  • CARGO_PRIMARY_PACKAGE — 如果正在构建的包是主要的,这个环境变量将被设置。主要包是用户在命令行中选择的,可以是 -p 标志,也可以是基于当前目录和默认工作空间成员的默认值。这个环境变量在构建依赖时不会被设置。只有在编译包时才会设置 (而不是在运行二进制文件或测试时) 。
  • CARGO_TARGET_TMPDIR — 只在构建集成测试或性能测试代码时设置。这是一个指向目标目录内的路径,集成测试或性能测试可以在这里自由放置测试/性能测试所需的任何数据。Cargo初始创建这个目录,但不以任何方式管理其内容,这是测试代码的责任。

动态库路径

在使用 cargo runcargo test 等命令编译和运行二进制文件时,Cargo也会设置动态库路径。这有助于定位作为构建过程一部分的共享库。变量名称取决于平台:

  • Windows: PATH
  • macOS: DYLD_FALLBACK_LIBRARY_PATH
  • Unix: LD_LIBRARY_PATH

macOS有特殊的考虑,如果 DYLD_FALLBACK_LIBRARY_PATH 还没有设置,它就会增加默认的 $HOME/lib:/usr/local/lib:/usr/lib

Cargo包括以下路径:

  • 搜索任何带有rustc-link-search instruction的构建脚本中包含的路径。 target 目录之外的路径会被删除。如果在搜索路径中需要额外的系统库,运行Cargo的用户有责任正确设置环境。
  • 基本输出目录,如 target/debug ,和 "deps" 目录。这主要是为了对 rustc 编译器插件的遗留支持。
  • rustc sysroot库的路径。这对大多数用户来说通常并不重要。

环境变量 Cargo 为构建脚本设置的环境变量

Cargo在运行构建脚本时设置了几个环境变量。因为这些变量在编译构建脚本时还没有设置,所以上面的例子中使用 env! 是行不通的,而是需要在运行构建脚本时检索这些值。

use std::env;
let out_dir = env::var("OUT_DIR").unwrap();

out_dir 现在将包含 OUT_DIR 的值。

  • CARGO — 执行构建的 cargo 二进制文件的路径。
  • CARGO_MANIFEST_DIR — 包含正在构建的包的配置清单的目录(包含构建脚本的包)。还要注意,这是构建脚本启动时的当前工作目录的值。
  • CARGO_MANIFEST_LINKS — 配置清单 links 值。
  • CARGO_MAKEFLAGS — 包含Cargo的jobserver实现所需的参数,以使子进程并行化。Rustc或build.rs中的cargo调用已经可以读取 CARGO_MAKEFLAGS ,但GNU Make要求这些标志直接作为参数指定,或通过 MAKEFLAGS 环境变量指定。目前Cargo并没有设置 MAKEFLAGS变量,但GNU Make的编译脚本可以将其设置为 CARGO_MAKEFLAGS 的内容。
  • CARGO_FEATURE_<name> — 对于正在构建的包的每个激活的特性,这个环境变量将出现,其中 <name> 是特性的名称,为大写字母, - 转换成 _
  • CARGO_CFG_<cfg> — 对于正在构建的包的每一个配置选项,这个环境变量将包含配置的值,其中 <cfg> 是配置的名称,为大写,并将 - 转换为 _ 。 布尔型配置如果被设置就会出现,否则就不会出现。具有多个值的配置连接到一个变量,其值以 , 分割。 这包括编译器内置的值(可以用rustc --print=cfg 查看),以及由编译脚本和传递给 rustc 的额外标志(比如在 RUSTFLAGS 中定义的)设置的值。这些变量的一些例子:
  • OUT_DIR — 所有输出和中间制品应该放在哪个文件夹里。这个文件夹位于正在构建的包的构建目录内,而且对相关的包来说是唯一的。
  • TARGET — 正在被编译的目标三元组。本地代码应该为这个三元组进行编译。更多信息请参见 Target Triple 的描述。
  • HOST — 是Rust编译器的主机三元组。
  • NUM_JOBS — 被指定为顶层的并行性。这对于向 make 这样的系统传递 -j 参数很有用。注意,在解释这个环境变量的时候要注意。 出于历史原因,仍然提供了这个变量,但最近的Cargo版本,例如,不需要运行 make -j ,而是可以将 MAKEFLAGS 环境变量设置为 CARGO_MAKEFLAGS 的内容,以激活使用Cargo的GNU Make兼容 jobserver 进行子make调用。
  • OPT_LEVEL, DEBUG — 目前正在建立的配置文件的相应变量的值。
  • PROFILErelease 用于发布版本, debug 用于其他版本。这是根据 profile 是否继承自 devrelease 配置文件来决定的。不建议使用这个环境变量。使用其他环境变量,如 OPT_LEVEL ,可以更准确地了解正在使用的实际设置。
  • DEP_<name>_<key> — 关于这组环境变量的更多信息,请参见关于 links 的构建脚本文档。
  • RUSTC, RUSTDOC — 是Cargo决定使用的编译器和文档生成器,传递给构建脚本,以便它也能使用。
  • RUSTC_WRAPPER — Cargo使用的 rustc 包装器,如果有的话。 见 build.rustc-wrapper.
  • RUSTC_WORKSPACE_WRAPPERrustc 包装器,如果有的话,Cargo对工作空间成员使用。 见 build.rustc-workspace-wrapper.
  • RUSTC_LINKER — 如果指定了链接器,则是Cargo已经决定为当前目标使用的链接器二进制文件的路径。链接器可以通过编辑 .cargo/config.toml 来改变;更多信息请参见 cargo configuration 文档。
  • CARGO_ENCODED_RUSTFLAGS — 附加的标志,Cargo调用 rustc 时,用 0x1f 字符(ASCII单位分隔符)分隔。见 build.rustflags 。注意,从Rust 1.55开始, RUSTFLAGS 已经从环境中移除;脚本应该使用 CARGO_ENCODED_RUSTFLAGS 代替。
  • CARGO_PKG_<var> - 包的信息变量,其名称和数值与在crate构建过程中提供的相同。

环境变量 Cargo 为第三方子命令设置的环境变量

Cargo将这个环境变量暴露给第三方子命令(即放在 $PATH 中的名为 cargo-foobar 的程序):

  • CARGO — 执行构建的 cargo 二进制文件的路径。

对于你的环境的扩展信息,可以运行 cargo metadata

构建脚本

有些包需要编译第三方的非Rust代码,例如C库。 有些包需要链接到C库,这些库可能位于系统中,也可能需要从源代码构建。 还有包需要一些功能性工具,比如在构建前生成代码 (语法分析生成器就是这样) 。

Cargo 并不是要取代这些为了任务优化的其他工具,而是可以通过定制构建脚本的方式,与这些工具进行整合。 在包的根目录下放置名称为 build.rs 的文件,Cargo会在构建包之前,先编译并执行该脚本。

// 自定义构建脚本的例子。
fn main() {
    // 告诉Cargo,如果指定的文件发生更改,则重新运行此构建脚本。
    println!("cargo:rerun-if-changed=src/hello.c");
    // 使用 `cc` crate 构建 C 文件并静态链接。
    cc::Build::new()
        .file("src/hello.c")
        .compile("hello");
}

构建脚本的一些用例如下:

  • 构建时绑定C库。
  • 在主机系统中查找C库。
  • 根据规范生成Rust模块。
  • 执行crate所需的任意平台特定的配置。

下面部分描述了构建脚本的工作方式。示例章节 有关于如何编写脚本的各种示例。

注意: 可以使用 package.build 配置键 来改变构建脚本的名称,或者是禁用。

构建脚本的生命周期

在构建包之前,Cargo会将构建脚本编译成可执行文件 (如果没有合适的构建)。 然后运行脚本,该脚本可以执行任意数量的任务。 脚本可以通过将带有 cargo: 前缀的特殊格式化命令打印到标准输出,从而与 Cargo 通信。

如果构建脚本的任意源文件或依赖发生更改,将重新构建脚本。

默认情况下,如果包中的任何文件发生变化,Cargo 会重新构建脚本。 通常,最好使用下面 change detection 一节中描述的 rerun-if 命令,以缩小触发重新构建的关注范围。

一旦构建脚本成功执行完毕,就会编译包的其他部分。 脚本应该以非零的退出代码退出,以便在出现错误时停止编译,此时,编译脚本的输出将显示在终端。

构建脚本的输入

当构建脚本运行时,对于构建脚本的输入,则都是以 环境变量 的形式传递。

除了环境变量外,构建脚本的当前目录是构建脚本的包的源目录。

构建脚本的输出

构建脚本可以将任何输出文件或中间制品保存在 OUT_DIR 环境变量 指定的目录中。 脚本不应该修改该目录之外的任何文件。

构建脚本通过打印信息到标准输出,从而与Cargo交流。 Cargo 会把每一行以 cargo: 开头的文字理解为影响包编译的指令,而忽略所有其他行。

注意:构建脚本打印的 cargo: 指令的顺序 可能 会影响 cargo 传递给 rustc 的参数的顺序。 反过来,传递给 rustc 的参数顺序也可能影响传递给链接器的参数顺序。 因此,你要注意构建脚本的指令顺序。 例如,如果对象 foo 需要与库 bar 链接,你可能需要确保库 barcargo:rustc-link-lib 指令出现在链接对象 foo 的指令 之后

在正常的编译过程中,脚本的输出信息会在终端中隐藏。 如果你想在终端上直接看到输出,可以用 -vv 标志让Cargo "详细输出" 。 这只发生在编译脚本运行的时候。 如果Cargo认为没有任何变化,就不会重新运行脚本,更多信息请参阅下面的 变化检测

构建脚本打印到标准输出的所有行都被写入一个文件,如 target/debug/build/<pkg>/output(确切位置可能取决于你的配置)。标准错误输出也保存在同一目录。

以下是 Cargo 所认识的指令摘要,每条指令都在下面详细说明。

rustc-link-arg 指令告诉Cargo将 -C link-arg=FLAG option 传递给编译器,但只在构建支持的目标(性能测试、二进制文件、 cdylib crate 、示例和测试)时使用。 它的用法与平台高度相关。对设置共享库版本或链接器脚本很有用。

rustc-link-arg-bin 指令告诉Cargo将 -C link-arg=FLAG option 传递给编译器,但只在构建名称为 BIN 的二进制目标时使用。 它的用法与平台高度相关。对设置链接器脚本或其他链接器选项很有用。

rustc-link-arg-bins 指令告诉Cargo将 -C link-arg=FLAG option 传递给编译器,但只在构建二进制目标时使用。 它的用法与平台高度相关。对于设置链接器脚本或其他链接器选项很有用。

rustc-link-lib 指令告诉 Cargo 使用编译器的 -l flag 来链接指定的库。 这通常用于使用 FFI 来链接本地库。

LIB 字符串是直接传递给rustc的,所以它支持任何 -l 语法。 目前, LIB 支持的全部语法是 [KIND[:MODIFIERS]=]NAME[:RENAME]

-l 标志只传递给包的库目标,若没有库目标会传递给所有目标。 这样做是因为其他目标会隐含对库目标的依赖,而链接库只应该包含一次。 这意味着,如果一个包有一个库和一个二进制目标,那么 可以访问给定 lib 的符号,而二进制应该通过库目标的公共 API 来访问。

可选的 KIND 可以是 dylibstaticframework 之一。 更多细节参阅 rustc book

rustc-link-arg-tests 指令告诉Cargo将 -C link-arg=FLAG option 传递给编译器,但只在构建测试目标时使用。

rustc-link-arg-examples 指令告诉Cargo将 -C link-arg=FLAG option 传递给编译器,但只在构建实例目标时传递。

rustc-link-arg-benches 指令告诉Cargo将 -C link-arg=FLAG option 传递给编译器,但只在构建性能测试目标时使用。

rustc-link-search 指令告诉Cargo将 -L flag 传递给编译器,在库搜索路径中添加一个目录。

可选的 KIND 可以是 dependencycratenativeframeworkall 之一。更多细节参阅 rustc book

如果这些路径在 OUT_DIR 内,它们也会被添加到 动态库搜索路径环境变量 。 不鼓励依赖这种行为,因为这使得,使用产生的二进制文件很困难。一般来说,最好避免在构建脚本中创建动态库(使用现有的系统库就可以了)。

cargo:rustc-flags=FLAGS

rustc-flags 指令告诉Cargo将给定的以空格分隔的标志传递给编译器。 只允许使用 -l -L 标志,相当于使用 rustc-link-librustc-link-search

cargo:rustc-cfg=KEY[="VALUE"]

rustc-cfg 指令告诉Cargo将给定的--cfg flag 的值传递给编译器。 这可用于编译时检测功能,以启用 条件编译

请注意,这并 影响Cargo的依赖解析。 这不能用来启用一个可选的依赖,或启用其他Cargo特性。

请注意,Cargo features 使用的是 feature="foo" 的形式。 用这个标志传递的 cfg 值不限于这种形式,可以只提供一个标识符,或任意的键值对。 例如,发送 cargo:rustc-cfg=abc 将允许代码使用 #[cfg(abc)] (注意缺少 feature= )。 或者可以使用任意的键值对与一个 = 号,如 cargo:rustc-cfg=my_component="foo" 。 键应该是一个Rust标识符,值应该是一个字符串。

cargo:rustc-env=VAR=VALUE

rustc-env 指令告诉Cargo在编译包的时候设置指定的环境变量。 然后可以通过编译后的crate中的 env! macro 来检索该值。 这对于在crate的代码中嵌入额外的元数据很有用,例如git HEAD的哈希值或持续集成服务器的唯一标识符。

参阅 Cargo自动包含环境变量

注意: 当用 cargo runcargo test 运行可执行文件时,也会设置这些环境变量。 然而,不鼓励这种用法,因为它将可执行文件与Cargo的执行环境关联在一起。 通常情况下,这些环境变量应该只在编译时用 env! 宏来检查。

rustc-dylib-link-arg 指令告诉Cargo将 -C link-arg=FLAG option 传递给编译器,但只在构建 cdylib 库目标时使用。 它的使用与平台高度相关。对于设置共享库的版本或运行时路径很有用。

cargo:warning=MESSAGE

warning 指令告诉Cargo在构建脚本运行完毕后显示一个警告。 警告只针对 path 依赖(也就是你在本地的那些依赖),所以比如在crates.iocrate中打印出来的警告,默认是不会发送的。 -vv "详细输出" 标志可以用来让Cargo显示所有crate的警告。

构建依赖

构建脚本也可以依赖其他基于Cargo的crate。 依赖是通过配置清单中的 build-dependencies 部分来声明的。

[build-dependencies]
cc = "1.0.46"

构建脚本 访问列在 dependenciesdev-dependencies 部分的依赖(它们还没有被构建!)。 另外,除非在 [dependencies] 表中明确添加,否则构建依赖对包本身不可用。

建议仔细考虑你添加的每个依赖,权衡对编译时间、许可、维护等的影响。 如果一个依赖是在构建依赖和正常依赖之间共享的,Cargo会尝试重用它。然而,这并不总是能用,例如在交叉编译时,所以要考虑到对编译时间的影响。

变化检测

当重新构建包时,Cargo不一定知道是否需要再次运行构建脚本。 默认情况下,它采取一种保守的方法,即如果包中的任意文件被改变(或由 excludeinclude 字段 控制的文件列表被改变),则总是重新运行构建脚本。 在大多数情况下,这不是一个好的选择,所以建议每个构建脚本至少发送一个 rerun-if 指令(如下所述)。 如果发送了这些指令,那么Cargo只会在给定值发生变化时重新运行脚本。 如果Cargo重新运行你自己的crate或依赖的构建脚本,而你又不知道为什么,请参阅FAQ中的 "为什么Cargo要重新构建我的代码?"

cargo:rerun-if-changed=PATH

rerun-if-changed 指令告诉Cargo在指定路径的文件发生变化时重新运行构建脚本。 目前,Cargo只使用文件系统最后修改的 "mtime" 时间戳来确定文件是否有变化。 它与内部缓存的构建脚本最后运行的时间戳进行比较。

如果路径指向一个目录,它将扫描整个目录的任何修改。

如果构建脚本在任何情况下都不需要重新运行,那么发送 cargo:rerun-if-changed=build.rs 防止其重新运行(否则,如果没有发送 rerun-if 指令,则默认为扫描整个包目录的变化)。 Cargo会自动处理脚本本身是否需要重新编译,当然,脚本在重新编译后会重新运行。否则,没有必要指定 build.rs

cargo:rerun-if-env-changed=NAME

rerun-if-env-changed 指令告诉Cargo,如果给定名称的环境变量值发生变化,则重新运行构建脚本。

注意,这里的环境变量是针对全局环境变量如 CC 之类的,对于Cargo设置的 TARGET 之类的环境变量没有必要使用这个。

package.links 键可以在 Cargo.toml 清单中设置,以声明该包与给定的本地库相链接。 这个清单键的目的是让Cargo了解包的本地依赖,以及提供在包构建脚本之间传递元数据的有条理的系统。

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

该清单表明,该包链接到 libfoo 本地库。 当使用 links 键时,包必须有一个构建脚本,而构建脚本应该使用 rustc-link-lib 指令 来链接该库。

主要的是,Cargo要求每个 links 值最多只能有一个包。 换句话说,禁止让两个包链接到同一个本地库。 这有助于防止crate之间的重复符号。注意,有一些 惯例 可以缓解这个问题。

比如,上文在输出格式中提到的,每个构建脚本可以以键值对的形式生成一组任意的元数据。 这些元数据被传递给 依赖的 包的构建脚本。 例如,如果包 bar 依赖于 foo ,那么如果 foo 生成 key=value 作为其构建脚本元数据的一部分,那么 bar 的构建脚本将有 DEP_FOO_KEY=value 的环境变量。 参见 "使用另一个 sys crate",以了解如何使用这个示例。

请注意,元数据只传递给直接依赖,而不传递给过渡依赖。

*-sys

一些链接到系统库的Cargo包有后缀为 -sys 的命名惯例。 任何名为 foo-sys 的包都应该提供两个主要功能:

  • 库crate应该链接到本地库 libfoo 。这通常会在从源代码构建之前探测当前系统中的 libfoo
  • 这个库应该为 libfoo 中的类型和函数提供 声明,而 不是 更高级别的抽象。

*-sys 包的集合为连接本地库提供了通用的依赖。 有了这个本地库相关包的惯例,带来许多好处:

  • foo-sys 的共同依赖简便了对于每个 links 值一个包的规则。
  • 其他 sys 包可以利用 DEP_NAME_KEY=value 环境变量的优势,更好地与其他包集成。参见 "使用另一个 sys crate" 例子。
  • 一个共同的依赖允许将逻辑集中在发现 libfoo 本身(或从源代码构建它)。
  • 这些依赖很容易被 覆盖

通常会有一个没有 -sys 后缀的配套包,在sys包的基础上提供安全的高级抽象。 例如,git2 cratelibgit2-sys crate 提供了高层接口。

覆盖构建脚本

如果配置清单中包含 links 键,那么Cargo支持用自定义库覆盖指定的构建脚本。 这一功能的目的是为了防止完全运行相关的构建脚本,而是提前提供元数据。

要覆盖一个构建脚本,在任意允许的 config.toml 文件中放置以下配置。

[target.x86_64-unknown-linux-gnu.foo]
rustc-link-lib = ["foo"]
rustc-link-search = ["/path/to/foo"]
rustc-flags = "-L /some/path"
rustc-cfg = ['key="value"']
rustc-env = {key = "value"}
rustc-cdylib-link-arg = ["…"]
metadata_key1 = "value"
metadata_key2 = "value"

在这种配置下,如果包声明它链接到 foo ,那么构建脚本将 被编译或运行,而将使用指定的元数据。

不应使用 warningrerun-if-changedrerun-if-env-changed 键,将忽略它们。

Jobserver

Cargo和 rustc 使用为GNU制作开发的 jobserver 协议 来协调进程间的并发。 它本质上是信号,控制同时运行的作业数量。 并发性可以用 --jobs 标志来设置,默认为逻辑CPU的数量。

每个构建脚本都从Cargo那里继承一个作业槽,并试图运行时只使用一个CPU。 如果脚本想并行使用更多的CPU,应该使用jobserver crate来与Cargo协调。

举例来说,cc crate 可以启用可选的 parallel 特性,它将使用jobserver协议尝试同时构建多个C文件。

构建脚本示例

下面小节是一些编写的构建脚本的举例。

通过 crates.io 中的crate,能找到一些构建脚本的常见功能。 查看 build-dependencies,看看有那些可用。 下面是一些流行的 crates1 示例:

  • bindgen — 自动生成Rust FFI与C库的绑定。
  • cc — 编译 C/C++/assembly 。
  • pkg-config — 使用 pkg-config 工具检测系统库。
  • cmake — 运行 cmake 构建工具来构建一个本地库。
  • autocfg, rustc_version, version_check — 这些crates提供了基于当前 rustc (如编译器的版本) 实现条件编译的方法。
1

这个列表并不是一种宣传,你需要评估依赖,选择更适合你的项目。

Code 生成

由于各种原因,有些Cargo包在编译前需要生成代码。 在这里,通过一个简单的例子,生成一个库,作为构建脚本的一部分调用。

首先,来看一下这个包的目录结构:

.
├── Cargo.toml
├── build.rs
└── src
    └── main.rs

1 directory, 3 files

可以看到,有一个 build.rs 构建脚本和 main.rs 二进制文件。这个包有一个基本的配置清单:

# Cargo.toml

[package]
name = "hello-from-generated-code"
version = "0.1.0"
edition = "2021"

来看看构建脚本里面有什么内容:

// build.rs

use std::env;
use std::fs;
use std::path::Path;

fn main() {
    let out_dir = env::var_os("OUT_DIR").unwrap();
    let dest_path = Path::new(&out_dir).join("hello.rs");
    fs::write(
        &dest_path,
        "pub fn message() -> &'static str {
            \"Hello, World!\"
        }
        "
    ).unwrap();
    println!("cargo:rerun-if-changed=build.rs");
}

这里有几个值得注意的地方:

  • 脚本使用 OUT_DIR 环境变量来发现输出文件的位置。 它可以使用进程的当前工作目录来寻找输入文件的位置,但在当前情况下我们没有任何输入文件。
  • 一般来说,构建脚本不应该修改 OUT_DIR 以外的任何文件。 乍一看,这似乎没什么问题,但当你使用这样的crate作为依赖时,却会产生问题,因为 implicit "隐式"不变性,即 .cargo/registry 中的源码应该是不可改变的。 cargo 在打包时不允许这样的脚本。
  • 这个脚本相对简单,因为它只是写生成了一个小的文件。 可以想象,还可以进行其他更多有趣的操作,例如从C头文件或其他语言定义中生成一个Rust模块。
  • rerun-if-changed instruction 告知Cargo,只有当构建脚本本身发生变化时才需要重新运行构建脚本。 如果没有这一行,Cargo会在包中的任何文件发生变化时自动运行构建脚本。 如果你的代码生成使用了一些输入文件,这里就应是你要打印每个文件列表的地方。

接下来,来看一下库本身:

// src/main.rs

include!(concat!(env!("OUT_DIR"), "/hello.rs"));

fn main() {
    println!("{}", message());
}

这就是真正奇妙的地方。该库使用rustc定义的 include! macroconcat!env! 宏相结合,将生成的文件(hello.rs)纳入crate的编译。

使用这里展示的结构,crate可以include来自构建脚本所生成的任意数量的文件。

构建本地库

有时有必要将一些本地C或C++代码作为包的一部分来构建。 这是利用构建脚本在Rust crate本身之前构建本地库的另一个很好的用例。 作为例子,我们将创建一个Rust库,调用C语言来打印 “Hello, World!” 。

像上面一样,来先看一下包的层次:

.
├── Cargo.toml
├── build.rs
└── src
    ├── hello.c
    └── main.rs

1 directory, 4 files

与上面的相似,以下是配置清单:

# Cargo.toml

[package]
name = "hello-world-from-c"
version = "0.1.0"
edition = "2021"

现在我们不打算使用任何构建依赖,先来看一下构建脚本:

// build.rs

use std::process::Command;
use std::env;
use std::path::Path;

fn main() {
    let out_dir = env::var("OUT_DIR").unwrap();

    // 注意,这种方法有一些缺点,下面的注解详细说明了如何提高这些命令的可移植性。
    Command::new("gcc").args(&["src/hello.c", "-c", "-fPIC", "-o"])
                       .arg(&format!("{}/hello.o", out_dir))
                       .status().unwrap();
    Command::new("ar").args(&["crus", "libhello.a", "hello.o"])
                      .current_dir(&Path::new(&out_dir))
                      .status().unwrap();

    println!("cargo:rustc-link-search=native={}", out_dir);
    println!("cargo:rustc-link-lib=static=hello");
    println!("cargo:rerun-if-changed=src/hello.c");
}

这个编译脚本首先将C文件编译成object文件(通过调用gcc),然后将这个object文件转换为静态库 (通过调用 ar )。 最后一步是反馈给Cargo本身,告知输出在 out_dir ,编译器应该通过 -l static=hello 标志将crate静态链接到 libhello.a

注意,这种硬编码的方法有很多缺点:

  • gcc 命令本身不能跨平台移植。例如,Windows平台不太可能有 gcc ,甚至不是所有Unix平台都可能有 gccar 命令也是类似的情况。
  • 这些命令没有考虑到交叉编译的问题。如果为Android这样的平台进行交叉编译,那么 gcc 不太可能产生ARM的可执行文件。

不过不用担心,这时 build-dependencies 条目会有帮助。Cargo生态系统有许多包,可以使这种任务变得更容易、便携、标准。 试试 crates.iocc crate 。首先,把它添加到 Cargo.tomlbuild-dependencies 中。

[build-dependencies]
cc = "1.0"

并重写构建脚本以使用这个crate:

// build.rs

fn main() {
    cc::Build::new()
        .file("src/hello.c")
        .compile("hello");
    println!("cargo:rerun-if-changed=src/hello.c");
}

cc crate 抽象了一系列对C代码构建的脚本需求:

  • 它调用适当的编译器 (MSVC用于Windows, gcc 用于MinGW, cc 用于Unix平台,等等)。
  • 它通过向正在使用的编译器传递适当的标志,将 TARGET 变量考虑在内。
  • 其他环境变量,如 OPT_LEVELDEBUG 等,都是自动处理的。
  • 标准输出和 OUT_DIR 位置也由 cc 库处理。

在这里,可以看到将尽可能多的功能移植到共同的构建依赖中,而不是在所有的构建脚本中重复逻辑的一些主要好处。

回到示例研究,来快速看一下 src 目录的内容:

// src/hello.c

#include <stdio.h>

void hello() {
    printf("Hello, World!\n");
}
// src/main.rs

// 注意没有 `#[link]` 属性。把链接内容的责任交给了构建脚本,而不是在源文件中硬编码。
extern { fn hello(); }

fn main() {
    unsafe { hello(); }
}

那么好了! 这样就完成了从Cargo包中使用构建脚本本身构建一些C代码的例子。 这也说明为什么在很多情况下,使用构建依赖是非常关键的,甚至更加简洁!

我们也看到这个简短的示例,说明构建脚本如何单纯将crate作为依赖,而不是在运行时将crate本身作为依赖。

链接到系统库

这个例子演示了如何链接系统库,以及如何支持使用构建脚本。

很多时候,Rust crate想要链接到系统上提供的本地库,绑定其功能,或者只是将其作为实现细节的一部分。 当涉及到以一种平台无关的方式执行时,这是相当细微的问题。 最好的办法是,如果可能的话,尽可能多地把这部分工作交给别人去做,让使用者更轻松。

对于这个例子,将创建一个与系统zlib库的绑定。 这是在大多数类Unix系统中常见的库,提供数据压缩。 这已经包含在 libz-sys crate 中了,但对于这个例子,我们将做一个极其简化的版本。请查看 libz源码 以了解完整的用例。

为了方便找到库的位置,我们将使用 pkg-config crate 。这个crate使用系统的 pkg-config 工具来发现库的信息。 它将自动告诉Cargo需要什么来链接这个库。这可能只能在安装了 pkg-config 的类Unix系统上工作。先从设置配置清单开始:

# Cargo.toml

[package]
name = "libz-sys"
version = "0.1.0"
edition = "2021"
links = "z"

[build-dependencies]
pkg-config = "0.3.16"

请注意,我们在 package 表中加入了 links 键。 这告知Cargo,正在链接到 libz 库。 请看 "使用另一个系统crate" 中的例子,可以利用这点。

构建脚本相当简单:

// build.rs

fn main() {
    pkg_config::Config::new().probe("zlib").unwrap();
    println!("cargo:rerun-if-changed=build.rs");
}

那么用基本的FFI绑定来完善这个例子:

// src/lib.rs

use std::os::raw::{c_uint, c_ulong};

extern "C" {
    pub fn crc32(crc: c_ulong, buf: *const u8, len: c_uint) -> c_ulong;
}

#[test]
fn test_crc32() {
    let s = "hello";
    unsafe {
        assert_eq!(crc32(0, s.as_ptr(), s.len() as c_uint), 0x3610a686);
    }
}

运行 cargo build -vv 来查看构建脚本的输出。在已经安装了 libz 的系统上,可能看起来像这样:

[libz-sys 0.1.0] cargo:rustc-link-search=native=/usr/lib
[libz-sys 0.1.0] cargo:rustc-link-lib=z
[libz-sys 0.1.0] cargo:rerun-if-changed=build.rs

很好! pkg-config 做了所有寻找库的工作,并告知Cargo它的位置。

包包含库的源代码,如果在系统中找不到它,或者设置了某个特性或环境变量,就静态地构建它,这种情况并不罕见。 例如,实际的 libz-sys crate 检查环境变量 LIBZ_SYS_STATICstatic 特性,从源码构建而不是使用系统库。 请查看 the source 以了解更完整的例子。

使用另一个 sys crate

当使用 links 键时,crates可以设置metadata,其他依赖它的crates可以读取这些元数据。这提供了一种在crate之间通信的机制。 在这个例子中,我们将创建一个C语言库,利用实际的 libz-sys crate 中的zlib。

如果你有一个依赖于zlib的C库,你可以利用 libz-sys crate 来自动查找或构建它。这对于跨平台支持非常有用,比如在通常不安装zlib的Windows。 libz-sys 设置 include 元数据 ,告诉其他包在哪里可以找到zlib的头文件。 我们的构建脚本可以通过 DEP_Z_INCLUDE 环境变量读取该元数据。 下面是一个例子:

# Cargo.toml

[package]
name = "zuser"
version = "0.1.0"
edition = "2021"

[dependencies]
libz-sys = "1.0.25"

[build-dependencies]
cc = "1.0.46"

这里我们包含了 libz-sys ,这将确保在最终库中只有一个 libz ,并允许我们从构建脚本中访问它:

// build.rs

fn main() {
    let mut cfg = cc::Build::new();
    cfg.file("src/zuser.c");
    if let Some(include) = std::env::var_os("DEP_Z_INCLUDE") {
        cfg.include(include);
    }
    cfg.compile("zuser");
    println!("cargo:rerun-if-changed=src/zuser.c");
}

有了 libz-sys 做所有繁重的工作,C源码现在可以include zlib头文件,它应能找到这个头文件,即使在还没有安装它的系统上。

// src/zuser.c

#include "zlib.h"

// … 使用zlib的其余代码。

条件编译

构建脚本可以发出 rustc-cfg 指令 ,这些指令可以启用在编译时可以检查的条件。 在这个例子中,我们将看看 openssl crate 如何使用它来支持多个版本的OpenSSL库。

openssl-sys crate 实现了OpenSSL库的构建和链接。 它支持多种不同的实现方式 (如LibreSSL) 和多个版本。 它使用了 links 键,这样就可以向其他构建脚本传递信息。 它传递的信息之一是 version_number 键,这是检测到的OpenSSL的版本。 构建脚本中的代码看起来 像这样:

println!("cargo:version_number={:x}", openssl_version);

这条指令使 DEP_OPENSSL_VERSION_NUMBER 环境变量在任何直接依赖 openssl-sys 的crate中被设置。

openssl crate 提供了更高层次的接口,指定 openssl-sys 为依赖项。 openssl 构建脚本可以通过 DEP_OPENSSL_VERSION_NUMBER 环境变量读取由 openssl-sys 构建脚本生成的版本信息。 它用这个来生成一些 cfg values

// (portion of build.rs)

if let Ok(version) = env::var("DEP_OPENSSL_VERSION_NUMBER") {
    let version = u64::from_str_radix(&version, 16).unwrap();

    if version >= 0x1_00_01_00_0 {
        println!("cargo:rustc-cfg=ossl101");
    }
    if version >= 0x1_00_02_00_0 {
        println!("cargo:rustc-cfg=ossl102");
    }
    if version >= 0x1_01_00_00_0 {
        println!("cargo:rustc-cfg=ossl110");
    }
    if version >= 0x1_01_00_07_0 {
        println!("cargo:rustc-cfg=ossl110g");
    }
    if version >= 0x1_01_01_00_0 {
        println!("cargo:rustc-cfg=ossl111");
    }
}

这些 cfg 值可以与 cfg attributecfg macro一起使用,从而有条件地include代码。 例如,SHA3支持是在OpenSSL 1.1.1中添加的,所以对于旧版本它被 条件排除

// (portion of openssl crate)

#[cfg(ossl111)]
pub fn sha3_224() -> MessageDigest {
    unsafe { MessageDigest(ffi::EVP_sha3_224()) }
}

当然,使用这种方法时应该小心,因为它使生成的二进制文件更加依赖于构建环境。 在这个例子中,如果二进制文件被分发到另一个系统,它可能没有完全相同的共享库,这可能导致问题。

发布到crates.io

你想与世界分享一个库,就该把它发布到 crates.io 上,发布crate指的是将特定版本上传到crates.io上托管。

在发布crate时要小心,发布将是永久性的,一旦发布就永远不能覆盖该版本,也不能删除代码。然后,对可发布的版本数量没有限制。

在你第一次发布之前

首先,你需要一个crates.io的账户来获取API token。要做到这一点,请 访问主页 并通过GitHub账户登录(目前需要)。 之后,访问你的 账户设置 页面并运行 cargo login 命令。

$ cargo login

然后在提示中输入指定的Token。

please paste the API Token found on https://crates.io/me below
abcdefghijklmnopqrstuvwxyz012345

这个命令会将你的API token告知Cargo,并将其保存在你本地的 ~/.cargo/credentials.toml 中。 请注意,这个token是私密的,不应该与其他人分享。如果因某些原因泄露,你应该立即撤销它。

在发布新crate之前

[cates.io]上的crate名称是以先到先得的方式分配的。一旦一个crate的名字被占用,就不能用于其他crate。

检查 Cargo.toml 中的 你能指定的元数据 ,让使用者更容易发现你 crate! 在发布之前,请确保已经填写了以下字段:

尽管不是必须的,但包含相关 keywordscategories 信息会更好。

如果你要发布库,可能还需要参考一下 Rust API 指南

打包crate

下一步是将你的crate打包并上传到 crates.io 。这时可以使用 cargo publish 子命令。 这个命令会执行以下步骤:

  1. 对包进行一些验证检查。
  2. 将源代码压缩成 .crate 文件。
  3. .crate 文件解压缩到临时目录中,并验证它是否可以编译。
  4. .crate 文件上传到crates.io
  5. 注册中心将在添加之前对上传的包进行一些额外的检查。

建议你首先运行 cargo publish --dry-run (或cargo package) , 以确保在发布前没有任何警告或错误。这将执行上面列出的前三个步骤。

$ cargo publish --dry-run

你可以在 target/package 目录下检查生成的 .crate 文件。 crates.io目前对 .crate 文件有10MB的大小限制。你需要检查 .crate 文件的大小, 以确保没有意外地打包构建包所不需要的大量资源,如测试数据、网站文档或代码生成。 你可以用下面的命令来检查包含了哪些文件:

$ cargo package --list

Cargo在打包时将自动忽略您的版本控制系统所忽略的文件,如果想额外指定一组要忽略的文件, 可以在配置清单中使用 exclude

[package]
# ...
exclude = [
    "public/assets/*",
    "videos/*",
]

如果你想明确地列出要包括的文件,Cargo也支持 include 键,如果设置了这个键,就可以覆盖 exclude 键。

[package]
# ...
include = [
    "**/*.rs",
    "Cargo.toml",
]

上传crate

当你准备好发布时,使用 cargo publish 命令上传至 crates.io :

$ cargo publish

这样,你现在已经发布了第一个 crate !

发布现有crate的新版本

为了发布新版本,请更改 Cargo.toml 清单中指定的 version。 请记住 语义化版本规范,该规范提供了关于什么是兼容性改变的指南。 然后如上所述运行 cargo publish 来上传新版本。

管理基于crate.io的crate

crate的管理主要是通过命令行 cargo 工具而不是 crates.io 网络界面来完成。 因此,有几个子命令来管理crate。

cargo yank

偶尔会出现这样的情况:你发布的版本由于某种原因(语法错误、忘记包含某个文件等),实际上已经坏了。 对于这样的情况,Cargo支持 "yank" crate 的一个版本。

$ cargo yank --version 1.0.1
$ cargo yank --version 1.0.1 --undo

yank 不会 删除任何代码。这个功能不能删除意外上传的秘密。如果发生这种情况,请立即重置这些秘密。

被yank版本的语义是,不能针对该版本创建新的依赖,但已有的依赖继续使用。 crates.io的主要目标之一是作为一个不随时间变化的永久档案,允许删除一个版本将违背这一目标。 从本质上讲,yank 意味着所有带有 Cargo.lock 的包都不会损坏,而未来生成的任何 Cargo.lock 文件都不会列出被yank的版本。

cargo owner

crate通常是由多人开发的,或者主要的维护者可能会随着时间的推移而改变! crate的所有者是唯一允许发布crate新版本的人,其所有者可以指定其他所有者。

$ cargo owner --add github-handle
$ cargo owner --remove github-handle
$ cargo owner --add github:rust-lang:owners
$ cargo owner --remove github:rust-lang:owners

给予这些命令的所有者ID必须是GitHub用户名或GitHub团队。

如果一个用户名被赋予 --add ,该用户就会被邀请为 "命名" 的所有者,拥有对该crate的全部权利。 除了能够发布或取消crate的版本外,他们还能够添加或删除所有者,包括 使他们成为所有者的所有者。 不用说,你不应该把不完全信任的人变成指定的所有者。为了成为指定的所有者,用户必须在之前登录过[cates.io]。

如果一个团队的名字被赋予 --add ,该团队被邀请为 "团队" 所有者,对crate的权利受到限制。 虽然他们有权限发布或删除crate的版本,但他们没有能力添加或删除所有者。 除了更方便管理所有者组之外,团队也更安全一点,会防止所有者变得恶意。

目前团队的语法是 github:org:team (见上面的例子)。 为了邀请一个团队成为所有者,其必须是该团队的成员。 在删除一个团队的所有者时没有这种限制。

GitHub 许可

团队成员资格不是GitHub提供的简单的公共访问,你在与他们合作时很可能会遇到以下信息:

看起来你没有权限从GitHub查询一个必要的属性来完成这个请求。你可能需要在 crates.io 上重新认证,以授予读取 GitHub org 会员资格的权限。

大体会说:"你试图查询一个团队,但五级成员访问控制拒绝了这一点" 。 这并不夸张。GitHub对团队访问控制的支持是企业级的。

最有可能的原因是,你最后一次登录是在这个功能添加之前。我们最初在认证用户时没有要求GitHub提供权限, 因为我们除了登录用户外,实际上没有使用过用户的令牌。然而,为了查询团队成员身份,我们现在需要 read:org

你可以自由地拒绝这个域,在进入团队之前的一切工作都将继续。 然而,你将无法作为所有者添加一个团队,或作为团队所有者发布crate。如果你试图这样做,会得到上面的错误。 如果你试图发布一个根本不属于你的crate,但恰好有一个团队,也可能看到这个错误。

如果你改变了主意,或者只是不确定crates.io是否有足够的权限, 你可以随时去https://crates.io/重新认证,如果crates.io没有所有它想获得的域,会提示你的权限。

查询GitHub的另一个障碍是,该组织可能主动拒绝第三方访问。要检查这一点,你可以去:

https://github.com/organizations/:org/settings/oauth_application_policy

其中 :org 是组织的名称(例如,rust-lang)。你可能会看到类似的情形:

组织访问控制

在这里,你可以选择从组织黑名单中明确删除 crates.io , 或者直接按下 "移除限制" 按钮,允许所有第三方应用程序访问这些数据。

另外,当crates.io请求 "read:org" 域时,你可以通过按下其名称旁边的 "Grant Access" 按钮,明确地将crates.io查询有关的组织列为白名单。

认证访问控制

解决GitHub团队访问错误

当试图添加GitHub团队作为 crate 所有者时,你可能会看到类似的错误:

error: failed to invite owners to crate <crate_name>: api errors (status 200 OK): could not find the github team org/repo

在这种情况下,你应该去the GitHub Application settings page,检查crates.io是否被列在 "授权的OAuth应用程序" 标签中。 如果没有,你应该去https://crates.io/并授权它。 然后回到GitHub上的应用设置页面,点击列表中的crates.io应用,确保你或你的组织被列在 "组织访问" 列表中,并打上绿色的勾。 如果有标注 "Grant" 或 "Request" 的按钮,你应该授予权限或要求组织所有者这样做。

包ID规格

包ID规格

Cargo的子命令经常需要引用依赖图中的某个特定包来进行各种操作,如更新、清理、构建等。 为了解决这个问题,Cargo支持 包ID规格 。规格是一个字符串,用来唯一地指代包图中的一个包。

该规格可以是完整标准的,例如 https://github.com/rust-lang/crates.io-index#regex@1.4.3 ,也可以是缩写的,例如 regex 。 缩写的形式可以使用,只要它在依赖图中唯一地标识了一个包。如果有歧义,可以添加额外的限定词来使其唯一。 例如,如果图中有两个版本的 regex 包,那么可以用一个版本来限定,使其唯一,如 regex@1.4.3

规格语法

包Id规格形式的语法是:

spec := pkgname
       | proto "://" hostname-and-path [ "#" ( pkgname | semver ) ]
pkgname := name [ ("@" | ":" ) semver ]

proto := "http" | "git" | ...

这里,方括号表示内容是可选的。

URL形式可用于git依赖,或区分来自不同来源的包,如不同的注册中心。

示例规格

以下是对 crates.io 上的 regex 包的引用:

SpecNameVersion
regexregex*
regex@1.4.3regex1.4.3
https://github.com/rust-lang/crates.io-index#regexregex*
https://github.com/rust-lang/crates.io-index#regex@1.4.3regex1.4.3

下面是几个不同的git依赖的规格例子:

SpecNameVersion
https://github.com/rust-lang/cargo#0.52.0cargo0.52.0
https://github.com/rust-lang/cargo#cargo-platform@0.1.2cargo-platform0.1.2
ssh://git@github.com/rust-lang/regex.git#regex@1.4.3regex1.4.3

文件系统上的本地包可以使用 file:// URL来引用它们:

SpecNameVersion
file:///path/to/my/project/foofoo*
file:///path/to/my/project/foo#1.1.8foo1.1.8

规格简略

这样做的目的是为了使在依赖图中引用包的语法既简明又详尽。模糊的引用可能指的是一个或多个包。 如果有一个以上的包可以用相同的规格引用,大多数命令会产生一个错误。

源替换

这篇文档是关于替换 crate 索引的。你可以在本文档的 overriding dependencies 部分阅读关于覆盖依赖的内容。

是包含可以作为包的依赖项的crate的提供者。 Cargo支持 用一个源替换另一个源的能力 ,从而有以下的策略:

  • 拓展 - 可以自定义源,代表本地文件系统上的crate。这些源是它们所替换源的子集,如果有必要,可以被检查引到包中。

  • 镜像 - 源被替换成一个相等的版本,作为crates.io的缓存。

Cargo有一个关于源替换的核心假设,即两个源的源代码是完全一样的。 请注意,这也意味着替换源不允许有原始源中没有的crate。

因此,源替换并不适合于修补依赖或私有注册中心的情况。 Cargo支持通过使用 [patch]来修补依赖,对私有注册中心的支持在注册中心章节中描述。

当使用源替换时,运行像 cargo publish 这样需要联系注册中心的命令需要通过 --registry 选项。这有助于避免在联系哪个注册中心方面出现歧义,并将使用指定注册中心的认证令牌。

配置

替换源的配置是通过 .cargo/config.toml 完成的,全部可用的键有:

# `source` 表是存储所有与源替换有关的键的位置。
[source]

# 在 `source` 表下有一些其他的表,它们的键是相关来源的名称。
# 例如,这一节定义了一个新的源文件,叫做 `my-vendor-source` ,它来自一个位于 `vendor` 的目录,相对于包含这个 `.cargo/config.toml` 文件的目录而言。
[source.my-vendor-source]
directory = "vendor"

# crates.io的默认源代码以 "crates-io" 的名称提供,这里我们使用 `replace-with` 键来表示它被我们上面的源替换。
#
# `replace-with` 键也可以引用在 `[registries]` 表中定义的其他注册中心名称。
[source.crates-io]
replace-with = "my-vendor-source"

# 每个源都有自己的表,其中键是源的名称。
[source.the-source-name]

# 表示 `the-source-name` 替换为 `another-source` ,定义在其他地方
replace-with = "another-source"

# 可以指定几种源(下文有更详细的描述):
registry = "https://example.com/path/to/index"
local-registry = "path/to/registry"
directory = "path/to/vendor"

# Git源也可以选择指定一个branch/tag/rev
git = "https://example.com/path/to/repo"
# branch = "master"
# tag = "v1.0.1"
# rev = "313f44e8"

注册中心源

"注册中心源" 是与crates.io 相同的。 也就是说,它有一个在git仓库中提供的索引,与 crates.io index 的格式一致。 然后,该仓库表明从哪里下载crates的配置。

目前还没有一个已经可用的项目来建立crates.io的镜像。但请继续关注!

本地注册中心源

"本地注册中心源" 旨在成为另一个注册中心源的子集,但在本地文件系统上可用(又称拓展)。 本地注册中心是提前下载的,通常与 Cargo.lock 同步,并由一组 *.crate 文件和一个索引组成,就像普通注册中心一样。

管理和创建本地注册中心源的主要方式是通过 cargo-local-registry 子命令, crates.io上有,可以用 cargo install cargo-local-registry 来安装。

本地注册中心包含在一个目录中,并包含一些从crates.io下载的 *.crate 文件,以及 index 目录,其格式与 crates.io-index 项目相同 (只填充存在的crates的条目)。

目录源

"目录源" 类似于本地注册中心源,它包含了一些在本地文件系统上可用的crate,适合于拓展依赖。目录源主要由 cargo vendor 子命令管理。

但目录源与本地注册中心不同,它们包含 *.crate 文件的解压版本,在某些情况下更适合将所有东西都检查引入源控制中。 目录源只是一个包含其他一些目录的目录,这些目录包含了crate的源代码(*.crate 文件的解压版本)。目前对每个目录的名称没有限制。

目录源中的每个crate也有一个相关的元数据文件,表明crate中每个文件的校验和,以防止意外的修改。

插件

Cargo的目标之一是能与第三方工具简单集成,如IDE和其他构建系统。为了使集成更容易,Cargo有几个方式:

  • cargo metadata 命令,以JSON格式输出包结构和依赖信息。

  • --message-format 标志,用于输出关于特定构建的信息,以及

  • 支持自定义子命令。

关于包结构信息

你可以使用 cargo metadata 命令来获取包结构和依赖的信息。有关输出格式的详细信息,请参见 cargo metadata 文档。

该格式是稳定的,有相应版本。当调用 cargo metadata 时,你应该明确传递 --format-version 标志以避免向前不兼容的风险。

如果你使用的是Rust,可以使用 cargo_metadata crate来解析输出。

JSON 消息

当传递 ---message-format=json 时,Cargo会在构建时输出以下信息:

  • 编译器错误和警告。

  • 产生的制品。

  • 构建脚本的结果 (例如,本地依赖)。

在标准输出中,按行的JSON对象格式化输出。 reason 字段区分不同种类的信息。

可以用 --message-format 选项带有额外的格式化值,改变JSON信息的计算和显示方式。 更多细节参阅 build command documentation 中对 --message-format 选项的描述。

如果你使用的是Rust,可以使用 cargo_metadata crate来解析这些信息。

编译消息

"compiler-message" 消息包括来自编译器的输出,如警告和错误。关于 rustc 的消息格式,请参阅 rustc JSON 章节,其信息包含到以下结构中:

{
    /* "reason" 表示信息的种类。*/
    "reason": "compiler-message",
    /* 包的ID,是指代包的唯一标识。 */
    "package_id": "my-package 0.1.0 (path+file:///path/to/my-package)",
    /* 包配置清单的绝对路径。 */
    "manifest_path": "/path/to/my-package/Cargo.toml",
    /* 产生该消息的Cargo目标 (lib、bin、example等)。 */
    "target": {
        /* 目标种类数组。
           - lib目标列出配置清单中的 `cate-type` 值,如 "lib"、"rlib"、"dylib"、"proc-macro" 等(默认["lib"])。
           - 二进制是 ["bin"]
           - 实例是 ["example"]
           - 集成测试是 ["test"]
           - 性能测试是 ["bench"]
           - 构建脚本是 ["custom-build"]
        */
        "kind": [
            "lib"
        ],
        /* crate类型数组。
           - lib和示例库列出配置清单中的 `crate-type` 值,如 "lib"、"rlib"、"dylib"、"proc-macro" 等(默认为["lib"])。
           - 所有其他目标类型是 ["bin"]
        */
        "crate_types": [
            "lib"
        ],
        /* 目标名称。 */
        "name": "my-package",
        /* 目标的根源文件的绝对路径。 */
        "src_path": "/path/to/my-package/src/lib.rs",
        /* 目标的Rust版本。默认为包版本。 */
        "edition": "2018",
        /* 所需特性的数组。如果没有设置必要的特性,则不包含此属性。 */
        "required-features": ["feat1"],
        /* 该目标是否启用了文档测试,以及该目标是否与文档测试兼容。 */
        "doctest": true
    },
    /* 由编译器发出的信息。 参阅 https://doc.rust-lang.org/rustc/json.html 。 */
    "message": {
        /* ... */
    }
}

制品消息

对于每一个编译步骤,都会发出 "compiler-artifact" 消息,其结构如下:

{
    /* "reason" 表示信息的种类。 */
    "reason": "compiler-artifact",
    /* 包的ID,是指代包的唯一标识。 */
    "package_id": "my-package 0.1.0 (path+file:///path/to/my-package)",
    /* 包配置清单的绝对路径。 */
    "manifest_path": "/path/to/my-package/Cargo.toml",
    /* 产生制品的Cargo目标(lib、bin、example等等)。详见上面 `compiler-message` 的定义。 */
    "target": {
        "kind": [
            "lib"
        ],
        "crate_types": [
            "lib"
        ],
        "name": "my-package",
        "src_path": "/path/to/my-package/src/lib.rs",
        "edition": "2018",
        "doctest": true,
        "test": true
    },
    /* 该简介表明使用了哪些编译器设置。 */
    "profile": {
        /* 优化级别。 */
        "opt_level": "0",
        /* 调试级别,是0、1或2的整数。如果 "null",它意味着rustc的默认值为0。 */
        "debuginfo": 2,
        /* 是否启用了调试断言。 */
        "debug_assertions": true,
        /* 是否启用了溢出检查。 */
        "overflow_checks": true,
        /* 是否使用 `--test` 标志。*/
        "test": false
    },
    /* 启用特性数组。 */
    "features": ["feat1", "feat2"],
    /* 该步骤产生的文件的数组。*/
    "filenames": [
        "/path/to/my-package/target/debug/libmy_package.rlib",
        "/path/to/my-package/target/debug/deps/libmy_package-be9f3faac0a26ef0.rmeta"
    ],
    /* 创建的可执行文件的路径的字符串,如果该步骤没有生成可执行文件,则为空。 */
    "executable": null,
    /* 这个步骤是否被实际执行。当 `true` 时,这意味着预先存在的制品是最新的,并且 `rustc` 没有被执行。当 `false` 时,这意味着运行 `rustc` 以生成制品。 */
    "fresh": true
}

构建脚本输出

"build-script-executed" 消息包括构建脚本的解析输出。注意,即使构建脚本没有运行,也会发出这个消息; 它将显示之前缓存的值。关于构建脚本输出的更多细节可以在 构建脚本章节 中找到。

{
    /* "reason" 表示信息的种类。 */
    "reason": "build-script-executed",
    /* 包的ID,是指代包的唯一标识。 */
    "package_id": "my-package 0.1.0 (path+file:///path/to/my-package)",
    /* 要链接的库的数组,如 `cargo:rustc-link-lib` 指令所指示。注意,这可能包括字符串中的 "KIND=" 前缀,其中KIND是库的种类。 */
    "linked_libs": ["foo", "static=bar"],
    /* 包含在库搜索路径中的路径数组,如 `cargo:rustc-link-search` 指令所指示。注意,这可能包括字符串中的 "KIND=" 前缀,其中KIND是库的种类。 */
    "linked_paths": ["/some/path", "native=/another/path"],
    /* 要启用的cfg值数组,如 `cargo:rustc-cfg` 指令所示。 */
    "cfgs": ["cfg1", "cfg2=\"string\""],
    /* 要设置的环境变量的 [KEY, VALUE] 数组,如 `cargo:rustc-env` 指令所示。 */
    "env": [
        ["SOME_KEY", "some value"],
        ["ANOTHER_KEY", "another value"]
    ],
    /* 一个绝对路径,在编译当前包时作为 `OUT_DIR` 环境变量的值。 */
    "out_dir": "/some/path/in/target/dir"
}

构建完成

构建结束后会发出 "build-finished" 消息。

{
    /* "reason" 表示信息的种类。 */
    "reason": "build-finished",
    /* 构建是否成功完成。 */
    "success": true,
}

这条信息对工具来说很有帮助,可以知道何时停止读取JSON信息。 诸如 cargo testcargo run 之类的命令在构建完成后可能会产生额外的输出。 这条消息让工具知道Cargo不会产生额外的JSON消息,但之后可能会有额外的输出(比如 cargo run 执行的程序产生的输出)。

注意: 对测试的JSON输出有实验性的每日支持,所以如果启用了该功能,额外的测试专用JSON消息可能会在 "build-finished" 消息之后。

自定义子命令

Cargo被设计成可以扩展新的子命令,而不需要修改Cargo本身。 这是通过将 cargo (?<command>[^ ]+) 形式的调用转换成插件 cargo-${command} 的调用来实现的。 该插件必须存在于用户的 $PATH 目录中。

当Cargo调用一个自定义子命令时,子命令的第一个参数将是自定义子命令的文件名,像往常一样。 第二个参数将是子命令名称本身。例如,调用 "cargo-${command}" 时,第二个参数将是 "${command}" 。 命令行上的任何其他参数将被转发,不做任何改变。

Cargo也可以用 cargo help ${command} 显示自定义子命令的帮助输出。 如果子命令的第三个参数是 --help ,Cargo会假定该子命令会打印帮助信息。 因此,cargo help ${command} 会调用 cargo-${command} ${command} --help

自定义子命令可以使用 CARGO 环境变量来回调Cargo。 另外,它也可以作为一个库链接到 cargo crate ,但这种方法有缺点。

  • 作为一个库,Cargo是不稳定的:API可能会改变而未淘汰。
  • 链接的Cargo库的版本可能与Cargo二进制文件不同。

相反,我们鼓励使用CLI接口来驱动Cargo。 cargo metadata 命令可以用来获取当前项目的信息( cargo_metadata crate为该命令提供了Rust接口)。

注册中心

Cargo 安装 crate 并从 "注册中心" 中获取依赖。 默认的注册中心是 [crates.io] 。注册中心包含一个 "索引" ,其中包含可搜索的可用 crate 的列表 。 注册中心也可以提供网络 API ,支持通过 Cargo 直接发布新的 crate 。

注意: 如果你对镜像或拓展现有的注册中心感兴趣,请查看 源替换

如果你想搭建注册中心服务器,请参阅 运行注册中心 了解更多关于Cargo和注册中心之间协议的细节。

使用备用注册中心

要使用 [crates.io] 以外的注册中心,必须将注册中心的名称和URL索引添加到 .cargo/config.toml fileregistries 表中每个键对应一个注册中心,例如:

[registries]
my-registry = { index = "https://my-intranet:8080/git/index" }

index 键应该是一个指向具有注册中心索引的git仓库的URL。 通过指定 registry 键和 Cargo.toml 中的依赖中的注册中心名称, crate 可以依赖不同注册中心的 crate。

# Sample Cargo.toml
[package]
name = "my-project"
version = "0.1.0"
edition = "2021"

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

就像大多数配置一样,索引可以用环境变量而不是配置文件来指定。 例如,设置以下环境变量将与定义配置文件完成相同的事情:

CARGO_REGISTRIES_MY_REGISTRY_INDEX=https://my-intranet:8080/git/index

注意: [crates.io] 不接受依赖其他注册中心的crate的包。

发布到备用注册中心

如果注册中心支持 Web API 访问,那么包可以直接从 Cargo 发布到注册中心。 Cargo 的一些命令,如 cargo publish ,可以通过 --registry 命令行标志来指示使用哪个注册中心。 例如,要发布当前目录下的包:

  1. cargo login --registry=my-registry

    这只需要执行一次。需要输入从注册中心网站获得的私密API令牌。 另外,令牌可以通过 --token 命令行标志直接传递给 publish 命令,或者用注册中心的名称作为环境变量,如CARGO_REGISTRIES_MY_REGISTRY_TOKEN

  2. cargo publish --registry=my-registry

可以在 .cargo/config.toml 中用 registry.default 键设置默认注册中心,而不必总是传递 "--registry" 命令行选项。比如说:

[registry]
default = "my-registry"

Cargo.toml 配置清单中设置 package.publish 键,可以限制包发布到哪些注册中心。这可以防止不小心将闭源包发布到 [crates.io] 。该值可以是一个注册中心名称的列表,例如:

[package]
# ...
publish = ["my-registry"]

publish 值可以是 false ,以限制所有发布,这与空列表相同。

cargo login 存储的认证信息被保存在Cargo主目录 (默认 $HOME/.cargo) 下的 credentials.toml 文件中。 对于每个注册中心对应一个单独的表,例如。

[registries.my-registry]
token = "854DvwSlUwEHtIo3kWy6x7UCPKHfzCmy"

运行注册中心

最小的注册中心可以通过拥有包含索引的git仓库和包含由 cargo package 创建的压缩的 .crate 文件的服务器来实现。 用户不能使用 Cargo 来发布内容,但这对于封闭环境来说可能已经足够了。索引格式在 Registry Index 中描述。

支持发布的完整功能的注册中心还需要有符合Cargo使用的API的Web API服务。该网络API在 Registry Web API 中描述。

商业和社区项目可用于建立和运行注册中心。参见 https://github.com/rust-lang/cargo/wiki/Third-party-registries,了解可用的列表。

索引格式

下面定义了索引的格式。有时会增加一些新的功能,这些新功能将从新版本的 Cargo 开始识别。 旧版本的Cargo可能无法使用利用了新特性的包。而旧版本的包的格式不应改变,旧版本Cargo应能使用它们。

索引存储在git仓库中,这样Cargo就可以有效地获取索引的增量更新。 仓库的根位置有一个名为 "config.json" 的文件,包含Cargo访问注册中心时使用的JSON信息。 这是一个[crates.io]配置文件的例子,看起来像:

{
    "dl": "https://crates.io/api/v1/crates",
    "api": "https://crates.io"
}

键是:

  • dl: 这是在索引中列出的下载crates的URL。该值可能有以下标记,这些标记将被替换成其相应的值:

    • {crate}: crate 的名称。
    • {version}: crate 的版本。
    • {prefix}: 从 crate 名称计算出来的目录前缀。例如,名为 cargo 的 crate 的前缀是 ca/rg 。详见下文。
    • {lowerprefix}: {prefix} 的小写变体。
    • {sha256-checksum}: crate 的sha256校验和。

    如果没有任何标记,那么结尾将附加值 /{crate}/{version}/download

  • api: 这是web API的基本URL。这个键是可选的,但如果没有指定,cargo publish 等命令将无法工作。下面将介绍web API。

下载端应发送所请求包的 .crate 文件。 Cargo支持https、http和文件URL、HTTP重定向、HTTP1和HTTP2。 TLS支持的具体细节取决于Cargo所运行的平台、Cargo的版本以及它的编译方式。

索引库的其余部分包含每个包的一个文件,其中文件名是小写包的名称。 包的每个版本在文件中都有一个单独的行。这些文件被组织在分层级的目录中。

  • 具有1个字符名称的包被放置在一个名为 1 的目录中。
  • 具有2个字符名称的包被放置在一个名为 2 的目录中。
  • 名称为3个字符的包被放置在 3/{first-character} 目录下,其中 {first-character} 是包名称的第一个字符。
  • 所有其他包都存储在名为 {first-two}/{second-two} 的目录中,其中顶部目录是包名称的前两个字符,下一个子目录是包名称的第三和第四个字符。例如,cargo 将被存储在一个名为 ca/rg/cargo的文件中。

注意: 尽管索引文件名是小写的,但 Cargo.toml 中包含包名的字段和索引JSON数据是区分大小写的,可能包含大写和小写字符。

上面的目录名是根据转换为小写的包名计算的;它由标记 {lowerprefix} 表示。当使用原始包名而不进行大小写转换时,产生的目录名由标记 {prefix} 表示。 例如,MyCrate 包的 {prefix}My/Cr{lowerprefix}my/cr 。一般来说,推荐使用 {prefix} 而不是 {lowerprefix} ,但每种选择都有优点和缺点。在不区分大小写的文件系统中使用 {prefix} 会导致(无害但不优雅的)目录别名。 例如, crateCrateTwo{prefix} 值分别为 cr/atCr/at ;这些在Unix机器上是不同的,但在Windows上却别名为同一个目录。 使用正常大小写的目录可以避免别名,但在对大小写敏感的文件系统中,很难支持缺乏 {prefix}/{lowerprefix} 的旧版本的Cargo。 例如,nginx的重写规则可以很容易地构建 {prefix} ,但不能进行大小写转换以构建 {lowerprefix}

注册中心应该考虑对添加到他们索引中的包名称实施限制。 Cargo本身允许名字中含有任何 [字母数字][alphanumeric] 、 -_ 字符。 [crates.io] 添加了自己的限制,包括以下内容:

  • 只允许ASCII字符。
  • 只有字母数字、 -_ 字符。
  • 第一个字符必须是英文字母。
  • 对大小写不敏感冲突检测。
  • 防止 -_ 的差异。
  • 在特定长度下(最大64)。
  • 抛弃保留名称,如Windows的特殊文件名,如 "nul" 。

注册中心应考虑纳入类似的限制,并考虑安全问题,如 IDN同源词攻击 以及 UTR36UTS39中的其他考虑。

包文件中的每一行都包含一个JSON对象,描述包的发布版本。下面是一个优雅的例子,其中有注释解释了条目的格式。

{
    // 包的名称。
    // 这必须只包含字母数字、 `-` 或 `_` 字符。
    "name": "foo",
    // 这一行描述包的版本。
    // 根据语义化版本 2.0.0 标准,这必须是一个有效的版本号,参考网址 https://semver.org/。
    "vers": "0.1.0",
    // 包的直接依赖的数组。
    "deps": [
        {
            // 依赖的名称。
            // 如果依赖从源包名称中重命名,这就是新的名称。源包的名称被保存在 `package` 字段中。
            "name": "rand",
            // 依赖的语义化版本要求。
            // 这必须是一个有效的版本要求,定义在https://doc.rust-lang.org/cargo/reference/specifying-dependencies.html。
            "req": "^0.6",
            // 该依赖启用的特性数组(字符串)。
            "features": ["i128_support"],
            // 布尔值,表示这是否是一个可选的依赖。
            "optional": false,
            // 是否启用默认特性的布尔值。
            "default_features": true,
            // 依赖的目标平台。
            // 如果不是目标依赖,则为空。
            // 否则,就是一个字符串,如 "cfg(windows)" 。
            "target": null,
            // 依赖性的种类。
            // "dev", "build", or "normal".
            // 注意: 这是必需的字段,但由于执行错误,crates.io索引中存在少量的条目,其中的 `kind` 字段缺失或为空。
            "kind": "normal",
            // 该依赖所在的注册中心索引的URL,是字符串。如果没有指定或为空,则假定该依赖在当前注册中心中。
            "registry": null,
            // 如果依赖被重新命名,这是一个包实际的名称字符串。如果没有指定或为空,则该依赖未重命名。
            "package": null,
        }
    ],
    // `.crate`文件的SHA256校验和。
    "cksum": "d867001db0e2b6e0496f9fac96930e2d42233ecd3ca0413e0753d4c7695d289c",
    // 为包定义的一组特性。
    // 每个特性都映射到它所启用的特性或依赖性数组。
    "features": {
        "extras": ["rand/simd_support"]
    },
    // 该版本是否已被撤消的布尔值。
    "yanked": false,
    // 包的配置清单中的 `links` 字符串值,如果没有指定则为空。这个字段是可选的,默认为空。
    "links": null,
    // 一个无符号的32位整数,表示该条目的模式版本。
    //
    // 如果没有指定,它应该被解释为默认的1。
    //
    // Cargo(从1.51版开始)会忽略它不认识的版本。
    // 这提供了一种方法,可以安全地对索引条目进行修改,并允许老版本的cargo忽略它不理解的新条目。1.51以上的版本会忽略这个字段,因此可能会误解索引条目的含义。
    //
    // 目前的数值是:
    //
    // * 1: 这里记录的模式,不包括较新的补充内容。
    //      这在Rust 1.51版和更新的版本中得到认可。
    // * 2: 增加了 `features2` 字段。
    //      这在Rust 1.60和更新的版本中得到认可。
    "v": 2,
    // 此可选字段包含具有新的扩展语法的特性。
    // 具体来说,命名空间特性(`dep:`)和弱依赖(`pkg?/feat`)。
    //
    // 这是从 `features` 中分离出来的,因为1.19以前的版本会因为无法解析新的语法而无法加载,即使有 `Cargo.lock` 文件。
    //
    // cargo 将把这里列出的任何数值与 "features" 字段合并。
    //
    // 如果包括这个字段,"v" 字段应至少设置为 2 。
    //
    // 注册中心不需要为扩展的特性语法使用这个字段,他们可以在 "features" 字段中包括这些特性。
    // 只有当注册中心要支持1.19之前的cargo版本时,才有必要使用这个功能,实际上,这只是 crates.io ,因为这些旧版本不支持其他注册中心。
    "features2": {
        "serde": ["dep:serde", "chrono?/serde"]
    }
}

除了 yanked 字段的值可能在任何时候改变外,JSON对象在添加后不应该被修改。

Web API

注册中心可以在 config.json 定义主机网络API位置,以支持下面列出的任何动作。

对于需要认证的请求,Cargo包含 Authorization 头。该头的值是API token "令牌"。如果令牌无效,服务器应以403代码进行响应。用户应该访问注册中心的网站来获得令牌 ,Cargo可以使用 cargo login 命令来存储令牌,或者在命令行中传递令牌。

响应使用代码200表示成功。 错误应使用适当的响应代码,如404。 失败响应应该有一个JSON对象,其结构如下:

{
    // 要显示给用户的错误数组。
    "errors": [
        {
            // 作为字符串的错误消息。
            "detail": "error message text"
        }
    ]
}

如果响应中有这种结构,Cargo会向用户显示详细信息,即使响应代码是200。 如果响应代码表示有错误,而且内容中没有这种结构,Cargo会向用户显示一条旨在帮助调试服务器错误的信息。 服务器返回一个 errors 对象,允许注册中心提供更详细的或以用户为中心的错误信息。

为了向后兼容,服务器应该忽略任何意外的查询参数或JSON字段。 如果缺少的JSON字段,应该假定它为空。终端使用路径的 v1 部分进行版本控制,如果将来有需要,Cargo负责处理向后兼容的回调。

Cargo为所有请求设置了以下头信息:

  • Content-Type: application/json
  • Accept: application/json
  • User-Agent: The Cargo version such as cargo 1.32.0 (8610973aa 2019-01-02). This may be modified by the user in a configuration value. Added in 1.29.

发布

  • Endpoint: /api/v1/crates/new
  • Method: PUT
  • Authorization: Included

发布终端用于发布新版本的crate。服务器应该验证该crate,使其可供下载,并将其添加到索引中。

Cargo发送的数据体:

  • JSON数据长度的32位无符号小端整数。
  • 作为JSON对象的包的元数据。
  • .crate 文件长度的32位无符号小端整数。
  • .crate 文件。

下面是JSON对象注释的例子。包括一些由crates.io所限制的说明, 只是为了说明一些关于可能进行的验证类型的建议,而不是crates.io所限制的详尽清单。

{
    // 包的名称。
    "name": "foo",
    // 发布的包的版本。
    "vers": "0.1.0",
    // 包直接依赖的数组。
    "deps": [
        {
            // 依赖的名称。
            // 如果依赖是由源包名重新命名的,这就是原来的名字。新的包名被保存在 `explicit_name_in_toml` 字段中。
            "name": "rand",
            // 这个依赖的语义化版本要求。
            "version_req": "^0.6",
            // 为该依赖启用的特性数组(以字符串形式)。
            "features": ["i128_support"],
            // 布尔值,表示这是否是可选的依赖。
            "optional": false,
            // 是否启用默认特性的布尔值。
            "default_features": true,
            // 依赖的目标平台。
            // 如果不是目标依赖,则为空。
            // 否则,就是字符串,如 "cfg(windows)" 。
            "target": null,
            // 依赖的类别。
            // "dev", "build", or "normal".
            "kind": "normal",
            // 该依赖所在的注册中心索引的URL,是字符串。如果没有指定或为空,则假定该依赖在当前注册中心中。
            "registry": null,
            // 如果依赖被重新命名,这是新包名称的字符串。如果没有指定或为空,则该依赖未重命名。
            "explicit_name_in_toml": null,
        }
    ],
    // 为该包定义的一组特性。
    // 每个特性都映射到它所启用的特性或依赖数组。
    // Cargo对特性名称不做限制,但crates.io需要字母数字的ASCII、 `_` 或 `-` 字符。
    "features": {
        "extras": ["rand/simd_support"]
    },
    // 作者的字符串列表.
    // 可能为空。
    "authors": ["Alice <a@example.com>"],
    // 来自配置清单的描述字段。
    // 可能为空。crates.io 至少需要一些内容。
    "description": null,
    // 这个包的文档的网站的URL字符串。
    // 可为空。
    "documentation": null,
    // 这个包的主页的网站的URL字符串。
    // 可为空。
    "homepage": null,
    // README文件内容的字符串。
    // 可为空。
    "readme": null,
    // crate中的README文件的相对路径字符串。
    // 可为空。
    "readme_file": null,
    // 包的关键词的字符串数组。
    "keywords": [],
    // 包的类别字符串的数组。
    "categories": [],
    // 包的许可证的字符串。
    // 可为空。 crates.io 要求设置 `license` 或 `license_file` 。
    "license": null,
    // 许可证文件的相对路径字符串。
    // 可为空。
    "license_file": null,
    // 包的源码库网站的URL字符串。
    // 可为空。
    "repository": null,
    // 可选的 "状态" 标志的对象。每个值是字符串到字符串映射的对象。
    // crates.io对标志的格式有特殊解释。
    "badges": {
        "travis-ci": {
            "branch": "master",
            "repository": "rust-lang/cargo"
        }
    },
    // 包清单中的 `links` 字符串值,如果没有指定则为空。这个字段是可选的,默认为空。
    "links": null
}

响应成功包括JSON对象:

{
    // 可选的警告对象,以显示给用户。
    "warnings": {
        // 无效和被忽略的类别的字符串数组。
        "invalid_categories": [],
        // 标志名称的字符串数组,这些标志名称是无效的并被忽略。
        "invalid_badges": [],
        // 向用户显示的任意警告字符串的数组。
        "other": []
    }
}

Yank

  • Endpoint: /api/v1/crates/{crate_name}/{version}/yank
  • Method: DELETE
  • Authorization: Included

yank终端在索引中将给定版本的crate的 yank 字段设置为 true

响应成功包括JSON对象:

{
    // 表示删除成功,始终为true。
    "ok": true,
}

Unyank

  • Endpoint: /api/v1/crates/{crate_name}/{version}/unyank
  • Method: PUT
  • Authorization: Included

unyank终端在索引中将给定版本的crate的 yank 字段设置为 false

响应成功包括JSON对象:

{
    // 表示删除成功,始终为true。
    "ok": true,
}

所有者

Cargo没有固有的用户和所有者的概念,但它提供 owner 命令来帮助管理谁有控制crate的授权。 具体如何处理用户和所有者,由注册中心决定。 关于crates.io如何通过GitHub用户和团队处理所有者的描述,请参见[发布文档]。

Owners: List

  • Endpoint: /api/v1/crates/{crate_name}/owners
  • Method: GET
  • Authorization: Included

owners终端返回crate的所有者列表。

响应成功包括JSON对象:

{
    // crate的所有者数组。
    "users": [
        {
            // 所有者的唯一无符号32位整数。
            "id": 70,
            // 所有者唯一的用户名。
            "login": "github:rust-lang:core",
            // 所有者的名字。
            // 这是可选的,可以为空。
            "name": "Core",
        }
    ]
}

Owners: Add

  • Endpoint: /api/v1/crates/{crate_name}/owners
  • Method: PUT
  • Authorization: Included

PUT请求将向注册中心发送请求,以将新的所有者添加到crate里。 如何处理这个请求是由注册中心决定。 例如,crates.io会向用户发送一个邀请,他们必须在被添加之前接受。

该请求应包括以下JSON对象:

{
    // 要添加的所有者的 `login` 字符串数组。
    "users": ["login_name"]
}

响应成功包括JSON对象:

{
    // 表示添加成功,始终为真。
    "ok": true,
    // 一个要显示给用户的字符串。
    "msg": "user ehuss has been invited to be an owner of crate cargo"
}

Owners: Remove

  • Endpoint: /api/v1/crates/{crate_name}/owners
  • Method: DELETE
  • Authorization: Included

DELETE请求将从crate中删除一个所有者。该请求应包括以下JSON对象:

{
    // 要删除的所有者的 `login` 字符串数组。
    "users": ["login_name"]
}

响应成功包括JSON对象:

{
    // 表示删除成功,始终为真。
    "ok": true
}
  • Endpoint: /api/v1/crates
  • Method: GET
  • Query Parameters:
    • q: The search query string.
    • per_page: Number of results, default 10, max 100.

搜索请求将使用服务器上定义的标准对caate进行搜索。

响应成功包括JSON对象:

{
    // 结果数组
    "crates": [
        {
            // crate的名字。
            "name": "rand",
            // 可用的最高版本
            "max_version": "0.6.1",
            // crate的文字描述。
            "description": "Random number generators and other randomness functionality.\n",
        }
    ],
    "meta": {
        // 服务器上可用的结果总数。
        "total": 119
    }
}

Login

  • Endpoint: /me

"login" 终端不是实际的API请求。 它的存在仅仅是为了 cargo login 命令显示URL,指示用户在网络浏览器中访问以登录并获取API令牌。

依赖解析

Cargo 的主要功能之一就是依据每个包指定的依赖版本,解析出具体使用的依赖版本。 这个过程称为 "依赖解析" ,由 "解析器" (resolver) 完成。 解析的结果保存在 Cargo.lock 文件中,将每个依赖 "锁定" 到特定版本,使其不会改变。

解析器会尽力统一处理相同依赖,同时也会考虑可能的冲突。下面一节详细介绍了使用解析器和约束处理。

查看 Specifying Dependencies 一章了解如何指定依赖的更多细节。

可以用 [cargo tree] 命令来可视化查看解析结果。

SemVer规则兼容性

Cargo 使用 SemVer 语义化规则来表述版本,从而判断某个包两个不同版本的 "兼容" 情况,关于 "兼容性" 改变的更多信息查看 SemVer Compatibility 。 "兼容性" 的概念很重要,因为Cargo假设在版本兼容范围内更新依赖后构建是安全的。

认为 最左侧非零数字 相同的版本之间是兼容的。比如 1.0.31.1.0 被认为是兼容的,因此可以安全地从低版本升级到高版本。 然而, 1.1.02.0.0 不允许自动升级。以0开头的版本也适用这种约定,比如 0.1.00.1.2 兼容,与 0.2.0 不兼容。同样的, 0.0.10.0.2 不兼容。

继续加深一下,Cargo 依赖使用的 版本请求 语法 为:

版本请求示例等同于描述
^1.2.3 or ^1.2.3>=1.2.3, <2.0.0SemVer 兼容的版本, 高于或等于所给版本
~~1.2>=1.2.0, <1.3.0更受限的兼容范围
通配符1.*>=1.0.0, <2.0.0* 位置可以运行任何值
等于号=1.2.3=1.2.3完全等于指定的版本
比较符号>1.1>=1.2.0进行简单的数字比较
组合>=1.2, <1.5>1.2.0, <1.5.0同时满足多个条件

当多个包共同指定某个公共包为依赖时,解析器会尝试使用该公共包的同一个版本,前提是在 SemVer 规则兼容的范围。 解析器会尽可能使用兼容范围内包的最新版本。比如,假设现在解析图中有下面两个依赖请求:

# Package A
[dependencies]
bitflags = "1.0"

# Package B
[dependencies]
bitflags = "1.1"

如果生成 Cargo.lockbigflags 的最高版本是 1.2.1,那么两个包都会使用 1.2.1,因为这是兼容范围内的最高版本。 如果 2.0.0 已经发布,仍会使用 1.2.1,因为 2.0.0 被认为是不兼容的。

Cargo 允许多个包依赖的公共包版本不兼容的情况,对公共包构建多份拷贝。比如:

# Package A
[dependencies]
rand = "0.7"

# Package B
[dependencies]
rand = "0.6"

上面的配置会使得包A使用最高的 0.7 版本(本文写作时为 0.7.3 ),包B使用最高的 0.6 版本(比如 0.6.5 )。 这可能会有潜在的问题,参考 Version-incompatibility hazards

不允许使用兼容范围内的多个版本,这会导致解析器错误。例如,解析图中的两个包有下面的依赖请求:

# Package A
[dependencies]
log = "=0.4.11"

# Package B
[dependencies]
log = "=0.4.8"

上面的解析会失败,因为不允许有两份 0.4 版的 log 包。

版本不兼容的风险

当解析图中出现同一crate的多个版本时,这些版本中的类型(types)可能会被使用它们的crate再暴露出来,这会导致问题。 这是因为Rust编译器以不同方式解读类型(types)和语法元素(items),即使它们有相同的名字。 一个库在发布一个 SemVer 不兼容版本时一定要小心(比如 1.0.0 在被使用的情况下发布 2.0.0),尤其是那些被广泛使用的库。

"semver trick" 是解决这个问题的一个变通方法,可以在发布破坏性更新的同时保持与旧版本的兼容性。 上面链接中的文章详细介绍了该问题的来源以及解决方法。简而言之,当一个库想要发布一个 SemVer 破坏性更新时, 先发布破坏性新版本,再同时发布一个旧版本的修复版本,在这个版本中引用新版本并将其中的类型 (types) 导出。

这种不兼容通常表现为编译错误,但有时也会显现为运行时的错误行为。 例如,比如说有一个库 foo1.0.02.0.0 在解析图中出现了两次, 当在使用foo 1.0.0 的库生成的一个对象上进行 downcast_ref , 而调用 downcast_ref 的代码引用的类型却来自 foo 2.0.0,downcast 就会在运行时失败。

一定要确认你是否用到了某个库的多个版本,尤其是检查混用不同版本的类型(types)的可能性。 cargo tree -d 命令可以用来检查重复依赖的存在和来源。 同样的,当你发布一个很流行的库的SemVer不兼容版本时,仔细考虑其对生态的影响。

预发布

SemVer 有 "预发布" 的概念,在版本号中带有 - ,比如 1.0.0-alpha1.0.0-beta 。 Cargo 会避免自动使用预发布版本,除非显式要求。例如,如果包 foo 发布了 1.0.0-alpha ,而版本请求是 foo = "1.0" , 则版本是不匹配的,Cargo 会返回错误。预发布版本必须显式指定,比如 foo = "1.0.0-alpha"。 同样的, cargo install 也会在未显式声明情况下避免使用预发布版本。

Cargo 允许预发布版本间的自动更新。例如,如果 1.0.0-beta 发布,那么请求 foo = "1.0.0-alpha" 会允许更新到 beta 版本。 注意,预发布版本是不稳定的,使用时要小心。一些项目可能会选择在预发布版本间进行破坏性更新, 建议不要使用预发布的依赖,除非你的库也是预发布版本。更新 Cargo.lock 时要小心,在预发布版本造成问题之前做好充分准备。

预发布标记可能会用句点来分割为不同的部分。数字部分会进行数值的比较。 比如 1.0.0-alpha.4 中的 4 会作为数字来比较, 1.0.0-alpha.11 的版本就比它高。 非数字部分通过字典排序来比较。

版本元数据

SemVer 有 "版本元数据" 的概念,会在版本后附带一个加号出现,比如 1.0.0+21AF26D3 。 通常忽略这个元数据,而且不应该在版本请求中使用。 永远不要在 crates.io 上发布两个仅有元数据不同的版本( 然而目前 crates.io 却允许这一点,这是一个 known issue 已知的问题)。

其他约束

版本请求并不是决定解析过程的唯一因素。下面章节中介绍了影响解析过程的其他几种约束:

特性

为了生成 cargo.lock,解析器在构建依赖图时会假设所有 workspace 的所有 [feature] 都被启用。 这保证所有可选的依赖都可用且被解析,当在命令行中通过 --features 命令行标志 添加或删除特性时,功能可以正常实现。 当 编译 crate时,解析器第二次执行,根据命令来决定实际启用的特性。

当解析依赖时,会将其被启用的所有特性一起解析。 例如,一个包依赖 im 包,开启了 serde dependency;另一个包也依赖 im,开启了 rayon dependency。 这时 im 会按照两个特性都启用的状态进行构建, serderayon 都会被加入解析图。 如果依赖 im 的包都没有包含这些特性,那么这些可选依赖会被忽略,不会影响解析过程。

当在工作空间(workspace)中构建多个包(比如通过 --workspace 或者 多个 -p 标记),这些包所有依赖的所有特性会统一进行构建。 如果你有需要避免合并,可以单独执行 cargo 进行构建。

解析器会跳过那些缺失所请求特性的包版本。例如,如果一个包依赖 regex^1 版本,且开启了 perf feature,那么其可以选择的最早版本是 1.3.0,因为那之前的版本没有 perf 这个特性。同样的,如果一个特性在新版本中被移除,那么需要这个特性的包的版本就会卡在之前包含这个特性的版本。 不建议在 SemVer 兼容的更新中移除特性。注意,可选依赖是隐式的特性,因此移除某个可选依赖或者将其改变为非可选可能会导致问题,详见 removing an optional dependency

Feature 解析器 v2

Cargo.toml 中指定 resolver = "2" 时,会启用不同算法的另一个特性解析器。 "1" 解析器会将一个包启用的所有特性合并起来,无论这些特性是在哪里指定的。 而 "2" 解析器会在以下场景中避免合并特性:

  • 当没有实际被构建时,平台特定依赖的特性不会被启用。例如:

    [dependencies.common]
    version = "1.0"
    features = ["f1"]
    
    [target.'cfg(windows)'.dependencies.common]
    version = "1.0"
    features = ["f2"]
    
  • 当在一个非windows平台构建这个示例时,不会 启用 f2 特性 。

  • 在这些相同的依赖作为常规依赖使用时,在build-dependencies或proc-macros上启用的特性,不会被合并。

    [dependencies]
    log = "0.4"
    
    [build-dependencies]
    log = {version = "0.4", features=['std']}
    

    当编译构建脚本时, log crate 和 std 特性一起编译。而当编译你的库时,则不会启用该特性。

  • 构建普通目标时,不会把 dev-dependencies 中相同依赖的特性合并进来。只有构建开发时目标(test、example等),构建 dev-dependencies 时,才会进行合并。

    [dependencies]
    serde = {version = "1.0", default-features = false}
    
    [dev-dependencies]
    serde = {version = "1.0", features = ["std"]}
    

    在这个例子中,该库构建 serde 不会带 std feature。然而,当构建一个 test或example时,就会带 std feature。比如执行 cargo testcargo build --all-targets 会合并 feature 。注意 dev-dependencies 总是会被忽略,以上内容仅针对顶层包或工作空间成员。

links field 字段用于确保二进制目标对每个本地库只链接一次。 解析器会尝试创建依赖图,使得每个 links 名只对应一个实例。 如果无法找到这样的依赖图,就会返回错误。

例如,如果一个包依赖 libgit2-sys0.11 版,而另一个包依赖 0.12,则会报错,因为 Cargo 无法将两个依赖合并,即使这个两个版本链接的都是 git2 本地库。 因此,在发布带 links字段的库的 SemVer 不兼容版本时,一定要多加注意。

Yanked versions

Yanked releases 是那些标记为不应该使用的版本。当解析器在构建依赖图时,会忽略哪些标记为yanked的版本,除非其已经写入了 Cargo.lock

更新依赖

需要知晓依赖图的那些 Cargo 命令会自动执行依赖解析。 例如,cargo build 会运行解析器来知晓所有需要构建的依赖。 在第一次执行之后,结果被保存到 Cargo.lock 中。 接下来的命令也会执行解析器,保持依赖被锁定在 Cargo.lock 中声明的版本(如果可以做到的话)。

如果修改了 Cargo.toml 中的依赖列表,比如把依赖从 1.0 改到 2.0,解析器会选择该依赖的新版本以满足依赖请求。 如果新的依赖也引用了新的依赖,那么会触发后者的更新。会更新 Cargo.lock--locked--frozen 标志可以改变这种行为,或者会返回一个错误,以防止依赖请求变更时的自动依赖更新。

cargo update 可以更新 Cargo.lock 中有新版本的依赖项。如果不带任何选项,其会更新 lock file 中的所有包。 -p 标志可以指定更新的包名,其他标志如 --aggressive--precise 可以用于控制如何进行版本选择。

覆盖

Cargo有多种机制来覆盖依赖图中的依赖项, Overriding Dependencies 一章中进行了详细介绍。 覆盖项是对注册中心(registry)进行覆盖,将被覆盖的依赖替换为其他条目,除此之外解析过程没有任何区别。

依赖的种类

包 (package) 中有三种依赖:常规的,build,和 dev。 大多数情况下,这三种依赖在解析器的方式一样,一个区别是非工作空间成员的 dev-dependencies 总是被忽略,不会影响到解析过程。

带有 [target] 表的 Platform-specific dependencies 解析为启用所有平台。换句话说,解析器忽略平台或 cfg 表达式。

dev-dependency cycles

通常解析器不允许循环依赖,但是在 dev-dependencies 却是允许的。 例如,项目 foo 有一个 dev-dependencies bar,而 bar 有一个依赖 foo (通常是以 "path" 依赖的形式)。 这是允许的,因为在构建制品看来,这并不是一个循环依赖。 在这个例子中, foo 库先被构建(这个过程中不需要 bar,因为 bar 只用于测试),然后依赖 foobar 被构建,最后 foo 的测试也可以链接 bar 而被构建。

小心这里会产生令人困惑的错误。在构建 foo 的单元测试(unit tests)时,实际上有两份 foo 的拷贝被链接进最后的测试二进制文件:一份是 bar 依赖的 foo,另一份是包含着单元测试的 foo。如同在 Version-incompatibility hazards 一节中提到问题,这两个 foo 的类型是不兼容的。在把 bar 中的 foo 的类型进行再导出时,要小心 foo 的单元测试不会把这些类型与本地类型视作等同。

尽可能拆分重构你的包,以保证依赖图中没有循环。

解析器版本

可以在 Cargo.toml 中指定解析器版本来使用另一种特性解析算法:

[package]
name = "my-package"
version = "1.0.0"
resolver = "2"

在 Cargo 1.50 之前默认为 "1" 代解析器。 如果在根包中指定 edition = "2021" 或者更高版本,则会使用 "2" 代解析器。其他情况下默认都是 "1" 代解析器。

"2" 代解析器主要是改变了 feature 合并 的过程。详情见 features 一章

解析器版本设置是全局性的,会影响到整个工作空间(workspace)。 依赖中定义的 resolver 版本会被忽略,只有顶层包中定义的才有效。 如果使用了 virtual workspace ,解析器版本应该在 [workspace] 表中指定:

[workspace]
members = ["member1", "member2"]
resolver = "2"

一些建议

下面是一些关于设置你的包以及依赖项版本的建议。这些建议在一般情况下的通用的,不过会有一些情况需要你指定不常规的依赖请求。

  • 在更新你的版本数时,遵从 SemVer guidelines,无论是 SemVer 兼容或不兼容的更新。

  • 尽可能使用 crate 依赖请求,比如 1.2.3 。这让解析器可以在保证构建兼容性同时尽可能灵活地选择依赖版本。

    • 三个数字都应该设置,这可以指定可用的最小版本,保证库的使用者不会使用比这个版本更旧的版本,因而缺失一些构建所需的东西。
    • 避免使用 * 版本,因为 crates.io 不允许这种请求,而且可能会导致 [cargo update] 时产生破坏 SemVer 兼容的更改。
    • 避免过度放宽依赖需求。例如 >="2.0.0" 可以允许任何 SemVer 不兼容的版本,比如 5.0.0,这会在未来破坏依赖过程。
    • 尽可能避免过度缩窄依赖需求。例如你指定 bar=~"1.3",而另一个包指定 bar="1.4",这会导致解析失败,即使一般情况下次版本更新 (minor release)是兼容的。
  • 保持声明依赖版本与你的库实际所需的最小依赖版本一致。比如说,你有个库声明需要 bar="1.0.12" ,后来你的库实际开始使用 bar 1.1.0 版中的某些功能,这时应该更新声明为 bar="1.1.0"

    如果你没有这样做,可能问题不会立即显现出来,因为当你执行 cargo update 时,Cargo会对把所有依赖更新到最新的版本。然而,当另一个用户使用你的库时,可能会执行 cargo update -p your-library,这不会更新 bar 的版本,因为 bar 版本可能被他的 Cargo.lock 锁定了。只有当声明的依赖项版本被改变时,bar 才会被更新。进行 cargo update -p 时的失败可能会让这个用户非常困惑。

  • 如果两个包的耦合很强,使用 = 来指定依赖可以保证之间的同步。例如,一个库有一个对应的 proc-macro,通常情况下假设必须保持版本统一(两者也不会独立使用)。这时parent library 可以用 = 来指定这个 proc-macro,然后把这些宏重导出方便使用。

  • 0.0.x 版本可以用于那些暂时还不稳定的包。

一般来说,你的依赖指定的越严格,解析越可能失败;反过来说,你的依赖指定的太宽松,新版本就可能破坏构建。

问题检查

下面部分阐述了一些你可能会遇到的问题,以及相应的解决办法:

SemVer不兼容的修订版更新导致构建被破坏

有时一个项目可能无意间发布了一个修订版更新(point release),但是却带有SemVer不兼容的改变。 当用户通过 cargo update 更新到最新版本后,构建被破坏了。这时建议该项目 yank 掉这个版本,要么移除这个不兼容改变,要么以主版本更新来发布。

如果这个改变来自第三方项目,可以(礼貌地)与项目合作来解决问题。

当等待该版本被 yank 时,可以采用一些变通措施:

  • 如果你的项目是一个末端产品(比如一个二进制可执行程序),可以通过 Cargo.lock 避免更新这个有问题的包。这可以通过在 cargo update 使用 --precise 标志来实现。
  • 如果你发布一个二进制程序到 crates.io,那么可以暂时添加一个 = 来强制依赖使用某个特定的"好"版本。
    • 或者建议用户在 cargo install 时使用 --locked 标志来使用自带的 Cargo.lock,其中包含着保证可以编译成功的依赖版本。
  • 库项目可以考虑发布一个暂时的新版本,其中包含更严格的依赖版本限制,以避免导致问题的依赖。你可以考虑使用一个范围限制(而不是 = )来避免过于严格的要求导致与其他包的依赖冲突。当问题解决后,你可以发布另一个修订版本来放松这个依赖限制。
  • 如果这个(出问题的)第三方项目看起来无法或者不情愿yank这个更新,那么一个办法是更新你的代码来兼容这个更新,同时更新依赖请求,将这个版本设置为最小要求版本。同时你还需要考虑这对于你的库来说是否是一个SemVer破坏性更新,例如你这个库导出了依赖中的某些类型。

语义化兼容性

本章详细介绍了对于新发布的包,什么是传统意义上的兼容或破坏性的语义化版本变化。 关于什么是语义化版本,以及Cargo如何使用它来确保库的兼容性,请参阅SemVer compatibility部分。

这些只是准则,而不一定是所有项目都会遵守的硬性规定。 Change categories部分详细说明了本指南如何对变更的级别和严重程度进行分类。 本指南的大部分内容都集中在那些会导致 cargorustc 不能构建以前正常工作的内容的变化。 几乎所有的改变都有可能对运行时的行为产生负面影响,对于这些情况,通常由项目维护者判断是否属于语义化不兼容的改变。

也可以参见rust-semverver,它是一个实验性的工具,试图以编程方式检查兼容性规则。

更改类别

下面列出的所有策略都是按变化的级别来分类的:

  • Major change: 这种变化需要语义化版本的重要改变。
  • Minor change: 这种变化只需要在语义化版本上做小改动。
  • Possibly-breaking change: 一些项目可能认为是大的变化,另一些则认为是小的变化。

"可能破坏" 类别涵盖了在更新期间有潜在破坏的变化,但不一定会导致破坏。 这些变化的影响应该被仔细考虑。确切的性质将取决于该变化和项目维护者的原则。

有些项目可能会选择只在一个小的变化上增加补丁号。我们鼓励遵循语义化规范,只在补丁版本中应用错误修复。 然而,一个错误的修复可能需要一个被标记为 "次要改动" 的API变化,并且不应该影响兼容性。 本指南不对每个 "次要改动" 应如何处理采取立场,因为次要改动和补丁改动之间的区别是取决于改动的性质的惯例。

有些改动被标记为 "次要",即使它们有破坏构建的潜在风险。 这适用于潜在风险极低的情况,而且可能破坏的代码不太可能用习惯性的Rust编写,或者去特别强调不使用。

本指南使用 "主要" 和 "次要" 这两个术语是假设这与 "1.0.0" 或更高版本有关。从 "0.y.z" 开始的初始开发版本可以把 "y" 中的变化作为主要版本,而把 "z" 作为次要版本。 "0.0.z" 版本总是主要变化。这是因为Cargo使用的惯例是,只有最左边的非零部分中的变化才被认为是不兼容的。

API兼容性

下面所有的例子都包含三个部分:原始代码,修改后的代码,以及可能出现在另一个项目中的代码使用范例。 在次要改动中,示例用法应该成功地与前后两个版本一起构建。

Major: 重新命名/移动/删除任意公共条目

缺失公开暴露条目将导致对该条目的任何使用无法编译。

// MAJOR CHANGE

///////////////////////////////////////////////////////////
// 之前
pub fn foo() {}

///////////////////////////////////////////////////////////
// 之后
// ... 条目被移除

///////////////////////////////////////////////////////////
// 示例:将打破用法。
fn main() {
    updated_crate::foo(); // Error: 不能找到函数 `foo`
}

这包括添加任何种类的[cfg 属性],它可以根据conditional compilation "条件编译"改变哪些条目或行为是可用的。

缓和策略:

  • 将要删除的条目标记为deprecated,然后在以后的语义化版本打破性发布中删除它们。
  • 将重命名的条目标记为deprecated,并使用 pub use 条目来重新输出旧名称。

Minor: 添加新公共条目

增加新的、公开的items是次要变化。

// MINOR CHANGE

///////////////////////////////////////////////////////////
// 之前
// ... 缺少条目

///////////////////////////////////////////////////////////
// 之后
pub fn foo() {}

///////////////////////////////////////////////////////////
// 示例:库的使用将安全工作。
// `foo` 没有被使用,因为它之前并不存在。

请注意,在某些少见的情况下,由于通配符导入的原因,这可能是破坏性改变。例如,如果你添加了一个新的特性, 而一个条目使用了一个将该特性带入范围的通配符导入,并且这个新的特性引入了一个与它所实现的任意类型相冲突的关联项,这可能会因为这种混淆而导致编译时错误。例子:

// Breaking change example

///////////////////////////////////////////////////////////
// 之前
// ... 缺少trait

///////////////////////////////////////////////////////////
// 之后
pub trait NewTrait {
    fn foo(&self) {}
}

impl NewTrait for i32 {}

///////////////////////////////////////////////////////////
// 示例:使用是破坏性的。
use updated_crate::*;

pub trait LocalTrait {
    fn foo(&self) {}
}

impl LocalTrait for i32 {}

fn main() {
    123i32.foo(); // Error:  在作用域有多个适用的条目
}

这并不被认为是重要改变,因为通常通配符导入是一个已知的向前兼容的风险。应该避免从外部crate中导入条目的通配符。

Major: 当当前所有字段都是公共的时候,添加私有结构体字段

当私有字段被添加到之前拥有所有公共字段的结构体中时。 这将破坏任何试图用struct literal"结构体字面量"来构建该结构体的代码。

// MAJOR CHANGE

///////////////////////////////////////////////////////////
// 之前
pub struct Foo {
    pub f1: i32,
}

///////////////////////////////////////////////////////////
// 之后
pub struct Foo {
    pub f1: i32,
    f2: i32,
}

///////////////////////////////////////////////////////////
// 示例:使用是破坏性的。
fn main() {
    let x = updated_crate::Foo { f1: 123 }; // Error: 不能构建 `Foo`
}

缓和策略:

  • 不要向所有公共字段的结构体添加新字段。
  • 在首次引入结构体时,将结构标记为#[non_exhaustive], 以阻止用户使用结构字面量语法,而是提供构造方法或 Default 实现。

Major: 在不存在私有字段的情况下添加公共字段

当公共字段被添加到拥有所有公共字段的结构体中时,这将破坏任何试图用struct literal"结构体字面量"来构建它的代码。

// MAJOR CHANGE

///////////////////////////////////////////////////////////
// 之前
pub struct Foo {
    pub f1: i32,
}

///////////////////////////////////////////////////////////
// 之后
pub struct Foo {
    pub f1: i32,
    pub f2: i32,
}

///////////////////////////////////////////////////////////
// 示例:使用是破坏性的。
fn main() {
    let x = updated_crate::Foo { f1: 123 }; // Error: 缺失 `f2` 字段
}

缓和策略:

  • 不要向所有公共字段结构体添加新字段。
  • 在首次引入结构体时,将结构体标记为#[non_exhaustive], 以阻止用户使用结构体字面量语法,而是提供构造方法或Default实现。

Minor: 当至少有一个私有字段存在时添加或删除私有字段

当结构已经至少有一个私有字段时,从结构中添加或删除私有字段是安全的。

// MINOR CHANGE

///////////////////////////////////////////////////////////
// 之前
#[derive(Default)]
pub struct Foo {
    f1: i32,
}

///////////////////////////////////////////////////////////
// 之后
#[derive(Default)]
pub struct Foo {
    f2: f64,
}

///////////////////////////////////////////////////////////
// 示例: 使用库将是安全的。
fn main() {
    // 不能访问私有字段。
    let x = updated_crate::Foo::default();
}

这是安全的,因为现有的代码不能使用struct literal来构造它,无需彻底匹配其内容。

请注意,对于元组结构体来说,如果元组包含公共字段,增加或删除私有字段会改变任何公共字段的索引,将是 major变化

// MAJOR CHANGE

///////////////////////////////////////////////////////////
// 之前
#[derive(Default)]
pub struct Foo(pub i32, i32);

///////////////////////////////////////////////////////////
// 之后
#[derive(Default)]
pub struct Foo(f64, pub i32, i32);

///////////////////////////////////////////////////////////
// 示例:使用是破坏性的。
fn main() {
    let x = updated_crate::Foo::default();
    let y = x.0; // Error: 是私有的。
}

Minor: 从具有所有私有字段的元组结构体(至少有一个字段)到正常的结构体。

如果所有字段都是私有的,那么将元组结构体改变为普通结构体是安全的,反之亦然。

// MINOR CHANGE

///////////////////////////////////////////////////////////
// 之前
#[derive(Default)]
pub struct Foo(i32);

///////////////////////////////////////////////////////////
// 之后
#[derive(Default)]
pub struct Foo {
    f1: i32,
}

///////////////////////////////////////////////////////////
// 示例:库的使用将是安全的。
fn main() {
    // 不能访问私有字段。
    let x = updated_crate::Foo::default();
}

这是安全的,因为当前的代码不能使用struct literal来构造它,不能匹配它的内容。

Major: 添加新的枚举条目 (没有 non_exhaustive ) 。

如果枚举未使用#[non_exhaustive]属性,增加新的枚举条目是破坏性的改变。

// MAJOR CHANGE

///////////////////////////////////////////////////////////
// 之前
pub enum E {
    Variant1,
}

///////////////////////////////////////////////////////////
// 之后
pub enum E {
    Variant1,
    Variant2,
}

///////////////////////////////////////////////////////////
// 示例:使用是破坏性的。
fn main() {
    use updated_crate::E;
    let x = E::Variant1;
    match x { // Error: `E::Variant2` 未涵盖
        E::Variant1 => {}
    }
}

缓和策略:

  • 在引入枚举时,将其标记为#[non_exhaustive],以迫使用户使用[通配符模式]来捕获新的变体。

Major: 向枚举变量添加新字段

在枚举变体中添加新的字段是一种破坏性的改变,因为所有的字段都是公开的,构造函数和匹配将无法编译。

// MAJOR CHANGE

///////////////////////////////////////////////////////////
// 之前
pub enum E {
    Variant1 { f1: i32 },
}

///////////////////////////////////////////////////////////
// 之后
pub enum E {
    Variant1 { f1: i32, f2: i32 },
}

///////////////////////////////////////////////////////////
// 示例:使用是破坏性的。
fn main() {
    use updated_crate::E;
    let x = E::Variant1 { f1: 1 }; // Error: 缺失 f2
    match x {
        E::Variant1 { f1 } => {} // Error: 缺失 f2
    }
}

缓和策略:

  • 在引入枚举时,将变体标记为non_exhaustive,使其没有通配符的情况下不能构建或匹配它。
    pub enum E {
        #[non_exhaustive]
        Variant1{f1: i32}
    }
  • 在引入枚举时,使用显式结构体作为值,在这里你可以对字段可见性进行控制。
    pub struct Foo {
       f1: i32,
       f2: i32,
    }
    pub enum E {
        Variant1(Foo)
    }

Major: 添加非默认的trait条目

在特性中添加非默认的条目是一种破坏性的改变。这将破坏该特性的任何实现者。

// MAJOR CHANGE

///////////////////////////////////////////////////////////
// 之前
pub trait Trait {}

///////////////////////////////////////////////////////////
// 之后
pub trait Trait {
    fn foo(&self);
}

///////////////////////////////////////////////////////////
// 示例:使用是破坏性的。
use updated_crate::Trait;
struct Foo;

impl Trait for Foo {}  // Error: 未实现所有trait条目

缓和策略:

  • 始终为新的相关trait条目提供默认的实现或值。
  • 在引入trait时,使用sealed trait技术来防止crate外的用户实现该trait。

Major: trait条目签名的任何变化

对trait条目的签名做任何改变都是破坏性的。可能会破坏该trait的外部实现者。

// MAJOR CHANGE

///////////////////////////////////////////////////////////
// 之前
pub trait Trait {
    fn f(&self, x: i32) {}
}

///////////////////////////////////////////////////////////
// 之后
pub trait Trait {
    // 对于密封的trait或普通函数,这将是次要变化,因为用泛型来泛化严格地扩展了可能的用法。
    // 但在这种情况下,trait的实现必须使用相同的签名。
    fn f<V>(&self, x: V) {}
}

///////////////////////////////////////////////////////////
// 示例:使用是破坏性的。
use updated_crate::Trait;
struct Foo;

impl Trait for Foo {
    fn f(&self, x: i32) {}  // Error: trait 声明有1个类型参数
}

缓和策略:

  • 引入带有默认实现的新条目,以涵盖新功能,而不是修改现有条目。
  • 当引入该trait时,使用sealed trait来防止crate外的用户实现该trait。

Possibly-breaking: 添加默认的trait条目

添加默认的trait条目通常是安全的。然而,这有时会导致编译错误。 例如,如果在另一个trait中存在同名的方法,则会引入混淆。

// Breaking change example

///////////////////////////////////////////////////////////
// 之前
pub trait Trait {}

///////////////////////////////////////////////////////////
// 之后
pub trait Trait {
    fn foo(&self) {}
}

///////////////////////////////////////////////////////////
// 示例:使用是破坏性的。
use updated_crate::Trait;
struct Foo;

trait LocalTrait {
    fn foo(&self) {}
}

impl Trait for Foo {}
impl LocalTrait for Foo {}

fn main() {
    let x = Foo;
    x.foo(); // Error: 作用域内有多个符合条目
}

注意,这种二义性并不存在于inherent implementations的名称冲突,因为它们优先于trait条目。

参见trait-object-safety,了解添加trait条目时需要考虑的特殊情况。

缓和策略:

  • 一些项目可能认为这是可以接受的破坏,特别是如果新的条目名称不太可能与任何现有的代码发生冲突。请谨慎选择名称,以有助避免这些冲突。此外,要求下游用户在更新依赖时添加disambiguation syntax "歧义消除语法" 以选择恰当的函数,这是可以接受的。

Major: 添加trait条目,使trait非对象安全

增加改变trait的条目,使trait不再是object safe,这是破坏性的变化。

// MAJOR CHANGE

///////////////////////////////////////////////////////////
// 之前
pub trait Trait {}

///////////////////////////////////////////////////////////
// 之后
pub trait Trait {
    // 一个相关的常量使得该trait不是对象安全的。
    const CONST: i32 = 123;
}

///////////////////////////////////////////////////////////
// 示例:使用是破坏性的。
use updated_crate::Trait;
struct Foo;

impl Trait for Foo {}

fn main() {
    let obj: Box<dyn Trait> = Box::new(Foo); // Error: 不能成为一个对象
}

反之也是安全的(将非对象安全的trait变成安全的trait)。

Major: 添加没有默认值的类型参数

在trait中添加没有默认值的类型参数是一种破坏性的改变。

// MAJOR CHANGE

///////////////////////////////////////////////////////////
// 之前
pub trait Trait {}

///////////////////////////////////////////////////////////
// 之后
pub trait Trait<T> {}

///////////////////////////////////////////////////////////
// 示例:使用是破坏性的
use updated_crate::Trait;
struct Foo;

impl Trait for Foo {}  // Error: 缺失泛型

缓和策略:

Minor: 添加默认trait类型参数

在trait中添加类型参数是安全的,只要它有默认值。 外部实现者将使用默认值而不需要指定参数。

// MINOR CHANGE

///////////////////////////////////////////////////////////
// 之前
pub trait Trait {}

///////////////////////////////////////////////////////////
// 之后
pub trait Trait<T = i32> {}

///////////////////////////////////////////////////////////
// 示例:库的使用是安全的。
use updated_crate::Trait;
struct Foo;

impl Trait for Foo {}

Possibly-breaking change: 添加任意内部条目

通常情况下,向一个实现添加内部条目应该是安全的,因为内部条目比trait条目有优先权。 然而,在某些情况下,如果名称与具有不同签名的已实现的trait条目相同,则冲突会导致问题。

// 破坏性改变示例

///////////////////////////////////////////////////////////
// 之前
pub struct Foo;

///////////////////////////////////////////////////////////
// 之后
pub struct Foo;

impl Foo {
    pub fn foo(&self) {}
}

///////////////////////////////////////////////////////////
// 示例:使用是破坏性的
use updated_crate::Foo;

trait Trait {
    fn foo(&self, x: i32) {}
}

impl Trait for Foo {}

fn main() {
    let x = Foo;
    x.foo(1); // Error: 这个函数有0个参数
}

注意,如果签名匹配,就不会出现编译时错误,但可能会出现运行时行为的静默变化(因为现在执行的是一个不同的函数)。

缓和策略:

  • 一些项目可能认为这是可以接受的破坏,特别是如果新的条目名称不太可能与任何现有的代码发生冲突。请谨慎选择名称,以有助避免这些冲突。此外,要求下游用户在更新依赖时添加disambiguation syntax "歧义消除语法" 以选择恰当的函数,这是可以接受的。

Major: 收紧泛型边界

在类型上收紧泛型边界是破坏性的改变,因为这可能会打破用户对较宽松边界的预期。

// MAJOR CHANGE

///////////////////////////////////////////////////////////
// 之前
pub struct Foo<A> {
    pub f1: A,
}

///////////////////////////////////////////////////////////
// 之后
pub struct Foo<A: Eq> {
    pub f1: A,
}

///////////////////////////////////////////////////////////
// 示例:使用是破坏性的。
use updated_crate::Foo;

fn main() {
    let s = Foo { f1: 1.23 }; // Error: trait 边界 `{float}: Eq` 不满足
}

Minor: 放宽泛型边界

放宽类型泛型界限是安全的,因为它仅扩展了允许的范围。

// MINOR CHANGE

///////////////////////////////////////////////////////////
// 之前
pub struct Foo<A: Clone> {
    pub f1: A,
}

///////////////////////////////////////////////////////////
// 之后
pub struct Foo<A> {
    pub f1: A,
}

///////////////////////////////////////////////////////////
// 示例:库的使用是安全的。
use updated_crate::Foo;

fn main() {
    let s = Foo { f1: 123 };
}

Minor: 添加默认的类型参数

只要类型有默认值,给它添加类型参数是安全的。所有现有的引用将使用默认值,而不需要指定参数。

// MINOR CHANGE

///////////////////////////////////////////////////////////
// 之前
#[derive(Default)]
pub struct Foo {}

///////////////////////////////////////////////////////////
// 之后
#[derive(Default)]
pub struct Foo<A = i32> {
    f1: A,
}

///////////////////////////////////////////////////////////
// 示例:库的使用是安全的。
use updated_crate::Foo;

fn main() {
    let s: Foo = Default::default();
}

Minor: 泛化类型以使用泛型(具有相同的类型)

结构体或枚举字段可以从具体类型改变为泛型类型参数,前提是这种变化带来的所有现有用例的类型相同。 例如,下面的改变是允许的。

// MINOR CHANGE

///////////////////////////////////////////////////////////
// 之前
pub struct Foo(pub u8);

///////////////////////////////////////////////////////////
// 之后
pub struct Foo<T = u8>(pub T);

///////////////////////////////////////////////////////////
// 示例:库的使用是安全的。
use updated_crate::Foo;

fn main() {
    let s: Foo = Foo(123);
}

因为当前 FooFoo<u8> 的缩写,产生相同的字段类型。

Major: 泛化类型以使用泛型(可能有不同的类型)

如果类型可以改变,将结构体或枚举字段从具体类型改为泛型类型参数就是破坏性的。

// MAJOR CHANGE

///////////////////////////////////////////////////////////
// 之前
pub struct Foo<T = u8>(pub T, pub u8);

///////////////////////////////////////////////////////////
// 之后
pub struct Foo<T = u8>(pub T, pub T);

///////////////////////////////////////////////////////////
// 示例:使用是破坏性的
use updated_crate::Foo;

fn main() {
    let s: Foo<f32> = Foo(3.14, 123); // Error: 缺失类型。
}

Minor: 将泛型类型改为一个更泛型的类型

将一个泛型类型改为更泛型的类型是安全的。例如,下面添加了一个默认为原始类型的泛型参数, 这是安全的,因为所有现有的用户都会为两个字段使用相同的类型,默认的参数不需要被指定。

// MINOR CHANGE

///////////////////////////////////////////////////////////
// 之前
pub struct Foo<T>(pub T, pub T);

///////////////////////////////////////////////////////////
// 之后
pub struct Foo<T, U = T>(pub T, pub U);

///////////////////////////////////////////////////////////
// 示例:库的使用是安全的
use updated_crate::Foo;

fn main() {
    let s: Foo<f32> = Foo(1.0, 2.0);
}

Major: 添加/删除函数参数

改变函数参数是一种破坏性的改变。

// MAJOR CHANGE

///////////////////////////////////////////////////////////
// 之前
pub fn foo() {}

///////////////////////////////////////////////////////////
// 之后
pub fn foo(x: i32) {}

///////////////////////////////////////////////////////////
// 示例:使用是破坏性的。
fn main() {
    updated_crate::foo(); // Error: 这个函数需要一个参数
}

缓和策略:

  • 用新的签名引入一个新的函数,并可能弃用旧的函数。
  • 引入接受结构体参数的函数,其中结构体是用构建模式构建的。这允许将来在结构体中添加新的字段。

Possibly-breaking: 引入新的函数类型参数

通常情况下,增加非默认类型参数是安全的,但在某些情况下,可能是破坏性的改变。

// Breaking change example

///////////////////////////////////////////////////////////
// 之前
pub fn foo<T>() {}

///////////////////////////////////////////////////////////
// 之后
pub fn foo<T, U>() {}

///////////////////////////////////////////////////////////
// 示例:使用是破坏性的
use updated_crate::foo;

fn main() {
    foo::<u8>(); // Error: 这个函数需要2个泛型参数,但只提供了一个泛型参数
}

然而,这样的显式调用是非常少见的(通常可以用其他方式编写),所以这种破坏通常是可以接受的。 我们应该考虑有问题的函数被显式类型参数调用的可能性。

Minor: 泛化函数以使用泛型(支持原始类型)

函数的参数或其返回值的类型可以被泛化以使用泛型,包括引入一个新类型的参数, 只要它可以被实例化为原始类型。例如,允许以下变化:

// MINOR CHANGE

///////////////////////////////////////////////////////////
// 之前
pub fn foo(x: u8) -> u8 {
    x
}
pub fn bar<T: Iterator<Item = u8>>(t: T) {}

///////////////////////////////////////////////////////////
// 之后
use std::ops::Add;
pub fn foo<T: Add>(x: T) -> T {
    x
}
pub fn bar<T: IntoIterator<Item = u8>>(t: T) {}

///////////////////////////////////////////////////////////
// 示例:库的使用是安全的
use updated_crate::{bar, foo};

fn main() {
    foo(1);
    bar(vec![1, 2, 3].into_iter());
}

因为所有现有的使用都是新签名的实例化。

也许有些令人惊讶的是,泛化也适用于trait对象,因为每个trait都实现了自己:

// MINOR CHANGE

///////////////////////////////////////////////////////////
// 之前
pub trait Trait {}
pub fn foo(t: &dyn Trait) {}

///////////////////////////////////////////////////////////
// 之后
pub trait Trait {}
pub fn foo<T: Trait + ?Sized>(t: &T) {}

///////////////////////////////////////////////////////////
// 示例:库的使用是安全的。
use updated_crate::{foo, Trait};

struct Foo;
impl Trait for Foo {}

fn main() {
    let obj = Foo;
    foo(&obj);
}

(使用 ?Sized 是必要的,否则你就无法恢复原始签名。)

以这种方式引入泛型,有可能造成类型推断的失败。这些通常是少见的, 对于一些项目来说,可能是可以接受的故障,因为这可以通过额外的类型注解来修复。

// Breaking change example

///////////////////////////////////////////////////////////
// 之前
pub fn foo() -> i32 {
    0
}

///////////////////////////////////////////////////////////
// 之后
pub fn foo<T: Default>() -> T {
    Default::default()
}

///////////////////////////////////////////////////////////
// 示例:使用是破坏性的
use updated_crate::foo;

fn main() {
    let x = foo(); // Error: 需要类型注释
}

Major: 泛化函数以使用类型不匹配的泛型

如果泛型约束或改变了以前允许的类型,那么改变函数参数或返回类型就是一种破坏性的改变。 例如,下面增加了一个可能不被现有代码所满足的泛型约束:

// MAJOR CHANGE

///////////////////////////////////////////////////////////
// 之前
pub fn foo(x: Vec<u8>) {}

///////////////////////////////////////////////////////////
// 之后
pub fn foo<T: Copy + IntoIterator<Item = u8>>(x: T) {}

///////////////////////////////////////////////////////////
// 示例:使用是破坏性的
use updated_crate::foo;

fn main() {
    foo(vec![1, 2, 3]); // Error: `Vec<u8>` 没有实现 `Copy` 
}

Major: 从 no_std 转为要求 std

如果你的库特别支持 no_std 环境,做一个需要 std 的新版本是破坏性的改变。

// MAJOR CHANGE

///////////////////////////////////////////////////////////
// 之前
#![no_std]
pub fn foo() {}

///////////////////////////////////////////////////////////
// 之后
pub fn foo() {
    std::time::SystemTime::now();
}

///////////////////////////////////////////////////////////
// 示例:使用是破坏性的
// 这将导致no_std目标的链接失败,因为它们没有 `std` crate。
#![no_std]
use updated_crate::foo;

fn example() {
    foo();
}

缓和策略:

  • 为了避免这种情况,一种常见的方式是包含 std Cargo feature ,可以选择启用 std 支持,当该特性关闭时,库可以在no_std 环境下使用。

工具和环境的兼容性

Possibly-breaking: 改变所需的最小Rust版本

在新版本的Rust中引入使用新的特性,会破坏使用旧版本Rust的项目。 这也包括在新版本的Cargo中使用新特性,以及要求在之前在稳定版本上工作的crate中使用只在每日构建使用的特性。

一些项目出于各种原因选择在次要版本中允许这样做。通常情况下,更新到一个较新的Rust版本是比较容易的。Rust也有一个6周的快速发布周期,一些项目会在一个发布窗口期内提供兼容性(比如当前的稳定版加上之前的N个版本)。只要记住,一些大型项目可能无法迅速更新其Rust工具链。

缓和策略:

  • 使用Cargo features使新特性可选加入。
  • 为旧版本提供更大的支持窗口期。
  • 如果可能的话,复制新的标准库项目的源代码,这样你就可以继续使用旧的版本,但利用新的特性。
  • 为较早的次要版本提供一个单独的分支,可以接收重要bug修复的向后移植。
  • 请注意[cfg(version(..))]#[cfg(accessible(..))]特性,它们为新特性提供了选择机制。这些特性目前是不稳定的,只在每日构建中可用。

Possibly-breaking: 改变平台和环境要求

一个库对它所运行的环境有非常宽泛的假设,例如主机平台、操作系统版本、可用的服务、文件系统支持等等。如果你发布的新版本限制了以前支持的内容,例如需要新版本的操作系统,这可能是破坏性的变化。这些变化可能很难跟踪,因为你可能并不总是知道在一个没有自动测试的环境中,变化是否会形成破坏。

一些项目可能认为这是可以接受的破坏,特别是如果这种破坏对大多数用户来说是不可能的,或者项目没有资源来支持所有环境。 另一种值得注意的情况是,当供应商停止对某些硬件或操作系统的支持时,项目可能认为停止支持也是合理的。

缓和策略:

  • 记录你具体支持的平台和环境。
  • 在CI中,在宽泛的环境中测试你的代码。

Cargo

Minor: 增加新的Cargo特性

增加新的Cargo features通常是安全的。如果该特性引入了新的变化,带来破坏性,这可能会给那些有更严格的向后兼容性需求的项目带来困难。在这种情况下,应避免将该特性添加到 "默认" 列表中,并记录可能启用该特性的后果。

# MINOR CHANGE

###########################################################
# 之前
[features]
# ..empty

###########################################################
# 之后
[features]
std = []

Major: 移除 Cargo 特性

移除Cargo features通常是一种破坏性的改变。这将导致任何启用该特性的项目出现错误。

# MAJOR CHANGE

###########################################################
# 之前
[features]
logging = []

###########################################################
# 之后
[dependencies]
# ..logging removed

缓和策略:

  • 清楚地记录你的特性。如果有一个内部或实验性的特性,就把它标记为这样的特性,以便用户知道这个特性的状态。
  • Cargo.toml 中保留旧的特性,但删除其功能。记录该特性已被废弃,并在未来的语义化主要版本中删除。

Major: 如果改变了功能或公共条目,从特性列表中删除一个特性

如果从另一个特性中删除特性,这可能会破坏现有的用户,如果他们期望通过该特性来获得该功能。

# Breaking change example

###########################################################
# 之前
[features]
default = ["std"]
std = []

###########################################################
# 之后
[features]
default = []  # 如果包期望启用std,这可能会导致它们失败。
std = []

Possibly-breaking: 删除可选依赖

删除可选依赖可能会破坏使用你的库的项目,因为另一个项目可能通过Cargo features启用该依赖。

# Breaking change example

###########################################################
# 之前
[dependencies]
curl = { version = "0.4.31", optional = true }

###########################################################
# 之后
[dependencies]
# ..curl removed

缓和策略:

  • 清楚地记录你的特性。如果可选依赖不包括在记录的特性列表中,那么你可以决定认为改变无记录的条目是安全的。
  • 留下可选择依赖,只是在你的库中不使用它。
  • 用一个什么都不做的Cargo feature来替换这个可选依赖,并记录下它的废弃情况。
  • 使用能够实现可选的依赖的高级特性,并将这些特性记录为实现扩展功能的首选方式。例如,如果你的库对 "联网" 这样的内容有可选的支持,创建一个名为 "联网" 的泛型特性,它能够实现 "联网" 所需的可选依赖。然后记录 "联网" 特性。

Minor: 改变依赖特性

通常情况下,改变依赖上的特性是安全的,只要该特性不引入破坏性的变化。

# MINOR CHANGE

###########################################################
# 之前
[dependencies]
rand = { version = "0.7.3", features = ["small_rng"] }


###########################################################
# 之后
[dependencies]
rand = "0.7.3"

Minor: 添加依赖

增加新的依赖通常是安全的,只要新的依赖没有引入新的需求而导致破坏性的变化。 例如,在一个以前在稳定版本上工作的项目中添加一个需要每日构建的新依赖,是一个重大的变化。

# MINOR CHANGE

###########################################################
# 之前
[dependencies]
# ..empty

###########################################################
# 之后
[dependencies]
log = "0.4.11"

应用程序兼容性

Cargo项目也可能包括可执行的二进制文件,它们有自己的接口(如CLI接口、OS级交互等)。 由于这些是Cargo包的一部分,它们经常使用和共享与包相同的版本。 你需要决定是否以及如何在你对应用程序的修改中采用语义化版本约定与你的用户进行沟通。 对应用程序的潜在破坏性和兼容性的改变不胜枚举, 所以我们鼓励你使用SemVer规范的精神来指导你决定如何将版本控制应用于你的应用程序,或者至少记录你的承诺。

未来的不兼容报告

Cargo检查所有依赖中的未来不兼容警告。 这些警告是关于未来可能成为硬性错误的改变,会导致依赖在未来的rustc版本中停止构建。 如果发现任何警告,就会显示简短通知,说明发现了这些警告,并提供如何显示完整报告的说明。

例如,你可能会在构建结束时看到这样的内容:

warning: the following packages contain code that will be rejected by a future
         version of Rust: rental v0.5.5
note: to see what the problems were, use the option `--future-incompat-report`,
      or run `cargo report future-incompatibilities --id 1`

完整的报告可以通过 "cargo report future-incompatibilities --id ID" 命令来显示,或者通过使用 "--future-incompat-report" 标志再次运行构建。 之后,开发者应该将他们的依赖更新到问题得到修复的版本,或者与依赖的开发者合作,帮助解决这个问题。

配置

这个特性可以通过 .cargo/config.toml 中的 [future-incompat-report] 部分来进行配置。目前,支持的选项有:

[future-incompat-report]
frequency = "always"

支持的可选值是 "always""never" ,其控制在 cargo build / cargo check 结束时是否打印出信息。

报告构建时间

--timings 选项提供了一些关于每次编译所需时间的信息,并跟踪时间推移且发送信息。

cargo build --timings

这将在 target/cargo-timings/cargo-timing.html 中写入一个HTML报告。如果你想查看更早的运行情况,也会将报告的副本写到同一目录下,文件名有时间戳。

阅读图表

在输出中,有两个图表。"unit" 图显示每个单元随时间变化的持续时间。一个 "unit" 是单一的编译器调用。 有几行显示了当一个单元结束时,哪些额外的单元被 "解锁" 。也就是说,它显示现在允许运行的新单元,因为它们的依赖已经全部完成。 将鼠标悬停在一个单元上,可以突出这些线条。这可以帮助直观地看到依赖的关键路径。由于单元可能以不同的顺序完成,这在运行中可能会发生变化。

"codegen" 的时间以淡紫色突出显示。在某些情况下,构建管道允许单元在其依赖执行代码生成时开始。 这一信息并不总是显示(例如,二进制单元不显示代码生成开始时间)。

"custom build" 单元是 build.rs 脚本,运行时以橙色显示。

第二张图显示了Cargo在一段时间内的并发量。背景表示CPU使用率。这三条线是:

  • "等待" (红色) — 这是等待CPU槽开放的单元的数量。
  • "不活跃" (蓝色) — 这是正在等待其依赖完成的单元的数量。
  • "活跃" (绿色) — 这是目前正在运行的单元的数量。

注意:这并不显示编译器本身的并发量。 rustc 通过 "作业服务" 与Cargo协调,以保持在并发量限制之内。目前这主要适用于代码生成阶段。

编译时间的提示:

  • 寻找缓慢的依赖。
    • 检查它们是否有你可能希望考虑禁用的特性。
    • 考虑尝试完全删除依赖。
  • 寻找crate在不同版本中被多次构建。尝试从依赖图中删除旧版本。
  • 将大crate拆成小块。
  • 如果有大量的crate在一个crate上出现瓶颈,那么就把注意力集中在改善这一crate上,以提高并行性。

不稳定的特性

实验性的Cargo 特性只在nightly channel"每日构建"中提供。我们鼓励你尝试使用这些特性,看看它们是否符合你的需求,以及是否有问题或难题。请查看下面列出的链接的问题跟踪,了解更多关于该特性的信息,如果你想获得未来的更新,请点击GitHub订阅按钮。

经过一段时间后,如果该特性没有任何重大问题,它可以被stabilized,这将使它在当前每日构建发布的版本到达稳定通道后,就可以在稳定版上使用(6到12周不等)。

根据特性的工作方式,有三种不同的方式可以启用不稳定的特性。

  • 按照 Cargo.toml 新语法,在顶部任意表之前设置 cargo-features 键。例如:

    # 这里指定启用哪些新的 Cargo.toml 特性。
    cargo-features = ["test-dummy-unstable"]
    
    [package]
    name = "my-package"
    version = "0.1.0"
    im-a-teapot = true  # 这是由 test-dummy-unstable 启用的新选项。
    
  • 新的命令行标志、选项和子命令需要同时包含 -Z unstable-options CLI选项。 例如,新的 --out-dir 选项只在每日构建中可用。

    cargo +nightly build --out-dir=out -Z unstable-options

  • -Z命令行标志用于启用可能没有接口的新功能,或者接口还没有设计好,或者用于影响Cargo多个部分的更复杂功能。例如,mime-on-use功能可以用以下方式启用:

    cargo +nightly build -Z mtime-on-use

    运行 cargo -Z help 可以查看可用的标志列表。

    可以用 -Z 标志配置的内容也可以在cargo config file (.cargo/config.toml)的 unstable 表中设置。比如说:

    [unstable]
    mtime-on-use = true
    build-std = ["core", "alloc"]
    

下面描述的每个新特性都将解释如何使用它。

不稳定特性列表

  • 不稳定特定特性
  • 构建脚本和链接
    • Metabuild — 提供声明式的构建脚本。
  • 解析器和特性
  • 输出行为
    • out-dir — 添加一个目录,将制品复制到该目录。
    • Different binary name — 为构建的二进制文件指定一个与crate名称分开的名称。
  • 编译行为
    • mtime-on-use — 在每次使用依赖时,更新其最后修改的时间戳,以提供一种机制来删除未使用的制品。
    • doctest-xcompile — 支持运行带有 --target 标志的文档测试。
    • build-std — 构建标准库而不是使用预先构建的二进制文件。
    • build-std-features — 设置与标准库一起使用的特性。
    • binary-dep-depinfo — 致使dep-info文件跟踪二进制文件的依赖。
    • panic-abort-tests — 允许用 "中止" 恐慌策略运行测试。
    • crate-type — 支持向编译器传递crate类型。
    • keep-going — 尽可能多地构建,而不是在第一个错误时就中止。
  • rustdoc
  • Cargo.toml 扩展
  • 信息和元数据
    • Build-plan — 发送关于哪些命令将被运行的JSON信息。
    • unit-graph — 为Cargo的内部图结构发送JSON。
    • cargo rustc --print — 用 --print 调用rustc,以显示来自 rustc 的信息。
  • 配置
    • config-include — 增加配置文件包含其他文件的能力。
    • cargo config — 增加新的子命令用于查看配置文件。
  • 注册中心
    • credential-process — 增加对从外部认证程序获取注册中心令牌的支持。
    • cargo logout — 添加 logout 命令,以删除当前保存的注册中心令牌。
    • sparse-registry — 增加从静态文件HTTP注册中心获取的支持(sparse+)。
    • publish-timeout — 控制上传crate和在索引中可用之间的超时。
    • registry-auth — 增加对认证注册的支持,并使用非对称加密生成注册中心认证令牌。

接受特性

这个永久不稳定的标志使得可以使用只有列出的一组不稳定的特性。具体来说,如果你传递了 -Zallow-features=foo,bar ,你将继续能够向 cargo 传递 -Zfoo-Zbar ,但将无法传递 -Zbaz 。你可以传递一个空字符串(-Zallow-features=)来禁止所有不稳定的特性。

-Zallow-features也限制了哪些不稳定的特性可以被传递给 Cargo.toml 中的 cargo-features 条目。例如,如果你想接受

cargo-features = ["test-dummy-unstable"]

如果 test-dummy-unstable 是不稳定的,那么 -Zallow-features= 也不接受该特性,而 -Zallow-features=test-dummy-unstable 则接受。

传递给cargo的 -Zallow-features 的特性列表也会传递给cargo最终调用的任何Rust工具(如 rustcrustdoc )。因此,如果你运行 cargo -Zallow-features= ,就不能使用不稳定的Cargo_或Rust特性。

no-index-update

-Z no-index-update 标志确保Cargo不会尝试更新注册中心索引。这是为Crater等工具准备的,这些工具会发布很多Cargo命令,你想避免每次更新索引的网络潜在行为。

mtime-on-use

  • Original Issue: #6477
  • Cache usage meta tracking issue: #7150

-Z mtime-on-use 标志是一个实验性的,让Cargo更新使用过的文件的时间戳,以便像cargo-sweep这样的工具更容易发现哪些文件是过时的。对于许多工作流程来说,这需要在 所有 cargo的调用中进行设置。为了更实用,在 .cargo/config.toml 中设置 unstable.mtime_on_use 标志或相应的环境变量,将对所有每日构建cargo的调用应用 -Z mtime-on-use 。(config标志在稳定版本中被忽略)

avoid-dev-deps

当运行 cargo installcargo build 等命令时,Cargo目前需要下载 dev-依赖,即使它们不被使用。 -Z avoid-dev-deps标志允许Cargo在不需要dev-依赖时避免下载它们。如果跳过了dev-依赖,将不会生成 Cargo.lock 文件。

minimal-versions

注意: 不建议使用这个功能。因为它为所有的横向依赖强制执行最小版本,它的作用是有限的,因为不是所有的外部依赖都声明适当的版本下限。 我们打算在未来对其进行修改,只对直接依赖执行最小版本。

当生成 Cargo.lock 文件时, -Z minimal-versions 标志将把依赖解析为能满足要求的最小语义化版本(而不是最高版本)。

这个标志的用途是在持续集成过程中检查 Cargo.toml 中指定的版本是否正确反映了你实际使用的最小版本。 也就是说,如果 Cargo.toml 说明 foo = "1.0.0",就不会意外地依赖 foo 1.5.0 中增加的特性。

out-dir

这个特性允许你指定制品在构建后将被复制到的目录。通常,制品只被写入 target/releasetarget/debug 目录。然而,确定确切的文件名可能很棘手,因为你需要解析JSON输出。--out-dir 标志使其更容易预计访问制品。注意,制品是复制的,所以原件仍然在 target 目录中。例子:

cargo +nightly build --out-dir=out -Z unstable-options

这也可以在 .cargo/config.toml 文件中指定。

[build]
out-dir = "out"

doctest-xcompile

这个标志改变了 cargo test 在传递目标时处理文档测试的行为。目前,如果传递的目标与主机不同,cargo将直接跳过文档测试。如果有这个标志,cargo将继续正常工作,将测试传给文档测试,同时也将 --target 选项传给它,以及启用 -Zunstable-features --enable-per-target-ignores,并将 .cargo/config.toml 的信息传给它。更多信息请参见 rustc issue。

cargo test --target foo -Zdoctest-xcompile

新的 dir-name 属性

target/ 下生成的一些路径是约定俗成的 "构建协议" , 被 cargo 作为更大的项目构建的一部分来调用。 因此,为了保留现有的行为,还有一个新的属性 dir-name ,当没有指定时,默认为配置文件的名称。比如说:

[profile.release-lto]
inherits = "release"
dir-name = "lto"  # 发送到target/lto,而不是target/release-lto
lto = true

Build-plan

build 命令的 --build-plan 参数将输出JSON信息,说明哪些命令将被运行,而不需要实际执行。这在与其他构建工具集成时很有用。 例子:

cargo +nightly build --build-plan -Z unstable-options

Metabuild

Metabuild是声明式构建脚本的特性。你不用写 build.rs 脚本,而是在 Cargo.toml 中的 metabuild 键中指定一个构建依赖项列表。 构建脚本会自动生成,按顺序运行每个构建依赖项。Metabuild包可以从 Cargo.toml 中读取元数据以指定其行为。

Cargo.toml 的顶部包含 cargo-features ,在 package 中包含 metabuild 键, 在 build-dependencies 中列出依赖项,并在 package.metadata 中添加metabuild包需要的元数据。 例子:

cargo-features = ["metabuild"]

[package]
name = "mypackage"
version = "0.0.1"
metabuild = ["foo", "bar"]

[build-dependencies]
foo = "1.0"
bar = "1.0"

[package.metadata.foo]
extra-info = "qwerty"

Metabuild包应该有一个名为 metabuild 的公共函数,执行与普通 build.rs 脚本相同的动作。

public-dependency

'public-dependency' 特性允许将依赖标记为 'public' 或 'private' 。当这个特性被启用时,附加的信息会传递给 rustc,以使 'exported_private_dependencies' 链接项能够正常工作。

这需要在 cargo-features 中设置适当的键。

cargo-features = ["public-dependency"]

[dependencies]
my_dep = { version = "1.2.3", public = true }
private_dep = "2.0.0" # 默认情况下,将是 'private' 。

build-std

build-std 特性使Cargo能够自己编译标准库,作为crate图编译的一部分。这个功能曾称为 "std-aware Cargo"。 这个功能仍处于开发的早期阶段,也是Cargo可能增加的重要特性。这是大的特性文档,即使现在以最小形式存在, 如果想保持最新,请关注跟踪仓库和issues。

目前实现的功能是在名为 -Z build-std 的标志后。这个标志表明,Cargo应该使用与主构建本身相同的配置文件从源代码中编译标准库。 请注意,要实现这个功能,你需要有标准库的源代码,目前唯一支持的方法是添加 rust-src rust rustup组件。

$ rustup component add rust-src --toolchain nightly

现在还要求 -Z build-std 标志与 --target 标志组合。请注意,并不是强制进行交叉编译,只是要求以某种形式传递 --target

使用方法如下:

$ cargo new foo
$ cd foo
$ cargo +nightly run -Z build-std --target x86_64-unknown-linux-gnu
   Compiling core v0.0.0 (...)
   ...
   Compiling foo v0.1.0 (...)
    Finished dev [unoptimized + debuginfo] target(s) in 21.00s
     Running `target/x86_64-unknown-linux-gnu/debug/foo`
Hello, world!

这里,在调试模式下重新编译了标准库,并带有调试断言(就像 src/main.rs 被编译一样) ,最后所有内容都被连接在一起。

使用 -Z build-std 将隐式地编译稳定版本 crate corestdallocproc_macro 。 如果你使用 cargo test ,它也将编译 test crate。如果你的工作环境不支持其中的一些crate,那么可以向 -Zbuild-std 传递参数。

$ cargo +nightly build -Z build-std=core,alloc

这里的值是以逗号分隔的要构建的标准库crate的列表。

要求

总结起来,使用 -Z build-std 的需求清单是:

  • 你必须通过 rustup component add rust-src 安装libstd的源代码。
  • 你必须传递 --target
  • 你必须同时使用每日构建 Cargo 和 Rustc
  • -Z build-std 标志必须传递给所有 cargo 调用。

报告错误并提供帮助

-Z build-std 特性正处于开发的早期阶段! Cargo的这项功能有非常长的历史,范围也非常大,而这只是一个开始。如果你想报告bug,请把它们报告给:

此外,如果你想查看尚未实现的特性,或者如果某些内容没有完全按照你希望的方式工作, 请随时查看库的问题跟踪,如果那里没有,请提交新问题!

build-std-features

这个标志是 -Zbuild-std 特性标志的成员。这将配置在构建标准库时为标准库本身启用的特性。 目前默认启用的特性是 backtracepanic_unwind 。这个标志期望逗号分隔的列表,如果提供的话,将覆盖默认启用的特性列表。

binary-dep-depinfo

  • Tracking rustc issue: #63012

-Z binary-dep-depinfo 标志使 Cargo 将同样的标志转发给 rustc ,这将使 rustc 在 "dep info" 文件(扩展名为 .d )中包含所有二进制依赖的路径。 Cargo会使用这些信息进行变化检测(如果有任何二进制的依赖发生变化,那么crate就会被重新构建)。 主要的用例是编译器本身,它对标准库有隐含的依赖,否则就不会追踪到变化检测。

panic-abort-tests

-Z panic-abort-tests 标志将启用每日构建支持,以 -Cpanic=abort 编译测试连接crate。如果没有这个标志,Cargo会用 -Cpanic=unwind 来编译测试, 以及所有依赖,因为这是 test-the-rate 知道如何操作的唯一方式。然而,从rust-lang/rust#64158开始,test-crate 支持 -C panic=abort ,并支持每个进程的测试,可以帮助避免多次编译crate图。

目前还不清楚如何在Cargo中稳定这一特性,但我们希望能以某种方式稳定下来。

keep-going

cargo build --keep-going (以及类似的 checktest 等)将尽可能多地构建依赖图中的crate,而不是在第一个失败的crate中止构建。

例如,如果当前包依赖于 failsworks 两个依赖项,其中一个构建失败,cargo check -j1 可能也可能不会构建成功(取决于Cargo选择先运行哪一个构建),而 cargo check -j1 --keep-going 肯定会同时运行两个构建,即使先运行的那个构建失败。

必须使用 -Z unstable-options 命令行选项,以便在尚未稳定时使用 --keep-going

cargo check --keep-going -Z unstable-options

config-include

配置文件中的 include 键可以用来加载另一个配置文件。它需要相对于配置文件的另一个文件路径的字符串,或者字符串列表。需要 -Zconfig-include 命令行选项。

# .cargo/config
include = '../../some-common-config.toml'

配置文件的值首先从包含路径中加载,然后在其上合并配置文件本身的值。

这可以与config-cli搭配使用,以指定从命令行加载的文件。传递一个配置文件的路径作为 --config 的参数:

cargo +nightly -Zunstable-options -Zconfig-include --config somefile.toml build

CLI路径是相对于当前工作目录的。

target-applies-to-host

  • Original Pull Request: #9322
  • Tracking Issue: #9453

曾经,Cargo对环境变量中的 linkerrustflags 配置选项以及 [target] 是否遵从构建脚本、插件和其他始终为主机平台构建的制品的行为有些不一致。当 --target 没有通过时,Cargo会遵从构建脚本的 linkerrustflags ,与所有其他编译制品相同。然而,当 --target 通过时,Cargo遵从 [target.<host triple>]linker ,而不接受任何 rustflags 配置。这种双重行为让人困惑,也让人难以正确地配置构建,在这种情况下,主机三元组和目标三元组恰好是相同的,但打算在构建主机上运行的制品仍应以不同方式配置。

-Ztarget-applies-to-host 在Cargo配置文件中启用顶层的 target-applies-to-host 设置,允许用户为这些属性选择不同(和更一致)的行为。当 target-applies-to-host 在配置文件中未设置或设置为 true 时,现有的Cargo行为将被保留(不过请查看 -Zhost-config ,它改变了这个默认值)。当它被设置为 false 时,无论 --target 是否被传递给Cargo, [target.<host triple>]RUSTFLAGS[build] 的选项都不会被主机制品所尊从。要定制打算在主机上运行的制品,请使用 [host] (host-config)。

将来, target- appliesto -host 可能最终会默认为 false ,以提供更健全和一致的默认行为。

# config.toml
target-applies-to-host = false
cargo +nightly -Ztarget-applies-to-host build --target x86_64-unknown-linux-gnu

host-config

  • Original Pull Request: #9322
  • Tracking Issue: #9452

配置文件中的 host 键可以用来向主机构建目标传递标志,比如交叉编译时必须在主机系统而不是目标系统上运行的构建脚本。 它同时支持通用的和特定于主机架构的表。匹配的host arch表优先于通用的host表。

它需要设置 -Zhost-config-Ztarget-applies-to-host 命令行选项,并且在Cargo配置文件中设置 target-applies-to-host = false

# config.toml
[host]
linker = "/path/to/host/linker"
[host.x86_64-unknown-linux-gnu]
linker = "/path/to/host/arch/linker"
rustflags = ["-Clink-arg=--verbose"]
[target.x86_64-unknown-linux-gnu]
linker = "/path/to/target/linker"

x86_64-unknown-linux-gnu 主机上构建时,上面的通用 host 表将被完全忽略,因为 host.x86_64-unknown-linux-gnu 表具有优先权。

设置 -Zhost-configtarget-applies-to-host 的默认值从 true 改为 false

cargo +nightly -Ztarget-applies-to-host -Zhost-config build --target x86_64-unknown-linux-gnu

unit-graph

--unit-graph 标志可以传递给任何构建命令(buildcheckruntestbenchdoc等), 以向标准输出发送JSON对象,表示Cargo的内部单元图。实际上没有任何内容被构建, 命令在打印后立即返回。每个 "单元" 对应于编译器的一次执行。这些对象还包含每个单元所依赖的单元。

cargo +nightly build --unit-graph -Z unstable-options

这种结构提供了Cargo所看到的更完整的依赖的视图。特别是,"features" 字段支持新的特性解析器, 依赖可以用不同的特性构建多次。 cargo metadata 从根本上不能表示不同依赖种类之间的特性关系, 当前特性取决于运行哪个命令,选择哪个包和目标。此外,它还可以提供包内依赖的细节,如构建脚本或测试。

下面是对JSON结构的描述:

{
  /* 是JSON输出结构的版本。如果有向后不兼容的变化,这个值将增加。 */
  "version": 1,
  /* 所有构建单位的数组。 */
  "units": [
    {
      /* 一个不透明的字符串,表示该包。关于包的信息可以从 `cargo metadata` 中获得。 */
      "pkg_id": "my-package 0.1.0 (path+file:///path/to/my-package)",
      /* Cargo目标。关于这些字段的更多信息,请参见 `cargo metadata` 文档。 https://doc.rust-lang.org/cargo/commands/cargo-metadata.html */
      "target": {
        "kind": ["lib"],
        "crate_types": ["lib"],
        "name": "my-package",
        "src_path": "/path/to/my-package/src/lib.rs",
        "edition": "2018",
        "test": true,
        "doctest": true
      },
      /* 本单元的配置文件设置。这些值可能与配置清单中定义的配置文件不一致。
         单位可以使用修改的配置文件设置。例如,"panic" 设置可以被覆盖,用于测试,以迫使它 "unwind" 。 */
      "profile": {
        /* 这些设置是由配置文件名称衍生而来。 */
        "name": "dev",
        /* 字符串表示的优化级别。 */
        "opt_level": "0",
        /* 字符串表示的LTO设置。 */
        "lto": "false",
        /* 编码单位是一个整数。 `null` 表示它应该使用编译器的默认值。 */
        "codegen_units": null,
        /* 整数表示的调试信息等级。 `null` 表示它应该使用编译器的默认值 (0) 。 */
        "debuginfo": 2,
        /* 是否启用了调试断言。 */
        "debug_assertions": true,
        /* 是否启用了溢出检查。 */
        "overflow_checks": true,
        /* 是否启用了rpath。 */
        "rpath": false,
        /* 是否启用了增量编译。 */
        "incremental": true,
        /* 恐慌的策略,"unwind" 或 "abort" 。 */
        "panic": "unwind"
      },
      /* 为哪个平台建立的目标。如果值为 `null` ,则表明它是为主机建立的。
         否则,它是目标三元组的字符串(如 "x86_64-unknown-linux-gnu" )。 */
      "platform": null,
      /* 该单元的 "mode" 。有效值:

         * "test" — 使用 `rustc` 作为测试来构建。
         * "build" — 使用 `rustc` 构建。
         * "check" — 在 "check" 模式下使用 `rustc` 构建。
         * "doc" — 使用 `rustdoc` 构建。
         * "doctest" — 使用 `rustdoc` 进行测试。
         * "run-custom-build" — 表示构建脚本的执行。
      */
      "mode": "build",
      /* 在这个单元上启用的特性数组字符串。 */
      "features": ["somefeat"],
      /* 这是否是一个标准库单元,是不稳定的 build-std 功能的一部分。如果没有设置,视为 `false` 。 */
      "is_std": false,
      /* 该单元的依赖数组。 */
      "dependencies": [
        {
          /* 依赖的 "单位" 数组中的索引。 */
          "index": 1,
          /* 此依赖项将被称为的名称。 */
          "extern_crate_name": "unicode_xid",
          /* 这个依赖是否是 "public" 的,是不稳定的公共依赖特性的一部分。如果没有设置,则不启用公共依赖特性。*/
          "public": false,
          /* 该依赖是否被注入到 prelude 中,目前由 build-std 功能使用。如果没有设置,视为 `false` 。 */
          "noprelude": false
        }
      ]
    },
    // ...
  ],
  /* "单位" 数组中作为依赖图 "根" 的索引数组。 */
  "roots": [0],
}

Profile rustflags option

这个特性在 "[profile]" 部分提供了新的选项,用来指定直接传递给rustc的标志。可以像这样启用:

cargo-features = ["profile-rustflags"]

[package]
# ...

[profile.release]
rustflags = [ "-C", "..." ]

rustdoc-map

这个特性增加了传递给 rustdoc 的配置,这样它就可以在依赖没有文档的情况下, 生成指向文档托管在其他地方的依赖的链接。首先,将其添加到 .cargo/config 中。

[doc.extern-map.registries]
crates-io = "https://docs.rs/"

然后,在构建文档时,使用以下标志,使链接的依赖链接到 docs.rs

cargo +nightly doc --no-deps -Zrustdoc-map

registries 表包含了注册中心名称与要链接的URL的映射。URL可以有 {pkg_name}{version} 的标记, 这些标记会被替换成相应的值。如果两者都没有指定,那么Cargo默认会在URL的末尾添加 {pkg_name}/{version}/

另一个配置设置可用于重定向标准库链接。默认情况下,rustdoc 创建链接到 https://doc.rust-lang.org/nightly/ 。 要改变这种行为,请使用 doc.extern-map.std 设置。

[doc.extern-map]
std = "local"

值为 "local" 意味着链接到在 rustc 系统根中找到的文档。如果你使用的是rustup,这个文档可以用 rustup component add rust-docs 来安装。

默认值是 "remote"

该值也可以接受一个自定义位置的URL。

per-package-target

per-package-target 特性在配置清单中增加了两个键:package.default-targetpackage.forced-target 。 第一个键使包在默认情况下 (即没有传递 --target 参数时)为某个目标进行编译。第二种是使包总是为该目标编译。

Example:

[package]
forced-target = "wasm32-unknown-unknown"

在这个例子中,crate总是为 wasm32-unknown-unknown 构建的,例如,因为它将被用作运行在主机(或在命令行上提供)目标上的主程序的插件。

artifact-dependencies

  • Tracking Issue: #9096
  • Original Pull Request: #9992

允许 Cargo 包依赖 bincdylibstaticlib crate,并在编译时使用这些crate构建的制品。

使用 -Z bindeps 运行 cargo 来启用这一功能。

示例: 在构建脚本中使用 cdylib 制品

消耗包中的 Cargo.toml ,为特定的构建目标将 bar 库构建为 cdylib

[build-dependencies]
bar = { artifact = "cdylib", version = "1.0", target = "wasm32-unknown-unknown" }

build.rs 中的构建脚本一起。

fn main() {
  wasm::run_file(std::env::var("CARGO_CDYLIB_FILE_BAR").unwrap());
}

示例: 在二进制文件中使用 binary 制品和它的库。

消耗包中的 Cargo.toml ,构建 bar 二进制文件作为制品,同时将其作为库提供…

[dependencies]
bar = { artifact = "bin", version = "1.0", lib = true }

与可执行文件一起使用 main.rs

fn main() {
  bar::init();
  command::run(env!("CARGO_BIN_FILE_BAR"));
}

sparse-registry

sparse-registry 特性允许cargo与通过普通HTTP而不是git提供的远程注册中心进行交互。这些注册中心可以通过以 sparse+http://sparse+https:// 开头的URL识别。

当通过HTTP获取索引元数据时,Cargo 只下载相关crate的元数据,这可以节省大量时间和带宽。

sparse索引格式与基于git的索引的签出是一样的。

registries.crates-io.protocol 配置选项可以用来设置 crates.io 的默认协议。这个选项需要启用 -Z sparse-registry

  • sparse — 使用 sparse 索引。
  • git — 使用 git 索引。
  • 如果选项没有设置,若启用 -Z sparse-registry ,它将是sparse索引,否则它将是git索引。

Cargo在本地缓存crate元数据文件,并从服务器上捕获每个条目的 ETagLast-Modified HTTP头。 当刷新crate元数据时,Cargo会发送 If-None-MatchIf-Modified-Since 头,如果本地缓存有效,则允许服务器以HTTP 304响应,以节省时间和带宽。

publish-timeout

配置文件中的 publish.timeout 键可以用来控制 cargo publish 在将包发布到注册中心和它在本地索引中可用之间的等待时间。

如果超时为 0 就不会发生任何检查。

它需要设置 -Zpublish-timeout 命令行选项。

# config.toml
[publish]
timeout = 300  # 按秒

registry-auth

通过在注册中心索引的config.json中添加配置选项,使Cargo在API请求、crate下载和sparse索引更新中包含授权令牌。

要使用这个特性,注册中心服务器必须在 config.json 中包含 "auth-required": true ,并且必须在Cargo命令行中传递 -Z registry-auth 标志。

当使用sparse协议时,Cargo会在获取任何其他文件之前尝试获取 config.json 文件。 如果服务器的回应是HTTP 401,那么Cargo将认为注册中心需要认证,并重新尝试请求 config.json ,其中包含认证令牌。

在认证失败 (或缺少认证令牌) 时,服务器可能包括 WWW-Authenticate 头和 Cargo login_url 信息,以表明用户可以去哪里获得令牌。

WWW-Authenticate: Cargo login_url="https://test-registry-login/me

This same flag is also used to enable asymmetric authentication tokens.

增加对Cargo的支持,以便在不通过网络发送私密信息的情况下对用户进行认证。

config.tomlcredentials.toml 文件中,有名为 private-key 的字段,它是以秘密的 subset of PASERK格式的私钥,用于签署非对称令牌。

可以用 cargo login --generate-keypair 生成密钥对,这将:

  • 以目前推荐的方式生成公钥/私钥对。
  • 保存私钥在 credentials.toml
  • 格式打印公钥 PASERK public

建议将 private-key 保存在 credentials.toml 中。在 config.toml 中也支持,主要是为了使用相关的环境变量来设置,这也是在CI背景下提供的推荐方式。这种设置就是为 token 字段设置秘密令牌的方式。

还有可选字段 private-key-subject ,是由注册中心选择的字符串。 这个字符串将作为非对称令牌的一部分,不应该是秘密的。 是为 "中央CA服务器授权此行为的加密证明" 这样的极少用例准备的。 Cargo要求它为非空格可打印的ASCII。需要非ASCII数据的注册中心应该对其进行base64编码。

这两个字段都可以用 cargo login --registry=name --private-key --private-key-subject="subject" 来设置,它将提示你输入密钥值。

注册中心最多可以设置 private-keytokencredential-process 之一。

所有PASETO将包含 iat ,即ISO 8601格式的当前时间。Cargo将酌情包含以下内容:

  • sub一个可选的、非秘密的字符串,由注册中心选择,预期在每次请求时都会被取得。该值将是 config.toml 文件中的 private-key-subject
  • mutation 如果存在, 表示该请求是一个改变操作(如果不存在,则是一个只读操作),必须是字符串 publishyankunyank 之一。
    • name 与此请求有关的crate的名称。
    • vers 与此请求相关的包的版本字符串。
    • cksum 箱子内容的SHA256哈希值,是由64个小写的十六进制数字组成的字符串,只有当 mutation 等于 publish 时才必须出现。
  • challenge 从该服务器的session 401/403中收到的质询字符串。发出质询的注册中心必须跟踪哪些质询已经 issued/used ,并且在同一有效期内不接受特定的质询超过一次(避免跟踪每一个曾经发出的质询)。

"footer" (这是签名的一部分)将是一个UTF-8格式的JSON字符串,包括:

  • url 符合RFC 3986标准的URL,cargo从那里得到config.json文件。
    • 如果这是有HTTP索引的注册中心,那么这就是所有索引查询相对的基本URL。
    • 如果这是有GIT索引的注册中心,它是Cargo用来克隆索引的URL。
  • kid 用于签署请求的私钥的标识,使用PASERK IDs 标准。

PASETO包括被签名的信息,因而服务器不必为了检查签名而从请求中重构确切字符串。 服务器需要检查签名比对PASETO中的字符串是否有效,以及该字符串的内容是否与请求相符。 如果该请求应该有一个声明,但在PASETO中没有,那么该请求必须被拒绝。

credential-process

credential-process 特性增加了一个配置设置,通过调用一个外部进程来获取注册中心认证令牌。

Token认证被 cargo logincargo publishcargo ownercargo yank 命令所使用。此外,该特性增加新的 cargo logout 命令。

要使用这个特性,你必须在命令行中传递 -Z credential-process 标志。 此外,你必须删除当前保存在 credentials file 中的任何当前令牌(这可以通过新的 logout 命令来完成)。

credential-process 配置

要配置运行哪个进程来获取令牌,在 config fileregistry 表中指定进程:

[registry]
credential-process = "/usr/bin/cargo-creds"

如果你想对一个特定的注册中心使用不同的进程,可以在 registries 表中指定。

[registries.my-registry]
credential-process = "/usr/bin/cargo-creds"

该值可以是用空格分隔参数的字符串,也可以是TOML字符串数组。

命令行参数允许特殊的占位符,这些占位符将被替换成相应的值:

  • {name} — 注册中心的名称。
  • {api_url} — 注册中心 API 端点的基本URL。
  • {action} — 认证动作(如下所述)。

带有 cargo: 前缀的进程名称会从cargo下的 libexec 目录中加载。Cargo中包含了几个实验性的证书包装器,以提供对它们的便利访问:

[registry]
credential-process = "cargo:macos-keychain"

目前的包装器是:

  • cargo:macos-keychain: 使用macOS Keychain来存储令牌。
  • cargo:wincred: 使用Windows证书管理器来存储令牌。
  • cargo:1password: 使用1password op CLI来存储令牌。你必须从 1password 网站安装 op CLI。你必须至少运行一次op signin,并加上适当的参数(如 op signin my.1password.com user@example.com ),除非你提供地址和电子邮件参数。除非设置了适当的 OP_SESSION 环境变量,否则每次请求时都需要主密码。它支持以下命令行参数。
    • --account: 使用的账户简写名称。
    • --vault: 使用的保险名称。
    • --sign-in-address: 登录地址,是一个网址,如 my.1password.com
    • --email: 用来登录的电子邮件地址。

GNOME libsecret 有包装器,可以在Linux系统上存储令牌。由于构建的限制,这个包装器不能作为预编译的二进制文件使用。 这可以手动构建和安装。首先,使用你的系统包管理器安装 libsecret (例如,sudo apt install libsecret-1-dev)。 然后用cargo install cargo-credential-gnome-secret 构建并安装包装器。在配置中,使用二进制文件的路径,如下所示:

[registry]
credential-process = "cargo-credential-gnome-secret {action}"

credential-process 接口

Cargo支持两种不同的token进程。简单的 "basic" 类型只在Cargo需要令牌时才会被调用。 这是为了与密码管理器进行简单而方便的集成,通常可以使用已有的工具。 更高级的 "Cargo" 类型支持作为命令行参数传递的不同动作。 这样做的目的是为了获得更好的集成体验,代价是需要一个Cargo特定的进程来粘合到密码管理器上。 Cargo会根据 "credential-process" 的定义来决定支持哪种类型。 如果它包含 {action} 参数,那么它就会使用高级样式,否则它就假定它只支持 "basic" 样式。

基础认证器

基础认证器是在stdout上返回一个令牌的进程。新行将被修整。该进程继承了用户的 stdin 和 stderr 。它应在成功时退出0,在错误时退出非零。

在这种形式下,不支持 cargo logincargo logout ,如果使用,会返回一个错误。

Cargo认证器

Cargo和进程之间的协议是非常基本的,目的是确保认证过程尽可能简单。 Cargo将执行进程,其 {action} 参数表明要执行的动作。

  • store — 将给定令牌可靠存储。
  • get —从存储中获取令牌。
  • erase — 从存储中移除令牌。

cargo login 命令使用 store 来保存令牌。需要认证的命令,如 cargo publish ,使用 get 检索令牌。 cargo logout 使用 erase 命令来删除令牌。

进程继承了用户的stderr,所以进程可以显示信息。 有些值是通过环境变量传递进来(见下文)。预期的交互作用是:

  • store — 令牌被发送到进程的stdin中,以换行结束。进程应该根据注册中心的名称来存储令牌。如果进程失败,它应该以非零的退出状态退出。

  • get — 进程应将令牌发送到其stdout(尾部的换行将被修整)。进程继承用户的stdin,如果它需要接收输入的话。

    如果进程无法完成请求,它应该以非零退出代码退出。

  • erase — 该进程应该删除与注册中心名称相关联的令牌。如果没有找到令牌,进程应该以0状态退出。

环境

以下环境变量提供给被执行的命令:

  • CARGO — 执行命令的 cargo 二进制文件的路径。
  • CARGO_REGISTRY_INDEX_URL — 注册中心索引的URL。
  • CARGO_REGISTRY_NAME_OPT — 注册中心的可选名称。不应作为存储键使用。并不总是可用的。

cargo logout

增加新的 cargo logout 命令,使其更容易从存储中删除令牌。这同时支持 credentials file 令牌和 credential-process 令牌。

当与 credentials 文件令牌一起使用时,它需要 -Z unstable-options 命令行选项:

cargo logout -Z unstable-options

当与 credential-process 配置一起使用时,使用 -Z credential-process 命令行选项:

cargo logout -Z credential-process

cargo config

cargo config 子命令提供了一种显示cargo加载的配置文件的方法。 它目前包括 get 子命令,可以接受可选的配置文件来显示。

cargo +nightly -Zunstable-options config get build.rustflags

如果不包含配置值,它将显示所有的配置值。参见 --help 输出,了解更多可用的选项。

doctest-in-workspace

-Z doctest-in-workspace 标志改变了运行文档测试时使用的当前工作目录的行为。 曾经,Cargo运行 rustdoc --test 时是相对于包的根目录,路径相对于根目录。 然而,这与 rustcrustdoc 在工作空间的正常运行方式不一致,它们是相对于工作空间根目录运行。 这种不一致会导致各种问题,比如在传递 RUSTDOCFLAGS 时,使用相对路径,或者处理诊断输出。

-Z doctest-in-workspace 标志使cargo切换到从工作空间的根运行 rustdoc 。 它还将 --test-run-directory 传递给 rustdoc ,以便在运行测试时,从包的根目录运行。 这保留了向后的兼容性,并且与正常的单元测试的运行方式一致。

rustc --print

cargo rustc --print=VAL--print 标志转发给 rustc ,以便从 rustc 中提取信息。 在运行 rustc 时,会有相应的 --print 标志, 然后立即退出,不进行编译。将其作为cargo标志暴露,允许cargo根据当前配置注入正确的目标和RUSTFLAGS。

主要的使用情况是运行 cargo rustc --print=cfg 来获得相应目标的配置值,并受到任何其他RUSTFLAGS的影响。

不同的二进制名称

different-binary-name 特性允许设置二进制文件的文件名,而不必遵守对crate名称的限制。比如,crate名称只能使用 alphanumeric 字符或 -_ ,并且不能为空。

filename 参数 包含二进制扩展名,cargo 将计算出适当的扩展名并将其用于二进制文件。

参数 filename 只在配置清单的 [[bin]] 部分可用。

cargo-features = ["different-binary-name"]

[package]
name =  "foo"
version = "0.0.1"

[[bin]]
name = "foo"
filename = "007bar"
path = "src/main.rs"

scrape-examples

-Z rustdoc-scrape-examples 标志告诉 Rustdoc 在当前工作空间中搜索crate的函数调用。 然后,这些调用点会被包含在文档中。你可以像这样使用该标志:

cargo doc -Z unstable-options -Z rustdoc-scrape-examples

默认情况下,Cargo会从记录的包的例子目标中抓取实例。 你可以用 doc-scrape-examples 标志单独启用或禁用目标,例如:

# 启用从库中抓取实例
[lib]
doc-scrape-examples = true

# 禁用从实例目标中抓取实例
[[example]]
name = "my-example"
doc-scrape-examples = false

关于测试的说明: 在测试目标上启用 doc-scrape-examples 目前没有任何效果。从测试中抓取例子是一项正在进行的工作。

关于dev-依赖的说明: 记录库通常不需要crate的dev-依赖。然而,示例目标需要dev-依赖。 为了向后兼容, -Z rustdoc-scrape-examplescargo doc 引入dev-依赖要求。 因此,在以下情况下,将 不会 从示例目标中抓取示例:

  1. 没有被记录的目标需要dev-依赖, AND
  2. 至少有一个目标被记录的crate有dev-依赖, AND
  3. 对于所有 [[example]] 目标,doc-scrape-examples 参数未设置或为假。

如果你想让实例从实例目标中被抓取,那么你必须不满足上述条件之一。 例如,你可以为一个例子目标设置 doc-scrape-examples 为 true,这就向Cargo发出信号,你可以为 cargo doc 建立dev-依赖。

check-cfg

-Z check-cfg 命令行可以在编译时检查 #[cfg]cfg! 中的名称和值。 #[link]#[cfg_attr] 中的名称和值,使用 rustcrustdoc 不稳定的 --check-cfg 命令行。

它的值是:

  • features: 通过 --check-cfg=values(feature, ...) 启用特性检查。 注意这个命令行选项可能会成为稳定时的默认选项。
  • names: 通过 --check-cfg=names() 实现众所周知的名称检查。
  • values: 通过 --check-cfg=values() 实现众所周知的值检查。
  • output: 启用构建脚本中的 rustc-check-cfg

例如:

cargo check -Z unstable-options -Z check-cfg=features
cargo check -Z unstable-options -Z check-cfg=names
cargo check -Z unstable-options -Z check-cfg=values
cargo check -Z unstable-options -Z check-cfg=features,names,values

Or for output:

#![allow(unused)]
fn main() {
// build.rs
println!("cargo:rustc-check-cfg=names(foo, bar)");
}
cargo check -Z unstable-options -Z check-cfg=output

cargo:rustc-check-cfg=CHECK_CFG

rustc-check-cfg 指令告诉Cargo将给定的值传递给编译器 --check-cfg 标志。 这可用于编译时检测意外的条件编译名称或值。

这只能与 -Zcheck-cfg=output 结合使用,否则会被忽略并发出警告。

如果你想集成Cargo的特性,请使用 -Zcheck-cfg=features ,而不是试图用这个选项手动完成。

稳定和删除特性

编译进度

编译进度功能在1.30版本中得到了稳定。进度条现在是默认启用的。 参见 term.progress 了解更多关于控制该特性的信息。

版次

Cargo.toml 中指定 edition 已在1.31版本中得到稳定。 请参阅 the edition field 以了解有关指定该字段的更多信息。

重命名依赖

Cargo.toml 中指定重命名依赖,在1.31版本中已经稳定。 参见 renaming dependencies 了解更多关于重命名依赖的信息。

备用注册中心

在1.34版本中,对备用注册中心的支持已经稳定下来了。 请参阅 Registries chapter 了解更多关于备用注册中心的信息。

脱机模式

脱机功能在1.36版本中已经稳定下来了。 参见 --offline flag,了解更多关于使用脱机模式的信息。

发表锁定文件

1.37版本中删除了 publish-lockfile 功能。如果包包含二进制目标,则在发布包时总是包括 Cargo.lock 文件。 cargo install 需要 --locked 标志来使用 Cargo.lock 文件。 更多信息见 cargo packagecargo install

默认运行

default-run 功能在1.37版本中已经稳定下来。参见 the `default-run'field 以了解更多关于指定默认运行目标的信息。

缓存信息

编译器信息缓存在1.40版本中得到了稳定。编译器警告现在被默认缓存,并在重新运行Cargo时自动回放。

安装升级

install-upgrade 特性在1.41版本中得到了稳定。cargo install现在会在包出现过期时自动升级。更多信息请参见 cargo install 文档。

Profile覆盖

Profile 覆盖已经在1.41版本中得到稳定。请参阅Profile Overrides以了解更多关于使用覆盖的信息。

Config Profiles

在Cargo 配置文件和环境变量中指定配置文件的做法在1.43版本中已经稳定下来。 参见 config [profile] table 以了解更多关于在配置文件中指定 profile 的信息。

crate版本

-Z crate-versions 标志在1.47版本中已经稳定。 crate版本现在自动包含在 cargo doc 文档中。

特性

在1.51版本中,-Z features 标志已经稳定下来。参见 feature resolver version 2 以了解更多关于使用新特性解析器的信息。

包特性

-Z package-features 标志在1.51版本中已经稳定了。 参见 resolver version 2 command-line flags 以了解更多关于使用特性 CLI 选项的信息。

解析器

Cargo.toml 中的 Cargo.toml 特性在1.51版本中已经稳定。 请参阅 resolver versions 以了解有关指定解析器的更多信息。

在1.56版本中,用于在构建脚本中指定额外链接器参数的 extra-link-arg 功能已经稳定了。 请参阅 build script documentation 以了解更多关于指定额外链接器参数的信息。

configurable-env

在Cargo配置中指定环境变量的 configurable-env 功能在1.56版本中已经稳定下来。 关于配置环境变量的更多信息,请参见 config documentation

rust-version

Cargo.toml 中的 rust-version 字段在1.56版本中已经稳定。 请参阅 rust-version field 以了解更多关于使用 rust-version 字段和 -ignore-rust-version 选项的信息。

codegen-backend

codegen-backend 特性使我们有可能使用配置文件来选择rustc使用的codegen后端。

Example:

[package]
name = "foo"

[dependencies]
serde = "1.0.117"

[profile.dev.package.foo]
codegen-backend = "cranelift"

patch-in-config

-Z patch-in-config 标志,以及对Cargo配置文件中 [patch] 部分的相应支持,在1.56版本中已经稳定下来。更多信息请参见 patch field

edition 2021

2021 版次在1.56版本中已经稳定下来了。 参见edition field,了解更多关于设置版次的信息。 参见cargo fix --editionThe Edition Guide了解更多关于迁移现有项目的信息。

自定义命名的配置文件

自定义命名的配置文件已经在1.57版本中得到稳定。请参阅 profiles chapter 了解更多信息。

Profile strip option

配置文件 strip 选项在1.59版本中已经稳定了。更多信息请参见 profiles chapter

未来不兼容报告

在1.59版本中,对生成未来不兼容报告的支持已经稳定下来了。 更多信息请参见 future incompat report chapter

名称空间特性

在1.60版本中,名称空间特性已经稳定下来了。 更多信息请参见Features chapter

弱依赖性特性

弱依赖性特性在1.60版本中已经稳定下来。 更多信息请参见Features chapter

timings

-Ztimings 选项在1.60版本中已经稳定为 --timings 。 ( --timings=html 和机器可读的 --timings=json 输出仍然不稳定,需要 --Zunstable-options 。)

config-cli

--config CLI选项在1.63版本中已经稳定。更多信息请参见 config documentation

multitarget

-Z multitarget 选项在1.64版本中已经稳定了。参见 build.target 以了解更多关于设置默认目标平台三元组的信息。

crate-type

在1.64版本中,cargo rustc--crate-type 标志已经稳定。更多信息请参见 cargo rustc documentation

工作空间继承

工作空间继承在1.64版本中得到了稳定。 参见 workspace.package,workspace.dependencies,和 inheriting-a-dependency-from-a-workspace 获得更多信息。

terminal-width

在1.68版本中, -Z terminal-width 选项已经稳定了。当从Cargo可以自动检测宽度的终端运行时,终端宽度总是被传递给编译器。

Cargo命令

常规命令

cargo(1)

NAME

cargo - Rust包管理器

SYNOPSIS

cargo [options] command [args]
cargo [options] --version
cargo [options] --list
cargo [options] --help
cargo [options] --explain code

DESCRIPTION

这个程序是Rust语言的包管理器和构建工具,可在https://rust-lang.org上获得。

COMMANDS

构建命令

cargo-bench(1)
    执行包的性能测试。

cargo-build(1)
    编译包

cargo-check(1)
    检查本地包及其所有依赖是否有错误。

cargo-clean(1)
    移除Cargo曾生成的制品。

cargo-doc(1)
    构建包的文档。

cargo-fetch(1)
    从网络中获取包的依赖。

cargo-fix(1)
    自动修复rustc报告的lint警告。

cargo-run(1)
    运行本地包的二进制文件或示例文件。

cargo-rustc(1)
    编译包,并传递附加选项给编译器。

cargo-rustdoc(1)
    使用指定的自定义标志构建包的文档。

cargo-test(1)
    执行包的单元测试和集成测试。

配置清单命令

cargo-generate-lockfile(1)
    为项目生成 Cargo.lock .

cargo-locate-project(1)
    打印 Cargo.toml 文件位置的JSON表示。

cargo-metadata(1)
    以机器可读的格式输出已解决的包的依赖。

cargo-pkgid(1)
    打印完全合格的包规格。

cargo-tree(1)
    显示依赖图的可视化树。

cargo-update(1)
    更新本地lock file中记录的依赖。

cargo-vendor(1)
    在本地提供所有依赖。

cargo-verify-project(1)
    检查crate配置是否正确。

包命令

cargo-init(1)
    在现有目录中创建新的Cargo包。

cargo-install(1)
    构建并安装Rust二进制文件。

cargo-new(1)
    创建新的Cargo包。

cargo-search(1)
    在 crates.io 搜索包。

cargo-uninstall(1)
    移除Rust二进制文件。

发布命令

cargo-login(1)
    在本地注册中心保存API令牌。

cargo-owner(1)
    在注册中心管理crate的所有者。

cargo-package(1)
    将本地包打包成可分发的压缩包。

cargo-publish(1)
    上传一个包到注册中心。

cargo-yank(1)
    从索引中移除已推送的crate。

常规命令

cargo-help(1)
    显示有关Cargo的帮助信息。

cargo-version(1)
    显示版本信息。

OPTIONS

特定选项

-V
--version
打印版本信息并退出。如果有 --verbose, 打印额外的信息。
--list
列出所有已安装的Cargo子命令。如果有 --verbose, 打印额外的信息。
--explain code
运行 rustc --explain CODE 这将打印错误信息的详细解释 (例如, E0004).

显示选项

-v
--verbose
使用详细输出。可能指定两次,"非常详细" 包含额外的内容,如依赖警告和构建脚本输出。也可以用 term.verbose 配置.
-q
--quiet
不要打印cargo日志信息。也可以用 term.quiet 配置.
--color when
控制何时使用彩色输出。有效值:

  • auto (默认): 自动检测终端上是否有颜色支持。
  • always: 总是显示颜色。
  • never: 总不显示颜色。

也可以用 term.color 配置.

配置选项

--frozen
--locked
这些标志中的任何一个都要求Cargo.lock文件是最新的。 如果lock file丢失,或者需要更新,Cargo将以错误退出。 --frozen 标志还可以防止Cargo试图访问网络以确定其是否过时。

这可能用于你想断言 Cargo.lock 文件是最新的环境(如CI构建)或想避免网络访问。

--offline
阻止Cargo访问网络。如果没有这个标志,Cargo在需要访问网络而网络不可用的情况下会以错误方式停止。 有了这个标志,如果可能的话,Cargo将尝试在没有网络的情况下进行。

请注意,这可能会导致与在线模式不同的依赖解决。 Cargo会将自己限制在本地下载的crate上,即使在本地拷贝的索引中可能有一个较新的版本。 参见 cargo-fetch(1) 命令在离线前下载依赖。

也可以用 net.offline 配置

通用选项

+toolchain
如果Cargo已经安装了rustup。 cargo的第一个参数以+开始, 它将被解释为一个rustup工具链名称 (比如 +stable+nightly)。 参见 rustup 文档 有关工具链覆盖如何工作的详细信息。
--config KEY=VALUE or PATH
覆盖Cargo配置值。参数应该是TOML语法中的 KEY=VALUE, 或作为一个额外的配置文件的路径提供。这个标志可以被多次指定。 参见 command-line 覆盖部分 了解详细信息。
-h
--help
打印帮助信息。
-Z flag
Cargo 不稳定的 (每日构建) 标记 。运行 cargo -Z 获得 详细帮助。

ENVIRONMENT

关于Cargo读取的环境变量的详情,参阅 参考

EXIT STATUS

  • 0: Cargo 成功。
  • 101: Cargo 未能完成。

FILES

~/.cargo/
    Cargo "home" 目录的默认位置,存储各种文件。这个位置可以通过 CARGO_HOME 环境变量来改变。

$CARGO_HOME/bin/
    由 cargo-install(1) 安装的二进制文件会放在这里。如果使用 rustup,随 Rust 分布的可执行文件也位于这里。

$CARGO_HOME/config.toml
    全局配置文件。见参考了解更多关于配置文件的信息。

.cargo/config.toml
    Cargo会自动在当前目录和所有父目录下搜索名为 .cargo/config.toml 的文件。这些配置文件将合并到全局配置文件中。

$CARGO_HOME/credentials.toml
    用于登录注册中心的私人认证信息。

$CARGO_HOME/registry/
    这个目录包含注册中心索引的缓存下载和任何下载的依赖。

$CARGO_HOME/git/
    这个目录包含了git依赖的缓存下载。

请注意, $CARGO_HOME 目录的内部结构还不稳定,可能会有变化。

EXAMPLES

  1. 构建本地包和它的所有依赖:

    cargo build
    
  2. 构建优化后的包:

    cargo build --release
    
  3. 为交叉编译的目标运行测试:

    cargo test --target i686-unknown-linux-gnu
    
  4. 创建新的包,构建可执行文件:

    cargo new foobar
    
  5. 在当前目录下创建包:

    mkdir foo && cd foo
    cargo init .
    
  6. 了解命令的选项和用法:

    cargo help clean
    

BUGS

对于问题见 https://github.com/rust-lang/cargo/issues

SEE ALSO

rustc(1), rustdoc(1)

cargo-help(1)

定义

cargo-help - 对于Cargo命令获得帮助。

概要

cargo help [subcommand]

说明

打印指定命令的帮助信息。

示例

  1. 获取命令帮助:

    cargo help build
    
  2. 也可以通过 --help 参数获得帮助:

    cargo build --help
    

参阅

cargo(1)

cargo-version(1)

定义

cargo-version - 显示版本信息

概要

cargo version [options]

说明

显示Cargo的版本。

选项

-v
--verbose
显示附加的版本信息。

示例

  1. 显示版本:

    cargo version
    
  2. 版本也可以通过标志获得:

    cargo --version
    cargo -V
    
  3. 显示额外的版本信息:

    cargo -Vv
    

参阅

cargo(1)

Build Commands

cargo-bench(1)

名称

cargo-bench - 执行包的基准测试

简介

cargo bench [options] [benchname] [-- bench-options]

DESCRIPTION

编译和执行基准。

基准过滤参数 benchname 及其后的所有参数两个破折号(--)被传递给基准二进制文件,从而传递给 libtest (rustc的内置单元测试和微基准框架)。 如果您同时向 Cargo 和二进制文件传递参数,那么 -- 之后的参数将转到二进制文件,转到 Cargo 之前的参数将转到 Cargo。有关libtest的详细信息参数查看 cargo bench -- --help 的输出,并检查rustc书中关于测试如何工作的章节 https://doc.rust-lang.org/rustc/tests/index.html.

例如,这将只运行名为 foo 的基准测试(并跳过其他类似名称的基准测试,如 foobar ):

cargo bench -- foo --exact

基准测试是使用 rustc- test 选项构建的,它通过将您的代码与 libtest 链接来创建一个特殊的可执行文件。可执行文件自动运行所有用 #[bench] 属性注释的函数。Cargo 将 bench 标志传递给测试工具,告诉它只运行基准测试。

可以通过在目标清单设置中设置 harness = false 来禁用 libtest 工具,在这种情况下,您的代码将需要提供自己的 main 函数来处理运行基准。

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

默认情况下,货物台架使用台架配置文件,这样可以优化和禁用调试信息。如果您需要调试一个基准,您可以使用 --profile=dev 命令行选项切换到dev配置文件。然后,您可以在调试器中运行启用调试的基准。

选项

Benchmark 选项

--no-run
编译,但是不要运行基准测试。
--no-fail-fast
不管失败与否,运行所有基准测试。如果没有这个标志,Cargo将在第一个可执行文件失败后退出。Rust test harness 将运行可执行文件中的所有基准直到完成,这个标志只适用于整个可执行文件。

Package 选择

缺省情况下,当没有给出包选择选项时,所选择的包取决于所选择的清单文件(如果没有给出 - manifest-path ,则基于当前工作目录)。如果清单是工作区的根,则选择工作区的默认成员,否则只选择清单定义的包。

可以使用根清单中的 workspace.default-members 键显式设置工作区的默认成员。如果未设置此项,虚拟工作区将包括所有工作区成员(相当于传递 - workspace ),而非虚拟工作区将只包括根机箱本身。

-p spec...
--package spec...
仅对指定的包进行基准测试。SPEC 格式请参考cargo-pkgid(1)。该标志可以多次指定,并支持常见的Unix全局模式,如 *?[] 。然而,为了避免您的shell在Cargo处理glob模式之前意外扩展它们,您必须在每个模式周围使用单引号或双引号。
--workspace
Benchmark all members in the workspace.
--all
--workspace已弃用的别名
--exclude SPEC...
排除指定的包。必须与 --workspace标志一起使用。该标志可以多次指定,并支持常见的Unix全局模式,如 *[]。然而,为了避免您的shell在Cargo处理glob模式之前意外扩展它们,您必须在每个模式周围使用单引号或双引号。

目标选择

当没有给出目标选择选项时,cargo bench 将建立所选包装的以下目标:

  • lib — 用于链接二进制文件和基准
  • bins (仅当构建了基准目标并且所需的特性可用时)
  • lib 作为基准
  • bins 作为基准
  • 基准目标

可以通过在清单设置中为目标设置 bench 标志来更改默认行为。将示例设置为 bench = true 将构建并运行该示例作为基准。默认情况下,将目标设置为 bench = false 将会阻止它们进行基准测试。通过名称获取目标的目标选择选项会忽略“bench”标志,并始终以给定目标为基准。

如果有一个集成测试或基准被选择来进行基准测试,那么二进制目标将被自动构建。这允许集成测试执行二进制代码来测试它的行为。 CARGO_BIN_EXE_<name> 环境变量 是在构建集成测试时设置的,以便它可以使用 env macro 来定位可执行文件。

传递目标选择标志将只对指定的目标进行基准测试。

注意 --bin--example--test--bench 标志也支持常见的 Unix 全局模式,如 *?[]。然而,为了避免您的 shell 在 Cargo 处理 glob 模式之前意外地扩展它们,您必须在每个 glob 模式周围使用单引号或双引号。

--lib
对软件包的库进行基准测试。
--bin name...
测试指定的二进制文件。该标志可以多次指定,并支持常见的Unix glob模式。
--bins
对所有二进制目标进行基准测试。
--example name...
对指定的示例进行基准测试。该标志可以多次指定,并支持常见的Unix glob模式。
--examples
对所有示例目标进行基准测试。
--test name...
对指定的集成测试进行基准测试。该标志可以多次指定,并支持常见的Unix glob模式。
--tests
在测试模式下对设置了test = true 清单标志的所有目标进行基准测试。默认情况下,这包括作为单元测试和集成测试构建的库和二进制文件。请注意,这也将构建任何所需的依赖项,因此lib目标可以构建两次(一次作为单元测试,一次作为二进制文件、集成测试等的依赖项。). 可以通过在目标的清单设置中设置 test 标志来启用或禁用目标。
--bench name...
基准测试指定的基准。该标志可以多次指定,并支持常见的Unix glob模式。
--benches
在基准模式下对设置了 bench = true 清单标志的所有目标进行基准测试。默认情况下,这包括作为基准构建的库和二进制文件,以及基准目标。请注意,这也将构建任何所需的依赖项,因此lib目标可能会构建两次(一次作为基准,一次作为二进制文件、基准等的依赖项。). 可以通过在目标的清单设置中设置 bench 标志来启用或禁用目标。
--all-targets
基准测试所有目标。这相当于指定 --lib --bins --tests --benches --examples

特征选项

功能标志允许您控制启用哪些功能。当未给出功能选项时,为每个选定的包激活 default 特性。

请参见 the features documentation 了解更多详情。

-F features
--features features
要激活的以空格或逗号分隔的功能列表。可以使用 package-name/feature-name 语法来启用工作区成员的功能。可以多次指定该标志,从而启用所有指定的功能。
--all-features
激活所有选定包的所有可用特性。
--no-default-features
不要激活所选包的 default 特性。

编译选项

--target triple
给定架构的基准。默认为主机架构。三元组的一般格式是<arch><sub>-<vendor>-<sys>-<abi>。运行 rustc --print target-list 以获取支持的目标列表。可以多次指定该标志.

这也可以用 build.target 来指定 配置值

注意,指定这个标志会使Cargo以不同的模式运行,其中目标工件被放在一个单独的目录中。有关更多详细信息,请参见 build cache 文档。

--profile name
用给定的 profile 文件进行基准测试。 请参见the reference,了解有关配置文件的更多详细信息。
--ignore-rust-version
对目标进行基准测试,即使选择的Rust编译器比 项目的rust-version字段中配置的所需Rust版本。
--timings=fmts
输出每次编译需要多长时间的信息,并随着时间的推移跟踪并发信息。接受可选的逗号分隔的输出格式列表;不带参数的 --timings 将默认为 --timings=html 。指定输出格式(而不是默认格式)不稳定,需要 -Zunstable-options。有效的输出格式:

  • html(不稳定,需要 -Zunstable-options ):将一个可读的文件 cargo-timing.html 写入 target/cargo-timings 目录,并附上编译报告。如果您想查看以前的运行,也可以在相同的目录下写一个带有时间戳的报告。HTML输出只适合人类使用,不提供机器可读的计时数据。
  • json(不稳定,需要 -Zunstable-options ):发出有关计时信息的机器可读json信息。

输出选项

--target-dir directory
所有生成的工件和中间文件的目录。也可以用CARGO_TARGET_DIR环境变量或build.target-dir config value。 默认为工作区根目录中的< code>target。

显式选项

默认情况下,Rust test harness隐藏了基准执行的输出,以保持结果的可读性。通过向基准二进制文件传递 --nocapture ,可以恢复基准输出(例如,用于调试):

cargo bench -- --nocapture
-v
--verbose
使用详细输出。 对于 "非常详细"的输出,可以指定两次,非常详细的输出包括额外的输出,如依赖项警告和构建脚本输出。

也可以用term.verbose 配置值.

-q
--quiet
不要打印货物日志信息。也可以用 term.quiet 来指定 配置值
--color when
控制何时使用彩色输出。有效值:

  • auto (默认):自动检测上是否支持颜色 终端。
  • always:始终显示颜色。
  • never: 从不显示颜色

也可以用 term.color 指定 配置值.

--message-format fmt
诊断消息的输出格式。可以多次指定,由逗号分隔的值组成。有效值:

  • human(默认):以人类可读的文本格式显示。与< code>short和< code>json冲突。
  • short: 发出更短的、人类可读的文本消息。与< code>human和< code>json冲突。
  • json: 向stdout发出JSON消息。 请参见 the reference 了解更多详情。 与 humanshort 冲突。
  • json-diagnostic-short :确保JSON消息的rendered字段包含来自rustc的"简短"呈现。不能与humanshort 一起使用。
  • json-diagnostic-rendered-ansi: Ensure the rendered field of JSON messages contains embedded ANSI color codes for respecting rustc's default color scheme. Cannot be used with human or short.
  • json-render-diagnostics :指示Cargo不要在打印的JSON消息中包含rustc诊断,而是Cargo本身应该呈现来自rustc的JSON诊断。Cargo自己的JSON诊断和来自rustc的其他诊断仍然会发出。不能与humanshort一起使用。

清单选项

--manifest-path path
Cargo.toml 文件的路径。默认情况下,Cargo在当前目录或任何父目录中搜索 Cargo.toml 文件。
--frozen
--locked
这两个标志都要求Cargo.lock文件是最新的。如果锁文件丢失,或者需要更新,Cargo将出错退出。--frozen标志还防止 Cargo 试图访问网络以确定其是否过期。

在您希望断言Cargo.lock文件是最新的(如CI构建)或希望避免网络访问的环境中,可以使用这些文件。

--offline
防止货物以任何理由访问网络。如果没有这个标志,当 Cargo 需要访问网络而网络不可用时,Cargo 将出错停止。有了这个标志,如果可能的话,Cargo将试图在没有网络的情况下前进。

请注意,这可能会导致与在线模式不同的依赖关系解析。Cargo 将自己限制在本地下载的 crate 中,即使在索引的本地副本中可能有更新的版本。 请参阅 cargo-fetch(1)命令,以便在脱机之前下载依赖项。

也可以用net.offline 配置值指定。

命令选项

+toolchain
如果Cargo已经与rustup一起安装,并且cargo的第一个参数以+开头,它将被解释为rustup工具链名称(例如+stable+nightly)。 有关工具链覆盖如何工作的详细信息,请参阅
--config KEY=VALUE or PATH
覆盖 Cargo 配置值。参数应该采用KEY=VALUE的TOML语法,或者作为额外配置文件的路径提供。可以多次指定该标志。 请参见< a href="../reference/config.html#command-line-overrides"> 命令行重写部分,了解更多信息。
-h
--help
打印帮助信息。
-Z flag
Cargo不稳定(night-only)标志。运行cargo -Z help获取详细信息。

Miscellaneous Options

--jobs 参数影响基准可执行文件的构建,但不影响运行基准时使用的线程数量。Rust test harness在单线程中连续运行基准测试。

-j N
--jobs N
要运行的并行作业的数量。也可以用build.jobs 配置值指定。 默认为逻辑CPU的数量。如果为负,它将并行作业的最大数量设置为逻辑CPU的数量加上提供的值。不应为0。
--keep-going
在依赖图中构建尽可能多的板条箱,而不是在第一个构建失败时中止构建。不稳定,需要< code>-Zunstable-options。

环境

参见 [参考文献](../reference/environment-variables . html) 以了解Cargo读取的环境变量的详细信息。

退出状态

  • 0 : Cargo 成功。
  • 101 : Cargo 未能完成。

示例

  1. 构建并执行当前包的所有基准:

    cargo bench
    
  2. 仅运行特定基准目标中的特定基准:

    cargo bench --bench bench_name -- modname::some_benchmark
    

另见

cargo(1), cargo-test(1)

cargo-build(1)

定义

cargo-build - 编译当前package

概要

cargo build [options]

说明

编译本地package以及它们的依赖

选项

Package 的选择

默认情况下,如果没有提供选择包的选项,那么会按照选择的配置清单文件来选择包(当没有指定 --manifest-path 时,按照当前工目录来查找配置清单文件)。 如果工作空间根目录的配置清单文件,则会选择该工作空间的默认成员,否则仅选取配置清单文件所在的那个包。

workspace默认的成员可以通过根清单文件中的 workspace.default-members 键指定, 如果没有指定该键,则会生成一个虚拟的workspace包含所有的workspace成员 (等同于直接传入 --workspace 参数),并且非虚拟的workspace将只包含根crate自身。

-p spec...
--package spec...
只包含特定的package。 要了解SPEC格式,请参阅cargo-pkgid(1) 该标识可被指定多次,并且支持通用Unix通配符(common Unix glob patterns),例如: *, ?[]。 然而, 为了避免shell在Cargo处理他们之前将通配符意外的展开 , 必须使用单引号或者双引号将模式串包住。
--workspace
在workspace中构建全部成员。
--all
--workspace已经弃用的别名。
--exclude SPEC...
排除指定的package,必须与 --workspace 标识连用。该标识可以被指定多次,并且支持Unix通配符(common Unix glob patterns),例如*, ?[]。 然而, 为了避免shell在Cargo处理他们之前将通配符意外的展开 , 必须使用单引号或者双引号将模式串包住。

构建目标的选择

当没有目标选择选项给出的时候,cargo build 将构建所有的选定的package中的binary和library目标。 如果Binary的 required-features 有缺失,则Binary构建将被跳过

如果集成测试或者性能测试被指定构建,则Binary目标将被自动构建。这允许了集成测试执行binary用以测试它们的行为。 在构建集成测试时设置 CARGO_BIN_EXE_<name> 环境变量 以便于它可以使用env 来定位可执行文件。

传入目标选择参数将只构建指定的目标。

需要注意的是--bin, --example, --test--bench 标志同样支持Unix通配符(common Unix glob patterns),例如 *, ?[]。 然而, 为了避免shell在Cargo处理他们之前将通配符意外的展开, 必须使用单引号或者双引号将模式串包住。

--lib
构建package的library。
--bin name...
构建指定的binary,该标识可以被指定多次,并且支持Unix通配符。
--bins
构建所有的binary目标。
--example name...
构建指定的示例,该标识可以被指定多次,并且支持Unix通配符。
--examples
构建所有的示例。
--test name...
构建指定的集成测试,该标识可以被指定多次,并且支持Unix通配符。
--tests
在测试模式下构建所有清单文件中带有 test = true 标识的目标,默认情况下,这将包含作为单元测试和集成测试构建的library和binary 当心这也会构建所需要的依赖,因此,library目标有可能被构建两次(一次作为单元测试,一次作为binary或集成测试等目标的依赖。)。 通过在目标的清单文件设置中设置 test 标志,可以启用或禁用目标。
--bench name...
构建指定的性能测试,该标识可以被指定多次,并且支持Unix通配符。
--benches
在性能测试模式下构建所有清单文件中带有 bench = true 标识的目标,默认情况下,这将包含作为性能测试或性能测试目标构建的library和binary 当心这也会构建所需要的依赖,因此,library目标有可能被构建两次(一次作为性能测试,一次作为binary或性能测试等目标的依赖。)。 通过在目标的清单文件设置中设置 bench 标志,可以选择是否启用。
--all-targets
构建所有的目标,等同于 --lib --bins --tests --benches --examples.

特性选择

特性标志允许你控制开启哪些特性。当没有提供特性选项时,会为每个选择的包启用 default 特性。

查阅 the features documentation 以获取更多细节

-F features
--features features
要激活的特性列表,特性间用空格逗号隔开。workspace的成员的特性可以通过 package-name/feature-name 来启用。 该标志可以被设置多次,将启用所有给出的特性。
--all-features
激活选中package的所有特性
--no-default-features
不激活选中的package的 default 特性

编译选项

--target triple
为指定的CPU架构构建. 默认情况下是当前主机的架构. 参数中的三元组的一般格式是 <arch><sub>-<vendor>-<sys>-<abi>. 运行 rustc --print target-list 来获取支持的架构列表

也可以通过 build.target 配置

注意,指定这个标志会使Cargo在不同的模式下运行,目标制品放在单独目录。 参见 构建缓存 文档了解详情。

-r
--release
通过清单文件中 release 配置项目(profile),以构建出优化过的产物。 参阅 --profile 选项了解如何按照指定的配置项目构建
--profile name
通过给定的profile构建 参阅 参考手册 获取更多关于profile的细节。
--ignore-rust-version
即使cargo低于项目中 rust-version 字段要求的cargo最低版本,也继续构建
--timings=fmts
输出每个编译过程所花费的时间,以及随着时间变化的并行执行情况,可以接收通过逗号分隔的可选的参数,来定义输出的格式 --timings 如果后面不跟参数将,将默认看作 --timings=html。 给出输出格式(除了默认)是不稳定的的功能,需要加上 -Zunstable-options。 有效的格式有:

  • html (不稳定, 需要 -Zunstable-options): 生成一个适合人类阅读的的耗时报告文件 cargo-timing.html ,保存到 target/cargo-timings 目录下。 同时也在同目录下生成一个相同内容的用时间戳命名的报告,方便再次编译将前者覆盖后查看。 HTML 输出只适合人类阅读,并且不会提供适合机器阅读的耗时数据
  • json (不稳定, 需要 -Zunstable-options): 生成适合机器阅读的JSON格式的耗时信息

输出选项

--target-dir directory
所有生成目标产物以及中间文件存放的目录,也可通过 CARGO_TARGET_DIR 环境变量指定, 又或者通过 build.target-dir 配置。 默认将保存到workspace根目录下的target 目录下
--out-dir directory
复制最终产物到指定目录.

该选项是不稳定的,只在 nightly channel 以及 -Z unstable-options 标志被设置才能启用。 查阅 https://github.com/rust-lang/cargo/issues/6790 获取更多信息。

显示选项

-v
--verbose
输出详细信息。 指定两次该选项表示 "非常详细" 输出诸如依赖警告或编译脚本的输出等信息。 也可通过 term.verbose 配置项指定 可选值
-q
--quiet
不输出cargo日志信息。也可通过term.quiet 配置项指定 可选值.
--color when
控制何时输出彩色信息,可选值:

  • auto (默认): 自动检测终端是否支持彩色。
  • always: 总是输出彩色信息。
  • never: 从不输出彩色信息。

也可通过 term.color 配置项指定 可选值

--message-format fmt
指定输出诊断信息的格式。可以被指定多次,值由逗号隔开,有效的值有:

  • human (default): 显示适合人类阅读的文本信息. 与 shortjson冲突。
  • short: 输出更短的, 适合人类阅读的信息。 与 humanjson冲突
  • json: 输出json信息到stdout。 查阅 参考手册 以获取详细信息。与 humanshort冲突。
  • json-diagnostic-short: 确保JSON的 rendered 字段包含 "short" 由rustc渲染。 不可以与 human 或者 short同时使用。
  • json-diagnostic-rendered-ansi: 确保JSON的 rendered 字段包含ANSI颜色码,以符合rustc的默认颜色方案,不可以与 human 或者 short同时使用。
  • json-render-diagnostics: 指导Cargo输出的JSON消息不要包含rustc的诊断信息,而是让Cargo自己渲染rustc的诊断信息, 但是Cargo自己的JSON诊断和来自rustc的其他诊断保留。不可以与human 或者 short同时使用。
--build-plan
输出一系列的JSON消息到指示要运行的命令的stdout

该选项尚且不稳定,只有在 nightly channel-Z unstable-options 被指定时才可以开启。 查阅 https://github.com/rust-lang/cargo/issues/5579 以获取更多信息.

清单选项

--manifest-path path
Cargo.toml 的路径. 默认情况下Cargo将搜索当前目录或所有父目录下的 Cargo.toml 文件。
--frozen
--locked
这些标志都要求 Cargo.lock 文件是最新的。 如果lock文件丢失, 或是需要更新, Cargo会返回错误并退出,--frozen 选项还会阻止cargo通过网络来判断其是否过期。

可以用于断言 Cargo.lock 文件是否最新状态(例如CI构建)或避免网络访问。

--offline
阻止Cargo访问网络。如果不指定该选项,Cargo会在需要使用网络但不可用时停止构建并返回错误。设置该标识,Cargo将尽可能不使用网络完成构建。

需注意,这样可能会导致与在线模式不同的依赖处理,Cargo将限制仅使用已下载到本地的crate,即使本地索引中有更新版本。 查阅 cargo-fetch(1) 命令,在脱机前下载依赖。

也可以使用 net.offline 配置

一般选项

+toolchain
如果Cargo已经通过rustup安装,并且第一个传给 cargo 的参数以 + 开头, 则当作rustup的工具链名称。(例如 +stable+nightly). 查阅 rustup 文档 了解关于工具链覆盖的信息。
--config KEY=VALUE or PATH
覆盖Cargo配置项的值,该参数应当为TOML KEY=VALUE 语法, 或者提供附加的配置文件的路径。该标识可以多次指定。 查阅 命令行覆盖部分 获取更多信息
-h
--help
输出帮助信息。
-Z flag
Cargo不稳定的(每日构建)标志。运行 cargo -Z help 了解详情。

杂项

-j N
--jobs N
并行执行的数量。也可以用 build.jobs 配置 可选值 默认为逻辑CPU个数。如果是给出负数,将采用逻辑逻辑CPU数量+传入的负数。
--keep-going
在依赖关系图中构建尽可能多的crate,而不是在遇到第一个构建失败的crate就中止构建,不稳定,需要 -Zunstable-options选项。
--future-incompat-report
显示一个未来兼容性报告,包含在执行命令时输出的所有的“未来不可用的”(future-incompatible)警告信息。

查阅 cargo-report(1)获取更多信息

环境

查阅 参考手册 获取Cargo会读取的环境变量。

退出状态

  • 0: Cargo 成功退出。
  • 101: Cargo 未能完成。

例子

  1. 构建本地package以及它的全部依赖。

    cargo build
    
  2. 带有编译优化的构建:

    cargo build --release
    

请参阅

cargo(1), cargo-rustc(1)

cargo-check(1)

名称

cargo-check - 检查当前包

简介

cargo check [options]

描述

检查本地包及其所有依赖项是否有错误。这实际上将编译软件包,而不执行代码生成的最后一步,这比运行“Cargo构建”要快。 编译器会将元数据文件保存到磁盘上,这样,如果源文件没有被修改,以后运行时就可以重用它们。一些诊断和错误仅在代码生成期间发出,因此它们本质上不会在“Cargo检查”中报告。

选项

包选择

缺省情况下,当没有给出包选择选项时,所选择的包取决于所选择的清单文件(如果没有给出 - manifest-path ,则基于当前工作目录)。如果清单是工作区的根,则选择工作区的默认成员,否则只选择清单定义的包。

可以使用根清单中的 workspace.default-members 键显式设置工作区的默认成员。如果未设置此项,虚拟工作区将包括所有工作区成员(相当于传递 - workspace ),而非虚拟工作区将只包括根机箱本身。

-p spec...
--package spec...
仅对指定的包进行基准测试。SPEC 格式请参考cargo-pkgid(1)。该标志可以多次指定,并支持常见的Unix全局模式,如 *?[] 。然而,为了避免您的shell在Cargo处理glob模式之前意外扩展它们,您必须在每个模式周围使用单引号或双引号。
--workspace
检查工作区中的所有成员。
--all
--workspace已弃用的别名
--exclude SPEC...
排除指定的包。必须与 --workspace标志一起使用。该标志可以多次指定,并支持常见的Unix全局模式,如 *[]。然而,为了避免您的shell在Cargo处理glob模式之前意外扩展它们,您必须在每个模式周围使用单引号或双引号。

目标选择

当没有给出目标选择选项时,Cargo检查 将检查所选包的所有二进制和库目标。如果二进制文件缺少必需的特性,则跳过它们。

传递目标选择标志将只检查指定的目标。

注意--bin--example--test--bench标志也支持常见的Unix全局模式,如*?[]。然而,为了避免您的 shell 在 Cargo 处理 glob 模式之前意外地扩展它们,您必须在每个 glob 模式周围使用单引号或双引号。

--lib
检查包的库。
--bin name...
检查指定的二进制文件。可以多次指定该标志 并支持常见的Unix glob模式。
--bins
检查所有二进制目标。
--example name...
检查指定的示例。该标志可以多次指定,并支持常见的Unix glob模式。
--examples
检查所有示例目标。
--test name...
检查指定的集成测试。该标志可以多次指定,并支持常见的Unix glob模式。
--tests
检查测试模式中设置了test = true 清单标志的所有目标。默认情况下,这包括作为单元测试和集成测试构建的库和二进制文件。请注意,这也将构建任何所需的依赖项,因此lib目标可能会构建两次(一次作为 unittest,一次作为二进制、集成测试等的依赖项。). 可以通过在目标的清单设置中设置test标志来启用或禁用目标。
--bench name...
检查指定的基准。该标志可以多次指定,并支持常见的Unix glob模式。
--benches
在基准模式下检查设置了bench = true 清单标志的所有目标。默认情况下,这包括作为基准构建的库和二进制文件,以及基准目标。请注意,这也将构建任何所需的依赖项,因此lib目标可能会构建两次(一次作为基准,一次作为二进制文件、基准等的依赖项。). 可以通过在目标的清单设置中设置bench标志来启用或禁用目标。
--all-targets
检查所有目标。这相当于指定--lib --bins --tests --benches --examples

特性选择

功能标志允许您控制启用哪些功能。当未给出功能选项时,为每个选定的包激活“默认”功能。

请参见 the features documentation 了解更多详细信息。

-F features
--features features
要激活的以空格或逗号分隔的功能列表。可以使用package-name/feature-name语法来启用工作区成员的功能。可以多次指定该标志,从而启用所有指定的功能。
--all-features
激活所有选定软件包的所有可用功能。
--no-default-features
不要激活所选软件包的default功能。

编译选项

--target triple
检查给定的体系结构。默认为主机架构。三元组的一般格式是<arch><sub>-<vendor>-<sys>-<abi>。运行 rustc --print target-list 以获取支持的目标列表。可以多次指定该标志.

这也可以用 build.target 来指定 配置值

注意,指定这个标志会使Cargo以不同的模式运行,其中目标工件被放在一个单独的目录中。有关更多详细信息,请参见 build cache 文档。

-r
--release
release 概要文件检查优化的工件。 另请参见 --profile 选项,以按名称选择特定的配置文件。
--profile name
使用给定的配置文件进行检查。

作为一个特例,指定test配置文件还将启用测试模式下的检查,这将启用检查测试并启用test cfg选项。 如需详细信息,请参阅rustc tests

请参见参考,了解有关配置文件的更多详细信息。

--ignore-rust-version
即使所选Rust编译器比项目的rust-version字段中配置的所需Rust版本旧,也要检查目标。
--timings=fmts
输出每次编译需要多长时间的信息,并随着时间的推移跟踪并发信息。接受可选的逗号分隔的输出格式列表;不带参数的 --timings 将默认为 --timings=html 。指定输出格式(而不是默认格式)不稳定,需要 -Zunstable-options。有效的输出格式:

  • html(不稳定,需要 -Zunstable-options ):将一个可读的文件 cargo-timing.html 写入 target/cargo-timings 目录,并附上编译报告。如果您想查看以前的运行,也可以在相同的目录下写一个带有时间戳的报告。HTML输出只适合人类使用,不提供机器可读的计时数据。
  • json(不稳定,需要 -Zunstable-options ):发出有关计时信息的机器可读json信息。

输出选项

--target-dir directory
所有生成的工件和中间文件的目录。也可以用CARGO_TARGET_DIR环境变量或build.target-dir config value。 默认为工作区根目录中的< code>target。

显示选项

-v
--verbose
使用详细输出。 对于 "非常详细"的输出,可以指定两次,非常详细的输出包括额外的输出,如依赖项警告和构建脚本输出。

也可以用term.verbose 配置值

-q
--quiet
不要打印Cargo日志信息。也可以用 term.quiet 来指定 配置值
--color when
控制何时使用彩色输出。有效值:

  • auto (默认):自动检测上是否支持颜色 终端。
  • always:始终显示颜色。
  • never: 从不显示颜色

也可以用 term.color 指定 配置值.

--message-format fmt
诊断消息的输出格式。可以多次指定,由逗号分隔的值组成。有效值:

  • human(默认):以人类可读的文本格式显示。与< code>short和< code>json冲突。
  • short: 发出更短的、人类可读的文本消息。与< code>human和< code>json冲突。
  • json: 向stdout发出JSON消息。 请参见 the reference 了解更多详情。 与 humanshort 冲突。
  • json-diagnostic-short :确保JSON消息的rendered字段包含来自rustc的"简短"呈现。不能与humanshort 一起使用。
  • json-diagnostic-rendered-ansi: Ensure the rendered field of JSON messages contains embedded ANSI color codes for respecting rustc's default color scheme. Cannot be used with human or short.
  • json-render-diagnostics :指示Cargo不要在打印的JSON消息中包含rustc诊断,而是Cargo本身应该呈现来自rustc的JSON诊断。Cargo自己的JSON诊断和来自rustc的其他诊断仍然会发出。不能与humanshort一起使用。

清单选项

--manifest-path path
Cargo.toml文件的路径。默认情况下,Cargo在当前目录或任何父目录中搜索Cargo.toml文件。
--frozen
--locked
这两个标志都要求Cargo.lock文件是最新的。如果锁文件丢失,或者需要更新,Cargo将出错退出。 --freezed 标志还防止 Cargo 试图访问网络以确定其是否过期。

在您希望断言Cargo.lock文件是最新的(如CI构建)或希望避免网络访问的环境中,可以使用这些文件。

--offline
防止Cargo以任何理由访问网络。如果没有这个标志,当Cargo需要访问网络而网络不可用时,Cargo将出错停止。有了这个标志,如果可能的话,Cargo将试图在没有网络的情况下前进。

请注意,这可能会导致与在线模式不同的依赖关系解析。Cargo将自己限制在本地下载的板条箱中,即使在索引的本地副本中可能有更新的版本。 请参阅cargo-fetch(1)命令,以便在脱机之前下载依赖项。

也可以用net.offline 配置值

常见选项

+toolchain
如果Cargo已经安装了rustup,并且cargo的第一个参数以 +开头,则它将被解释为rustup工具链名称 (例如 +stable+nightly). 有关工具链覆盖如何工作的详细信息,请参阅 rustup documentation rust up文档。
--config KEY=VALUE or PATH
覆盖Cargo配置值。该参数应该采用TOML语法KEY=VALUE,或者作为额外配置文件的路径提供。可以多次指定该标志。 请参见,了解更多信息。
-h
--help
打印帮助信息。
-Z flag
Cargo 不稳定(nightly-only)标志。运行cargo -Z help获取详细信息。

其他选项

-j N
--jobs N
要运行的并行作业的数量。也可以用build.jobs config value指定。 默认为逻辑CPU的数量。如果为负,它将并行作业的最大数量设置为逻辑CPU的数量加上提供的值。 不应为0。
--keep-going
在依赖图中构建尽可能多的 crate ,而不是在第一个构建失败时中止构建。不稳定,需要 -Zunstable-options
--future-incompat-report
显示在执行此命令期间产生的任何未来不兼容警告的未来不兼容报告

请参阅 cargo-report(1)

环境

参见 the reference Cargo读取的环境变量的详细信息。

退出状态

  • 0: Cargo 成功。
  • 101: Cargo 未能完成。

示例

  1. 检查本地包是否有错误:

    cargo check
    
  2. 检查所有目标,包括单元测试:

    cargo check --all-targets --profile=test
    

另见

cargo(1), cargo-build(1)

cargo-clean(1)

名称

cargo-clean - 删除生成的产物

概要

cargo clean [options]

描述

删除目标 (target) 文件夹中的构建产物。

未附带选项时,cargo clean 会删除整个目标文件夹。

选项

包的选择

如果没有选择哪个包,工作空间中所有的包和依赖都将被删除。

-p spec...
--package spec...
只清除选中的包。这个标志可以指定多次。可从cargo-pkgid(1) 了解 SPEC 格式的相关信息。

清除选项

--doc
此选项会使得 cargo clean 只清除目标文件夹中的 doc 文件夹。
--release
清除 release 文件夹中的所有产物。
--profile name
清除构建预设 (profile) 名为 name 的文件夹中的所有产物。
--target-dir directory
存放构建产物和中间文件的文件夹。也可以用 CARGO_TARGET_DIR 环境变量来设置,或者 build.target-dir 设置选项。默认会放在工作空间根目录的 target 子目录下。

--target triple
清除指定架构 (architecture) 的产物。默认为宿主架构。通常的 triple 格式为<arch><sub>-<vendor>-<sys>-<abi>。 运行 rustc --print target-list 可以获取所有支持的架构的列表。此标志可以指定多次。

也可以通过 build.target 选项进行设置。

注意,指定这个标志会使Cargo在不同的模式下运行,目标产物会放在单独的目录。 参见 构建缓存 文档了解详情。

显示选项

-v
--verbose
进行详细输出。可以指定两遍来开启 "非常详细" 模式,输出更多的额外信息,像是依赖项的警告和构建脚本的输出信息。 也可以通过 term.verbose 选项进行配置 。
-q
--quiet
不打印 cargo 日志信息。 也可以通过 term.quiet 选项进行配置。
--color when
控制使用彩色输出。可选值有:

  • auto (默认值): 自动检测终端是否支持彩色输出。
  • always: 总是显示彩色。
  • never: 从不显示彩色。

也可以在 term.color 选项进行配置。

清单选项

--manifest-path path
Cargo.toml 文件的路径。 默认情况下,Cargo 在当前目录或任意的父目录中查找 Cargo.toml
--frozen
--locked
这两个 flag 都需要 Cargo.lock 文件处于无需更新的状态。如果 lock 文件缺失,或者需要被更新,Cargo 会报错退出。 --frozen flag 还会阻止 Cargo 访问网络来判断 Cargo.lock 是否过期。

这些 flag 可以用于某些场景下你想断言 Cargo.lock 无需更新 (比如在CI中构建) 或者避免网络访问。

--offline
阻止 Cargo 访问网络。如果没有这个 flag,当 Cargo 需要访问网络但是没有网络时,就会报错退出。加上这个 flag,Cargo 会尝试在不联网的情况下继续执行 (如果可以的话) 。

要小心这会导致与在线模式不同的解析结果。Cargo 会限制自己在本地已下载的 crate 中查找版本,即使在本地的 index 拷贝中表明还有更新的版本。 cargo-fetch(1) 命令可以在进入离线模式前下载依赖。

同样的功能也可以通过设置 net.offline 配置选项来实现。

通用选项

+toolchain
如果 Cargo 由 rustup 安装,那么 cargo 后第一个以 + 开头的参数会被认为是 rustup toolchain 名字(例如 +stable+nightly)。 查看 rustup documentation 了解 toolchain overrides 如何工作。
--config KEY=VALUE or PATH
覆盖一个 Cargo 配置的值。参数应该是一个 TOML 语法的 KEY=VALUE,或者提供一个路径来指向一个额外的配置文件 (configuration file)。 这个标记可以指定多次。 参考 command-line overrides 一节 获取更多信息。
-h
--help
打印帮助信息。
-Z flag
不稳定 (nightly-only) 的标志。 执行 cargo -Z help 获取详细信息。

环境

查看 the reference 获取 Cargo 读取的环境变量的更多信息。

退出状态

  • 0: Cargo 执行成功。
  • 101: Cargo 没有执行完成。

使用案例

  1. 清除整个 target 文件夹:

    cargo clean
    
  2. 只清除 release 产物:

    cargo clean --release
    

其他参考

cargo(1), cargo-build(1)

cargo-doc(1)

名称

cargo-doc - 为包构建文档

概要

cargo doc [options]

描述

构建本地的包及其依赖的文档。输出以 rustdoc 的通常格式存放在 target/doc 路径下。

选项

文档选项

--open
构建完成后在浏览器中打开文档。这会使用到你的默认浏览器,除非你在 BROWSER 环境变量中指定其他的。 或者可以使用 doc.browser 设置选项来设置。
--no-deps
不为依赖构建文档。
--document-private-items
文档中包含非 Public 的语法元素(Rust item)。这会在二进制目标中默认启用。

包的选择

默认情况下,如果没有提供选择包的选项,那么会按照选择的配置清单文件来选择包(当没有指定 --manifest-path 时,按照当前工目录来查找配置清单文件)。 如果工作空间根目录的配置清单文件,则会选择该工作空间的默认成员,否则仅选取配置清单文件所在的那个包。

可以通过 workspace.default-members 来显式设置工作空间的默认成员。如果没有设置,在虚拟工作空间下会选择所有的成员,在非虚拟工作空间下仅会选择根 package 。

-p spec...
--package spec...
仅为指定的 package 构建文档。 见 cargo-pkgid(1) 中关于 SPEC 格式的描述。此标志可以指定多次,而且支持 common Unix glob patterns ,如 *?[]。但是,为避免你的 shell 误在 Cargo 之前扩展这些 glob pattern,必须用单引号或双引号将每个 pattern 括起来。
--workspace
为工作空间中的所有成员构建文档。
--all
--workspace 的同义词,已弃用。
--exclude SPEC...
排除指定的包。必须与 --workspace 标志一起使用。 此标志可以指定多次,而且支持 common Unix glob patterns ,如 *?[]。但是,为避免你的 shell 误在 Cargo 之前扩展这些 glob pattern,必须用单引号或双引号将每个 pattern 括起来。

目标选择

当没有提供目标选择选项, cargo doc 会为所选包的所有二进制和库目标构建文档。如果二进制目标的名字和库目标相同,则二进制目标会被跳过。如果二进制有丢失的 required-features ,则也会被跳过。

可以通过在清单文件中为 target 设置 doc = false 来改变默认行为。使用目标选择选项时会忽略 doc 标志,并且总会为所提供的目标构建文档。

--lib
为该包的库构建文档。
--bin name...
为特定的二进制构建文档。这个标志可以指定多次,而且支持 common Unix glob patterns。
--bins
为所有的二进制目标构建文档。
--example name...
为特定的 example 构建文档。这个标志可以指定多次,而且支持 common Unix glob patterns。
--examples
为所有的 example 目标构建文档。

feature 选择

特性标志允许你控制开启哪些特性。当没有提供特性选项时,会为每个选择的包启用 default 特性。

查看 the features documentation 获取更多信息。

-F features
--features features
用空格或逗号来分隔多个启用的 feature。 工作空间成员的 feature 可以通过 package-name/feature-name 语法来启用。 该标志可以设置多次,最终将启用指定的所有 feature 。
--all-features
启用指定包的所有可用 feature。
--no-default-features
不使用指定包的 default feature 。

编译选项

--target triple
为指定的架构而构建文档,默认为宿主架构。triple 的格式为 <arch><sub>-<vendor>-<sys>-<abi>。 执行 rustc --print target-list 可以展示支持的 target 的列表。该标志可以指定多次。

也可以通过 build.target 配置

注意,指定这个标志会使Cargo在不同的模式下运行,目标制品放在单独目录。 参见 构建缓存 文档了解详情。

-r
--release
为使用 release profile 优化的产物构建文档。 另见 --profile 选项来按名称选择特定的 profile。
--profile name
用给定的 profile 构建文档。 见 the reference 查看关于 profile 的详细内容。
--ignore-rust-version
即使选择的 Rust 编译器版本落后于项目 rust-version 字段中指定的版本,也为其构建文档。
--timings=fmts
输出编译所花费时间的信息,同时跟踪并发信息。接收一个由逗号分隔的输出格式;若 --timings 没有参数,则默认使用 --timings=html。 指定输出格式 (而不是使用默认格式) 是不稳定 (unstable) 的,需要设置 -Zunstable-options。 可用的输出格式选项有:

  • html (不稳定,需要 -Zunstable-options): 写入一个人类可读的 cargo-timing.html 文件到 target/cargo-timings 文件夹,其中包含关于编译过程的报告。 同时也会写入一个文件名带着时间戳 (timestamp) 的报告文件,可以让你读取之前的编译报告。HTML 输出文件只适合人类阅读,不提供机器所需的 timing 数据。
  • json (不稳定,需要 -Zunstable-options): 生成机器可读的 JSON timing 信息。

输出选项

--target-dir directory
存放构建产物和中间文件的文件夹。也可以用 CARGO_TARGET_DIR 环境变量来设置,或者 build.target-dir 设置选项。默认会放在工作空间根目录的 target 子目录下。

显示选项

-v
--verbose
进行 verbose 输出。可以指定两遍来开启 "very verbose" 模式,输出更多的额外信息,像是依赖项的警告和构建脚本的输出信息。 也可以通过 term.verbose 配置
-q
--quiet
不打印 cargo log 信息。 也可以通过 term.quiet 配置
--color when
控制*何时*使用彩色输出。可选值有:

  • auto (默认值): 自动检测终端是否支持彩色输出。
  • always: 总是显示彩色。
  • never: 从不显示彩色。

也可以在 term.color 配置

--message-format fmt
诊断信息的输出格式。 可以指定多次,可以包含由逗号分隔的多个值。合法的值有:

  • human (默认值): 显示适合人类阅读的格式。与 shortjson 互斥。
  • short: 生成更短的适合人类阅读的格式。 与 humanjson 互斥。
  • json: 将 JSON 信息输出到 stdout。 从 the reference 获取更多详细信息。 与 humanshort 互斥。
  • json-diagnostic-short: 使得 JSON 的 rendered 属性包含 rustc 渲染的 "short" 信息。不能与 humanshort 一起使用。
  • json-diagnostic-rendered-ansi: 使得 JSON 的 rendered 属性包含嵌入的 ANSI 颜色代码以符合 rustc 的默认颜色策略。 不能与 humanshort 一起使用。
  • json-render-diagnostics: 命令 Cargo 在打印的 JSON 中不包含 rustc 的诊断信息,而是由 Cargo 自己渲染 rustc 提供的 JSON 诊断信息。Cargo 自己的 JSON 诊断信息和其他来自 rustc 的信息都会被生成。 不能与 humanshort 一起使用。

清单选项

--manifest-path path
Cargo.toml 文件的路径。 默认情况下,Cargo 在当前目录或任意的父目录中查找 Cargo.toml
--frozen
--locked
这两个 flag 都需要 Cargo.lock 文件处于无需更新的状态。如果 lock 文件缺失,或者需要被更新,Cargo 会报错退出。 --frozen flag 还会阻止 Cargo 访问网络来判断 Cargo.lock 是否过期。

这些 flag 可以用于某些场景下你想断言 Cargo.lock 无需更新 (比如在CI中构建) 或者避免网络访问。

--offline
阻止 Cargo 访问网络。如果没有这个 flag,当 Cargo 需要访问网络但是没有网络时,就会报错退出。加上这个 flag,Cargo 会尝试在不联网的情况下继续执行 (如果可以的话) 。

要小心这会导致与在线模式不同的解析结果。Cargo 会限制自己在本地已下载的 crate 中查找版本,即使在本地的 index 拷贝中表明还有更新的版本。 cargo-fetch(1) 命令可以在进入离线模式前下载依赖。

同样的功能也可以通过设置 net.offline 配置选项来实现。

通用选项

+toolchain
如果 Cargo 由 rustup 安装,那么 cargo 后第一个以 + 开头的参数会被认为是 rustup toolchain 名字(例如 +stable+nightly)。 查看 rustup documentation 了解 toolchain overrides 如何工作。
--config KEY=VALUE or PATH
覆盖一个 Cargo 配置的值。参数应该是一个 TOML 语法的 KEY=VALUE,或者提供一个路径来指向一个额外的配置文件 (configuration file)。 这个标记可以指定多次。 参考 command-line overrides 一节 获取更多信息。
-h
--help
打印帮助信息。
-Z flag
不稳定 (nightly-only) 的标志。 执行 cargo -Z help 获取详细信息。

杂项

-j N
--jobs N
并行执行的任务数。可以通过 build.jobs 配置。默认值为逻辑CPU数。如果设置为负值,则最大的并行任务数为*逻辑CPU数*加*这个负数*。该值不能为0。
--keep-going
依赖图中的 crate 能构建多少就构建多少,而不是一个失败就停止。功能还不稳定,需要 -Zunstable-options

环境

查看 the reference 获取 Cargo 读取的环境变量的更多信息。

退出状态

  • 0: Cargo 执行成功。
  • 101: Cargo 没有执行完成。

使用案例

  1. 为本地包及其依赖构建文档,输出放在 target/doc

    cargo doc
    

其他参考

cargo(1), cargo-rustdoc(1), rustdoc(1)

cargo-fetch(1)

名称

cargo-fetch - 从网络中下载一个包的依赖。

概要

cargo fetch [options]

描述

如果有一个可用的 Cargo.lock ,则该命令可以保证所有的 git 依赖和/或 registry 依赖都会被下载且本地可用。cargo fetch 之后的命令都可以离线 (offline) 执行,除非 lock file 发生改变。

如果 lock file 不可用,则该命令会在下载依赖之前生成 lock file。

如果没有指定 --target ,则所有 target 的依赖都会被下载。

另见 cargo-prefetch 插件,其可以添加一个命令来下载流行的 crates。如果你打算在无网络的环境使用 Cargo (使用 --offline),那么这个命令可能会很有用。

选项

fetch 选项

--target triple
为指定的架构而下载依赖,默认为所有架构下载。triple 的格式为 <arch><sub>-<vendor>-<sys>-<abi>。 执行 rustc --print target-list 可以展示支持的 target 的列表。该标志可以指定多次。

也可以通过 build.target 配置

注意,指定这个标志会使Cargo在不同的模式下运行,目标制品放在单独目录。 参见 构建缓存 文档了解详情。

显示选项

-v
--verbose
进行 verbose 输出。可以指定两遍来开启 "very verbose" 模式,输出更多的额外信息,像是依赖项的警告和构建脚本的输出信息。 也可以通过 term.verbose 配置
-q
--quiet
不打印 cargo log 信息。 也可以通过 term.quiet 配置
--color when
控制*何时*使用彩色输出。可选值有:

  • auto (默认值): 自动检测终端是否支持彩色输出。
  • always: 总是显示彩色。
  • never: 从不显示彩色。

也可以在 term.color 配置

清单选项

--manifest-path path
Cargo.toml 文件的路径。 默认情况下,Cargo 在当前目录或任意的父目录中查找 Cargo.toml
--frozen
--locked
这两个 flag 都需要 Cargo.lock 文件处于无需更新的状态。如果 lock 文件缺失,或者需要被更新,Cargo 会报错退出。 --frozen flag 还会阻止 Cargo 访问网络来判断 Cargo.lock 是否过期。

这些 flag 可以用于某些场景下你想断言 Cargo.lock 无需更新 (比如在CI中构建) 或者避免网络访问。

--offline
阻止 Cargo 访问网络。如果没有这个 flag,当 Cargo 需要访问网络但是没有网络时,就会报错退出。加上这个 flag,Cargo 会尝试在不联网的情况下继续执行 (如果可以的话) 。

要小心这会导致与在线模式不同的解析结果。Cargo 会限制自己在本地已下载的 crate 中查找版本,即使在本地的 index 拷贝中表明还有更新的版本。 cargo-fetch(1) 命令可以在进入离线模式前下载依赖。

同样的功能也可以通过设置 net.offline 配置选项来实现。

通用选项

+toolchain
如果 Cargo 由 rustup 安装,那么 cargo 后第一个以 + 开头的参数会被认为是 rustup toolchain 名字(例如 +stable+nightly)。 查看 rustup documentation 了解 toolchain overrides 如何工作。
--config KEY=VALUE or PATH
覆盖一个 Cargo 配置的值。参数应该是一个 TOML 语法的 KEY=VALUE,或者提供一个路径来指向一个额外的配置文件 (configuration file)。 这个标记可以指定多次。 参考 command-line overrides 一节 获取更多信息。
-h
--help
打印帮助信息。
-Z flag
不稳定 (nightly-only) 的标志。 执行 cargo -Z help 获取详细信息。

环境

查看 the reference 获取 Cargo 读取的环境变量的更多信息。

退出状态

  • 0: Cargo 执行成功。
  • 101: Cargo 没有执行完成。

使用案例

  1. 下载所有的依赖:

    cargo fetch
    

其他参考

cargo(1), cargo-update(1), cargo-generate-lockfile(1)

cargo-fix(1)

定义

cargo-fix - 自动修复由rustc报告的lint警告

概要

cargo fix [options]

描述

这个Cargo子命令会自动从诊断中获取rustc的建议,如警告,并将其应用于你的源代码。 帮助自动化那些rustc本身已经知道如何告诉你怎样修复的任务。

执行 cargo fix 将在引擎下执行 cargo-check(1) 。 自动修复包所有警告(如果可能的话),在检查结束后显示剩余所有警告。 比如,想把所有修正应用于当前包,可以运行:

cargo fix

其行为与 cargo check --all-targets 相同。

cargo fix 只能够修复用 cargo check 常规编译的代码。 如果代码有条件地启用了可选特性,你需要启用这些特性才能对该代码进行分析。

cargo fix --features foo

同样,其他 cfg 表达式,如平台特定的代码,将需要传递 --target 来修复给定目标的代码。

cargo fix --target x86_64-pc-windows-gnu

如果你在使用 cargo fix 时遇到任何问题,或者有其他功能需求,请在 https://github.com/rust-lang/cargo 上提issue。

版次迁移

cargo fix 子命令也可以用来将包从一个Edition版次迁移到另一个版次。通常的过程是:

  1. 运行 cargo fix --edition 。如果项目有多个特性,也可以考虑使用 --all-features 标志。 如果你的项目有特定平台的代码被 cfg 属性控制,你可能需要使用不同的 --target 标志,多次运行 cargo fix --edition
  2. 修改 Cargo.toml ,将edition field设置为新版本。
  3. 运行你的项目测试,以验证所有内容是否仍然有效。如果有新的警告,你可以考虑再次运行 cargo fix (没有 --edition 标志) 来应用编译器给出的任何建议。

希望这样就可以了! 请记住上面提到的注意事项, cargo fix 不能更新非活动特性或 cfg 表达式的代码。 另外,在某些罕见的情况下,编译器无法自动将所有代码迁移到新版本,这可能需要在用新版本构建后进行手动修改。

选项

修复选项

--broken-code
即使代码已有编译错误,仍然修复。如果cargo fix不能应用修改,这就很有用。 它将应用这些变化,并在工作目录中留下破坏的代码以便检查和手动修复。
--edition
应用修改,将代码更新到下一个版次。 这将不会更新 Cargo.toml 配置清单中的版次。必须在cargo fix --edition完成后手动更新。
--edition-idioms
应用建议,将代码更新为当前版次的首选样式。
--allow-no-vcs
即使没有检测到VCS,也可以修复代码。
--allow-dirty
即使工作目录VCS有变化,也可以修复代码。
--allow-staged
即使工作目录有VCS暂存变化,也能修复代码。

包的选择

默认情况下,如果没有提供选择包的选项,那么会按照选择的配置清单文件来选择包(当没有指定 --manifest-path 时,按照当前工目录来查找配置清单文件)。 如果工作空间根目录的配置清单文件,则会选择该工作空间的默认成员,否则仅选取配置清单文件所在的那个包。

可以通过 workspace.default-members 来显式设置工作空间的默认成员。如果没有设置,在虚拟工作空间下会选择所有的成员,在非虚拟工作空间下仅会选择根 package 。

-p spec...
--package spec...
只修复指定的包。 见 cargo-pkgid(1) 了解 SPEC 格式。这个标志可以多次指定,并支持常见的 Unix 通配符模式,如 *, ?[]. 然而,为了避免shell在Cargo处理通配符模式之前意外地扩展它们,必须在每个模式周围使用单引号或双引号。
--workspace
修复工作空间的所有成员。
--all
弃用的 --workspace 的别名。
--exclude SPEC...
排除指定的包。必须与 --workspace 标志一起使用。 这个标志可以多次指定,并支持常见的 Unix 通配符模式,如 *, ?[] 。 然而,为了避免shell在Cargo处理通配符模式之前意外地扩展它们,必须在每个模式周围使用单引号或双引号。

目标选择

当没有给出目标选择选项时, cargo fix 将修复所有目标(隐含 --all-targets )。如果二进制文件的 required-features 缺失,将被跳过。

传递目标选择标志将只修复指定的目标。

注意 --bin--example--test--bench 标志也支持常见的Unix通配符模式,如 *?[] 。 然而,为了避免shell在Cargo处理通配符模式之前意外地扩展它们,必须在每个glob模式周围使用单引号或双引号。

--lib
修复包的库。
--bin name...
修复指定的二进制文件。这个标志可以多次指定,并支持常见的Unix通配符模式。
--bins
修复所有二进制目标。
--example name...
修复指定的示例。这个标志可以多次指定,并支持常见的Unix通配符模式。
--examples
修复所有实例目标。
--test name...
修复指定的集成测试。这个标志可以多次指定,并支持常见的Unix通配符模式。
--tests
修复测试模式下所有设置了test = true 配置清单标志的目标。 默认情况下,这包括作为单元测试构建的库和二进制文件,以及集成测试。请注意,这也将构建任何所需的依赖,所以lib目标可能会被构建两次(一次作为单元测试,一次作为二进制文件、集成测试等的依赖)。 通过在目标的配置清单中设置test标志,可以启用或禁用目标。
--bench name...
修复指定的性能测试。这个标志可以多次指定,并支持常见的Unix通配符模式。
--benches
修复性能测试模式下所有设置了bench = true配置清单标志的目标。 默认情况下,这包括作为性能测试构建的库和二进制文件,以及性能测试目标。请注意,这也将构建任何所需的依赖,所以lib目标可能会被构建两次(一次是作为性能测试,一次是作为二进制文件、性能测试等的依赖)。 通过在目标的配置清单中设置bench标志,可以启用或禁用目标。
--all-targets
修复所有目标。这等同于指定 --lib --bins --tests --benches --examples

特性选择

特性标志允许你控制开启哪些特性。当没有提供特性选项时,会为每个选择的包启用 default 特性。

特性文档 了解更多内容。

-F features
--features features
激活的特性列表用空格或逗号分隔。可以用package-name/feature-name语法启用工作空间成员的特性。这个标志可以多次指定,从而可以启用所有指定的特性。
--all-features
激活所有选定包的所有可用特性。
--no-default-features
不激活所选包的default特性。

编译选项

--target triple
对给定的架构进行修复。默认是主机架构。三元组的一般格式是<arch><sub>-<vendor>-<sys>-<abi> 。 运行rustc --print target-list以获得支持的目标列表。这个标志可以多次指定。

也可以通过 build.target 配置

注意,指定这个标志会使Cargo在不同的模式下运行,目标制品放在单独目录。 参见 构建缓存 文档了解详情。

-r
--release
修复release编译设置的优化制品。 参见 --profile选项,以按名称选择特定的编译设置。
--profile name
用给定的编译设置进行修复。

作为一种特殊情况,指定 test 编译设置也将启用测试模式下的检查,这将启用检查测试并启用test cfg选项。 见 rustc tests 了解细节。

参考 了解编译设置细节。

--ignore-rust-version
即使所选的Rust编译器比项目rust-version字段中配置的所需Rust版本更早,也可以修复目标。
--timings=fmts
输出每次编译需要多长时间的信息,并跟踪时间段的并发信息。 接受可选的逗号分隔的输出格式列表;没有参数的--timings将默认为--timings=html。 指定未稳定的输出格式(而不是默认),需要-Zunstable-options。 有效的输出格式:

  • html (未稳定, 要求 -Zunstable-options): 在target/cargo-timings目录下生成可阅读的 cargo-timing.html 文件,并附编译报告。 如果你想查看更早的运行情况,也可以将报告写到同一目录下,文件名带有时间戳。 HTML输出适合人类阅读,机器不可读。
  • json (未稳定, 要求 -Zunstable-options): 发送机器可读的关于时间信息的JSON。

输出选项

--target-dir directory
所有生成制品和中间文件的目录。 也可以用 CARGO_TARGET_DIR 环境变量, 或 build.target-dir 配置。 默认为工作空间的根target

Display Options

-v
--verbose
进行详细输出。可以指定两遍来开启 "非常详细" 模式,输出更多的额外信息,像是依赖项的警告和构建脚本的输出信息。 也可以通过 term.verbose 配置
-q
--quiet
不打印 cargo 日志信息。 也可以通过 term.quiet 配置
--color when
控制使用彩色输出。可选值有:

  • auto (默认值): 自动检测终端是否支持彩色输出。
  • always: 总是显示彩色。
  • never: 从不显示彩色。

也可以在 term.color 配置

--message-format fmt
特征信息的输出格式。可以多次指定,数值由逗号分隔。有效值:

  • human (默认): 以人可阅读的文本格式显示。 shortjson 冲突。
  • short: 发出更短的、人可阅读的文本信息。 humanjson 冲突。
  • json: 向标准输出发送JSON信息。 见 参考 了解详情. humanshort 冲突。
  • json-diagnostic-short: 确保JSON消息的rendered字段包含rustc的"short"渲染。不能和 human short
  • json-diagnostic-rendered-ansi: 确保JSON消息的rendered字段包含嵌入式ANSI颜色代码,以遵从rustc的默认颜色方案。 不能和 human short
  • json-render-diagnostics: 指示Cargo在打印的JSON信息中不包含rustc的特征信息,而是由Cargo来渲染来自rustc的JSON信息。Cargo自身的JSON和其他来自rustc的信息仍会发送。不能和 human short

配置选项

--manifest-path path
Cargo.toml 文件的路径。默认, Cargo 在当前目录和任意父目录搜索 Cargo.toml 文件。
--frozen
--locked
这些标志都要求 Cargo.lock 文件是最新的。 如果lock文件丢失, 或是需要更新, Cargo会返回错误并退出,--frozen 选项还会阻止cargo通过网络来判断其是否过期。

可以用于断言 Cargo.lock 文件是否最新状态(例如CI构建)或避免网络访问。

--offline
阻止Cargo访问网络。如果不指定该选项,Cargo会在需要使用网络但不可用时停止构建并返回错误。设置该标识,Cargo将尽可能不使用网络完成构建。

需注意,这样可能会导致与在线模式不同的依赖处理,Cargo将限制仅使用已下载到本地的crate,即使本地索引中有更新版本。 查阅 cargo-fetch(1) 命令,在脱机前下载依赖。

也可以用 net.offline 配置

常规选项

+toolchain
如果Cargo已经通过rustup安装,并且第一个传给 cargo 的参数以 + 开头, 则当作rustup的工具链名称。(例如 +stable+nightly). 查阅 rustup 文档 了解关于工具链覆盖的信息。
--config KEY=VALUE or PATH
覆盖Cargo配置项的值,该参数应当为TOML KEY=VALUE 语法, 或者提供附加的配置文件的路径。该标识可以多次指定。 查阅 命令行覆盖部分 获取更多信息
-h
--help
打印帮助信息。
-Z flag
Cargo不稳定的(每日构建)标志。运行 cargo -Z help 了解详情。

其他选项

-j N
--jobs N
并行执行的任务数。可以通过 build.jobs 配置。默认值为逻辑CPU数。如果设置为负值,则最大的并行任务数为*逻辑CPU数*加*这个负数*。该值不能为0。
--keep-going
尽可能的构建依赖图中的 crate ,而不是一个失败就停止。功能还不稳定,需要 -Zunstable-options

环境

查阅 参考 了解Cargo读取环境变量。

退出状态

  • 0: Cargo 执行成功。
  • 101: Cargo 没有成功完成。

示例

  1. 将编译器建议修复本地包:

    cargo fix
    
  2. 更新包到下一版本前的准备:

    cargo fix --edition
    
  3. 应用当前版本建议的首选样式:

    cargo fix --edition-idioms
    

参阅

cargo(1), cargo-check(1)

cargo-run(1)

定义

cargo-run - 运行当前包

概要

cargo run [options] [-- args]

说明

运行本地包的二进制程序或实例。

两个破折号(--)后的所有参数都传递给二进制程序运行。 如果同时向Cargo和二进制程序传递参数,那么 -- 后面的参数将传递给二进制程序,前面的参数将传递给Cargo。

选项

包的选择

默认情况下,选中当前工作目录下的包。可以用 -p 标志来选择工作空间中不同的包。

-p spec
--package spec
运行包。 见 cargo-pkgid(1) 了解 SPEC 规格。

目标选择

当未给出目标选择选项时, cargo run 将运行二进制目标。如果有多个二进制目标,必须传递一个目标标志。或者,在 Cargo.toml 指定 [package]default-run 字段。

--bin name
运行指定二进制。
--example name
运行指定实例。

特性选择

特性标志允许你控制开启哪些特性。当没有提供特性选项时,会为每个选择的包启用 default 特性。

参阅 特性文档 了解更多内容。

-F features
--features features
要激活的特性列表用空格或逗号分隔。 工作空间成员的特性可以用package-name/feature-name语法启用。 这个标志可以被多次指定,以启用所有指定的特性。
--all-features
激活所有选定包的所有可用特性。
--no-default-features
不要激活所选包的default特性。

编译选项

--target triple
运行给定的架构。默认是主机架构。三元组的常规格式是 <arch><sub>-<vendor>-<sys>-<abi>。 运行 rustc --print target-list 以获得支持的目标列表。

也可以通过 build.target 配置

注意,指定这个标志会使Cargo在不同的模式下运行,目标制品放在单独目录。 参见 构建缓存 文档了解详情。

-r
--release
release 编译设置运行优化的制品。 参见 --profile 选项,以按名称选择特定的编译设置。
--profile name
以给定的编译设置运行。 见 参考 了解编译设置详情。
--ignore-rust-version
即使所选的Rust编译器比项目rust-version字段中配置所需的Rust版本更早,仍运行目标。
--timings=fmts
输出每次编译需要多长时间的信息,并跟踪时间段的并发信息。 接受可选的逗号分隔的输出格式列表;没有参数的--timings将默认为--timings=html。 指定未稳定的输出格式(而不是默认),需要-Zunstable-options。 有效的输出格式:

  • html (未稳定, 要求 -Zunstable-options): 在target/cargo-timings目录下生成可阅读的 cargo-timing.html 文件,并附编译报告。 如果你想查看更早的运行情况,也可以将报告写到同一目录下,文件名带有时间戳。 HTML输出适合人类阅读,机器不可读。
  • json (未稳定, 要求 -Zunstable-options): 发送机器可读的关于时间信息的JSON。

输出选项

--target-dir directory
所有生成制品和中间文件的目录。 也可以用 CARGO_TARGET_DIR 环境变量, 或 build.target-dir 配置。 默认为工作空间的根target

显示选项

-v
--verbose
进行详细输出。可以指定两遍来开启 "非常详细" 模式,输出更多的额外信息,像是依赖项的警告和构建脚本的输出信息。 也可以通过 term.verbose 配置
-q
--quiet
不打印 cargo 日志信息。 也可以通过 term.quiet 配置
--color when
控制使用彩色输出。可选值有:

  • auto (默认值): 自动检测终端是否支持彩色输出。
  • always: 总是显示彩色。
  • never: 从不显示彩色。

也可以在 term.color 配置

--message-format fmt
特征信息的输出格式。可以多次指定,数值由逗号分隔。有效值:

  • human (默认): 以人可阅读的文本格式显示。 shortjson 冲突。
  • short: 发出更短的、人可阅读的文本信息。 humanjson 冲突。
  • json: 向标准输出发送JSON信息。 见 参考 了解详情. humanshort 冲突。
  • json-diagnostic-short: 确保JSON消息的rendered字段包含rustc的"short"渲染。不能和 human short
  • json-diagnostic-rendered-ansi: 确保JSON消息的rendered字段包含嵌入式ANSI颜色代码,以遵从rustc的默认颜色方案。 不能和 human short
  • json-render-diagnostics: 指示Cargo在打印的JSON信息中不包含rustc的特征信息,而是由Cargo来渲染来自rustc的JSON信息。Cargo自身的JSON和其他来自rustc的信息仍会发送。不能和 human short

配置选项

--manifest-path path
Cargo.toml 文件的路径。默认, Cargo 在当前目录和任意父目录搜索 Cargo.toml 文件。
--frozen
--locked
这些标志都要求 Cargo.lock 文件是最新的。 如果lock文件丢失, 或是需要更新, Cargo会返回错误并退出,--frozen 选项还会阻止cargo通过网络来判断其是否过期。

可以用于断言 Cargo.lock 文件是否最新状态(例如CI构建)或避免网络访问。

--offline
阻止Cargo访问网络。如果不指定该选项,Cargo会在需要使用网络但不可用时停止构建并返回错误。设置该标识,Cargo将尽可能不使用网络完成构建。

需注意,这样可能会导致与在线模式不同的依赖处理,Cargo将限制仅使用已下载到本地的crate,即使本地索引中有更新版本。 查阅 cargo-fetch(1) 命令,在脱机前下载依赖。

也可以用 net.offline 配置

常规选项

+toolchain
如果Cargo已经通过rustup安装,并且第一个传给 cargo 的参数以 + 开头, 则当作rustup的工具链名称。(例如 +stable+nightly). 查阅 rustup 文档 了解关于工具链覆盖的信息。
--config KEY=VALUE or PATH
覆盖Cargo配置项的值,该参数应当为TOML KEY=VALUE 语法, 或者提供附加的配置文件的路径。该标识可以多次指定。 查阅 命令行覆盖部分 获取更多信息
-h
--help
打印帮助信息。
-Z flag
Cargo不稳定的(每日构建)标志。运行 cargo -Z help 了解详情。

其他选项

-j N
--jobs N
并行执行的任务数。可以通过 build.jobs 配置。默认值为逻辑CPU数。如果设置为负值,则最大的并行任务数为*逻辑CPU数*加*这个负数*。该值不能为0。
--keep-going
尽可能的构建依赖图中的 crate ,而不是一个失败就停止。功能还不稳定,需要 -Zunstable-options

环境

查阅 参考 了解Cargo读取环境变量。

退出状态

  • 0: Cargo 执行成功。
  • 101: Cargo 没有成功完成。

示例

  1. 构建本地包并运行其主要目标(假设仅有一个二进制文件):

    cargo run
    
  2. 运行附带参数的实例:

    cargo run --example exname -- --exoption exarg1 exarg2
    

参阅

cargo(1), cargo-build(1)

cargo-rustc(1)

定义

cargo-rustc - 编译当前包,并将额外参数传递给编译器

概要

cargo rustc [options] [-- args]

说明

当前包的指定目标(或由 -p 指定的已有的包)将与它的所有依赖一起被编译。 指定的 args 将全部传递给最终的编译器调用,而非依赖项的参数。 请注意,编译器仍然会无条件地接受参数,如 -L-extern ,和 -crat-type , 而指定的的 args 将被添加到编译器的调用中。

有关 rustc 的标志位的文档请查看 https://doc.rust-lang.org/rustc/index.html

该命令要求在提供额外参数时,只有一个目标被编译。 如果当前的包有多个的目标,则必须使用 --lib--bin 等过滤器来选择编译目标。 目标被编译。

使用 RUSTFLAGS environment variable 或者 build.rustflags config value 来给 Cargo 创建的所有编译器进程传递标志位。

选项

选择包

当前工作目录下的包是默认选中的。可以使用 -p 选项来选择工作空间中不同的包。

-p spec
--package spec
要构建的包。请在 cargo-pkgid(1) 查看 SPEC 格式

选择构建目标

当没有提供构建目标选择的选项时, cargo rustc 会构建选中包的所有二进制程序和类库目标。

如果要构建集成测试或基准测试,二进制目标也会自动构建。 这允许集成测试执行二进制文件以测试其行为。 集成测试构建时会设置 CARGO_BIN_EXE_<name> [environment variable](.../reference/environment-variables.html#environment-variables-cargo-sets for-crates) , 以便它可以使用 env macro 来定位可执行程序。

传递目标选中标志可以仅编译指定的目标。

注意 --bin--example--test--bench 标志也 支持常见的 Unix glob pattern,比如 * , ?[] 。 然而,为了避免你的 shell 在 Cargo 处理 glob pattern 之前意外地扩展它们, 你必须在每个 glob pattern 周围使用单引号或双引号。

--lib
构建包的类库
--bin 名称...
构建指定的二进制程序。这个标志位可以多次指定并且支持通用的 Unix glob pattern 格式。
--bins
构建所有二进制目标
--example 名称...
构建指定的例子。这个标志位可以多次指定并且支持通用的 Unix glob pattern 格式。
--examples
构建所有例子目标
--test 名称...
构建指定的集成测试。这个标志位可以多次指定并且支持通用的 Unix glob pattern 格式。
--tests
在清单文件中将 test = true 来在测试模式下构建所有目标。 默认情况下,这包括构建为 单元测试和集成测试的库和二进制文件。请注意,这也会构建任何 所需的依赖项,所以 lib 目标可能会被构建两次(一次是作为一个 单元测试,一次作为二进制文件、集成测试等的依赖项)。 可以在清单文件通过设置目标的 test 标志来启用或禁用此目标。
--bench 名称...
构建指定的基准测试。这个标志位可以多次指定并且支持通用的 Unix glob pattern 格式。
--benches
在清单文件中将 bench = true 来在测试模式下构建所有目标。 默认情况下,这包括构建为 基准测试的库和二进制文件。请注意,这也会构建任何 所需的依赖项,所以 lib 目标可能会被构建两次(一次是作为一个 基准测试,一次作为二进制文件、基准测试等的依赖项)。 可以在清单文件通过设置目标的 bench 标志来启用或禁用此目标。
--all-targets
构建所有目标。 相当于指定 --lib --bins --tests --benches --examples.

选择特性

feature 标志允许你有选择的启用特性。 当没有设置这个此标志时,将为所有已选的包启用 defualt 特性。

更多细节查看 the features documentation

-F 特性
--features 特性
要启用的特性列表,列表用空格或逗号分割。 工作空间中成员的特性可以通过 package-name/feature-name 语法启用。 此标志可以多次指定,会启用所有指定的特性。
--all-features
为全部选择的包启用所有可用的特性。
--no-default-features
不要为选择的包 默认 启用默认特性。

编译选项

--target triple
指定架构的构建。 默认为宿主机的架构。三元组的通用格式为 <arch><sub>-<vendor>-<sys>-<abi>。运行 rustc --print target-list 来获取支持的目标列表。 这个标志可以指定多次。

这也可以与 build.target config value 一起使用。

注意,指定这个标志会使 Cargo 在不同的模式下运行,目标 artifacts 被放在一个单独的目录中。 更多细节请参见 build cache 文档。

-r
--release
release 配置构建优化的 artifacts 。 请参阅 --profile 选项,通过名称选择一个特定的配置。
--profile name
用给定的配置进行测试。

rustc 子命令会对下列特殊名称的配置有特殊的行为:

  • check — 与 cargo-check(1) 命令一样进行构建,使用 dev 配置。
  • test — 与 cargo-test(1) 命令一样进行构建,在测试模式下构建,这会启用测试并启用 test cfg配置。 更多信息请查看 rustc tests
  • bench — 与 cargo-bench(1) 命令一样进行构建,与 test 配置类似。

关于配置的更多细节,请参见 the reference

--ignore-rust-version
即使选择的 Rust 编译器比项目的 rust-version 字段中配置的所需的Rust版本要低,也要测试目标。
--timings=fmts
输出每次编译所需时间的信息,并跟踪一段时间的并发信息。 接受一个可选的逗号分隔的输出格式列表; 没有参数的 --timings 将默认为 --timings=html 。 指定一个输出格式(而不是默认的)是不稳定的,需要 -Zunstable-options 。 有效的输出格式:

  • html (不稳定,需要 -Zunstable-options): 在 target/cargo-timings 目录下写一个方便阅读的文件 cargo-timing.html ,并附上编译报告 。 如果你想查看更早的运行情况,也可以在同一目录下写一份文件名中带有时间戳报告。 HTML输出只适合用户使用,并不提供机器可读的计时数据。
  • json (不稳定,需要 -Zunstable-options): 发出机器可读的JSON格式的计时信息。
--crate-type crate-type
按给定的 crate 类型进行构建。 这个标志接收逗号分割的 crate 类型列表,允许的 crate 类型与清单中配置 Cargo target 的 crate-type 字段相同。 在 crate-type 字段查看可用的类型

如果清单中制定了列表, 并且提供了 --crate-type, 命令行参数会覆盖清单指定的列表。

此标志仅用于构建 libexample 类库目标.

输出选项

--target-dir directory
所有生成的 artifacts 和中间文件的目录。 也可以与 CARGO_TARGET_DIR 环境变量或 build.target-dir 配置项 一起指定。 默认是工作空间中 target 的根目录。

显示选项

-v
--verbose
使用 verbose 级别输出详细信息。 指定两次此选项来输出 "十分详细" 的输出信息, 这会包含额外的输出信息,比如依赖警告和构建脚本输出。 也可以与 term.verbose config value 一起使用。
-q
--quiet
不要打印任何 cargo 日志信息。 也可以与 term.quiet config value 一起使用。
--color when
控制的日志的颜色。 有效的值如下:

  • auto (默认): 自动检测终端颜色支持是否可用。
  • always: 总是带颜色显示。
  • never: 不带颜色显示.

也可以与 term.color config value 一起使用。

--message-format fmt
诊断信息的输出格式。可以多次指定,由逗号分隔的数值组成。有效值:

  • human (默认): 以人类可读的文本格式显示。与 shortjson冲突。
  • short: 生成更短的、人类可读的文本信息。 与humanjson 冲突。
  • json: 生成 JSON 信息输出到 stdout. 更多细节请参见 the reference。 与 humanshort冲突。
  • json-diagnostic-short: 确保 JSON 信息的 rendered 包含来自 rustc 的 "short" 渲染。 不能与 humanshort 一起使用。
  • json-diagnostic-rendered-ansi: 确保 JSON 信息的 rendered 包含 嵌入式ANSI颜色代码来兼容 rustc 的默认颜色方案。 不能与 humanshort 一起使用。
  • json-render-diagnostics: 指示 Cargo 在打印的JSON信息中不包含 rustc 的诊断信息, 而是由 Cargo 自己来渲染来自 rustc 的 JSON 诊断信息。 Cargo 自己的 JSON 诊断程序和其他来自 rustc 的诊断程序仍然会被生成出来。 不能与 humanshort 一起使用。

清单选项

--manifest-path path
Cargo.toml 文件的路径. 默认情况下,Cargo 会在当前目录或任何父目录下搜索 Cargo.toml 文件。
--frozen
--locked
这两个标志都要求 Cargo.lock 文件是最新的。 如果 .lock 文件缺失,或者需要更新,Cargo 将以错误退出。 --frozen 标志也可以防止 Cargo 访问网络以确定其是否过期。

这些可以用于需要判断 Cargo.lock 文件是否最新(比如CI构建)或者想避免网络访问的环境中。

--offline
禁止 Cargo 在任何情况下访问网络。 如果没有这个标志,当 Cargo 需要访问网络而网络不可用时,它会以错误的方式停止。 有了这个标志,Cargo会尝试在没有网络的情况下进行。

请注意,这可能会导致与在线模式不同的依赖方案。Cargo 会将自己限制在本地的 crate 仓库上, 即使在本地拷贝的索引中可能有更新的版本也是如此。 参见 cargo-fetch(1) 命令来在离线前下载依赖关系。

也可以用 net.offline config value 来指定。

通用选项

+toolchain
如果 Cargo 已经和 rustup 一起安装, 并且 cargo 的第一个参数以 + 开头, 它将被解释为一个rustup工具链的名字 (比如 +stable 或者 +nightly)。 更多关于工具链覆盖工作的信息,请参见 rustup documentation
--config KEY=VALUE or PATH
覆盖一个 Cargo 配置值。参数应该使用 TOML 的 KEY=VALUE 语法,或者提供一个额外配置文件的路径。 这个标志可以被多次指定。更多信息请参见 command-line overrides section
-h
--help
打印帮助信息。
-Z flag
Cargo 的不稳定 (仅限 nightly 版本) 标志。 更多信息请运行 cargo -Z help

其他选项

-j N
--jobs N
要运行的并行作业的数量。 也可以通过 build.jobs config value 配置值来指定。 默认为逻辑CPU的数量。如果是负数,它将最大的并行作业数量设置为逻辑CPU的数量加上所提供的值。不应该是0。
--keep-going
尽可能多地构建依赖关系图中的 crates, 而不是有一个 crate 构建失败则中止构建。 不稳定,需要 -Zunstable-options
--future-incompat-report
展示一个未来兼容性报告(future-incompat report),显示在执行此命令过程中产生的任何未来不兼容(future-incompatible)的警告

请参阅 cargo-report(1)

环境

更多关于 Cargo 读取的环境变量信息,请参见the reference

退出状态

  • 0: Cargo 成功退出.
  • 101: Cargo 错误退出.

示例

  1. 检查你的软件包(不包括依赖)是否使用了不安全代码:

    cargo rustc --lib -- -D unsafe-code
    
  2. 在每日版编译器上尝试实验标志,比如这个标志打印了所有 type 的大小:

    cargo rustc --lib -- -Z print-type-sizes
    
  3. 用命令行选项覆盖 Cargo.toml 中的 crate-type 字段:

    cargo rustc --lib --crate-type lib,cdylib
    

另请参见

cargo(1), cargo-build(1), rustc(1)

cargo-rustdoc(1)

定义

cargo-rustdoc - 使用指定标志构建包的文档

概要

cargo rustdoc [options] [-- args]

说明

当前包的指定目标(或由 -p 指定的已有的包)将与传递给最终 rustdoc 调用的指定 args 参数一起生成文档。 依赖不会作为此命令的一部分,依赖不会生成文档。 请注意,rustdoc 仍然会无条件地接受参数,如 -L-extern ,和 -crat-type , 而指定的的 args 将被添加到 rustdoc 的调用中。

有关 rustdoc 的标志位的文档请查看 https://doc.rust-lang.org/rustdoc/index.html

该命令要求在提供额外参数时,只有一个目标被编译。 如果当前的包有多个的目标,则必须使用 --lib--bin 等过滤器来选择编译目标。 目标被编译。

使用 RUSTDOCFLAGS environment variable 或者 build.rustdocflags config value 来给 Cargo 创建的所有 rustdoc 进程传递标志位。

选项

文档选项

--open
文档生成后将在浏览器中打开。 命令会使用默认浏览器,除非在环境变量中使用 BROWSER 或 使用 doc.browser 配置项定义了其他浏览器。

选择包

当前工作目录下的包是默认选中的。可以使用 -p 选项来选择工作空间中不同的包。

-p spec
--package spec
要生成文档的包。请在 cargo-pkgid(1) 查看 SPEC 格式

选择构建目标

当没有提供构建目标选择的选项时, cargo rustdoc 会为选中包的所有二进制程序和类库目标生成文档。 与类库名称相同的二进制目标将被跳过。 缺少 required-features 的二进制目标将被跳过。

传递目标选中标志可以仅为指定的目标生产文档。

注意 --bin--example--test--bench 标志也 支持常见的 Unix glob pattern,比如 * , ?[] 。 然而,为了避免你的 shell 在 Cargo 处理 glob pattern 之前意外地扩展它们, 你必须在每个 glob pattern 周围使用单引号或双引号。

--lib
为包的类库生成文档
--bin name...
为指定二进制目标生成文档。这个标志位可以多次指定并且支持通用的 Unix glob pattern 格式。
--bins
为所有二进制目标生成文档
--example name...
为指定例子生成文档。这个标志位可以多次指定并且支持通用的 Unix glob pattern 格式。
--examples
为所有例子目标生成文档
--test name...
为指定集成测试生成文档。这个标志位可以多次指定并且支持通用的 Unix glob pattern 格式。
--tests
在清单文件中将 test = true 来在测试模式下为所有目标生成文档。 默认情况下,这包括构建为 单元测试和集成测试的库和二进制文件。请注意,这也会构建任何 所需的依赖项,所以 lib 目标可能会被构建两次(一次是作为一个 单元测试,一次作为二进制文件、集成测试等的依赖项)。 可以在清单文件通过设置目标的 test 标志来启用或禁用此目标。
--bench name...
为指定的基准测试生成文档。这个标志位可以多次指定并且支持通用的 Unix glob pattern 格式。
--benches
在清单文件中将 bench = true 来在基准模式下为所有目标生成文档。 默认情况下,这包括构建为 基准测试的库和二进制文件。请注意,这也会构建任何 所需的依赖项,所以 lib 目标可能会被构建两次(一次是作为一个 基准测试,一次作为二进制文件、基准测试等的依赖项)。 可以在清单文件通过设置目标的 bench 标志来启用或禁用此目标。
--all-targets
为所有目标生成文档。 相当于指定 --lib --bins --tests --benches --examples.

选择特性

feature 标志允许你有选择的启用特性。 当没有设置这个此标志时,将为所有已选的包启用 defualt 特性。

更多细节查看 the features documentation

-F features
--features features
要启用的特性列表,列表用空格或逗号分割。 工作空间中成员的特性可以通过 package-name/feature-name 语法启用。 此标志可以多次指定,会启用所有指定的特性。
--all-features
为全部选择的包启用所有可用的特性。
--no-default-features
不要为选择的包 默认 启用默认特性。

编译选项

--target triple
为指定架构生成文档。 默认为宿主机的架构。三元组的通用格式为 <arch><sub>-<vendor>-<sys>-<abi>。运行 rustc --print target-list 来获取支持的目标列表。 这个标志可以指定多次。

这也可以与 build.target config value 一起使用。

注意,指定这个标志会使 Cargo 在不同的模式下运行,目标 artifacts 被放在一个单独的目录中。 更多细节请参见 build cache 文档。

-r
--release
release 配置为优化的 artifacts 生成文档。 请参阅 --profile 选项,通过名称选择一个特定的配置。
--profile name
用给定的配置生成文档。 更多关于配置的细节请查看 参考
--ignore-rust-version
即使选择的 Rust 编译器比项目的 rust-version 字段中配置的所需的Rust版本要低,也要生成文但。
--timings=fmts
O输出每次编译所需时间的信息,并跟踪一段时间的并发信息。 接受一个可选的逗号分隔的输出格式列表; 没有参数的 --timings 将默认为 --timings=html 。 指定一个输出格式(而不是默认的)是不稳定的,需要 -Zunstable-options 。 有效的输出格式:

  • html (不稳定,需要 -Zunstable-options): 在 target/cargo-timings 目录下写一个方便阅读的文件 cargo-timing.html ,并附上编译报告 。 如果你想查看更早的运行情况,也可以在同一目录下写一份文件名中带有时间戳报告。 HTML输出只适合用户使用,并不提供机器可读的计时数据。
  • json (不稳定,需要 -Zunstable-options): 发出机器可读的JSON格式的计时信息。

输出选项

--target-dir directory
所有生成的 artifacts 和中间文件的目录。 也可以与 CARGO_TARGET_DIR 环境变量或 build.target-dir 配置项 一起指定。 默认是工作空间中 target 的根目录。

显示选项

-v
--verbose
使用 verbose 级别输出详细信息。 指定两次此选项来输出 "十分详细" 的输出信息, 这会包含额外的输出信息,比如依赖警告和构建脚本输出。 也可以与 term.verbose config value 一起使用。
-q
--quiet
不要打印任何 cargo 日志信息。 也可以与 term.quiet config value 一起使用。
--color when
控制的日志的颜色。 有效的值如下:

  • auto (默认): 自动检测终端颜色支持是否可用。
  • always: 总是带颜色显示。
  • never: 不带颜色显示.

也可以与 term.color config value 一起使用。

--message-format fmt
诊断信息的输出格式。可以多次指定,由逗号分隔的数值组成。有效值:

  • human (默认): 以人类可读的文本格式显示。与 shortjson冲突。
  • short: 生成更短的、人类可读的文本信息。 与humanjson 冲突。
  • json: 生成 JSON 信息输出到 stdout. 更多细节请参见 the reference。 与 humanshort冲突。
  • json-diagnostic-short: 确保 JSON 信息的 rendered 包含来自 rustc 的 "short" 渲染。 不能与 humanshort 一起使用。
  • json-diagnostic-rendered-ansi: 确保 JSON 信息的 rendered 包含 嵌入式ANSI颜色代码来兼容 rustc 的默认颜色方案。 不能与 humanshort 一起使用。
  • json-render-diagnostics: 指示 Cargo 在打印的JSON信息中不包含 rustc 的诊断信息, 而是由 Cargo 自己来渲染来自 rustc 的 JSON 诊断信息。 Cargo 自己的 JSON 诊断程序和其他来自 rustc 的诊断程序仍然会被生成出来。 不能与 humanshort 一起使用。

清单选项

--manifest-path path
Cargo.toml 文件的路径. 默认情况下,Cargo 会在当前目录或任何父目录下搜索 Cargo.toml 文件。
--frozen
--locked
这两个标志都要求 Cargo.lock 文件是最新的。 如果 .lock 文件缺失,或者需要更新,Cargo 将以错误退出。 --frozen 标志也可以防止 Cargo 访问网络以确定其是否过期。

这些可以用于需要判断 Cargo.lock 文件是否最新(比如CI构建)或者想避免网络访问的环境中。

--offline
禁止 Cargo 在任何情况下访问网络。 如果没有这个标志,当 Cargo 需要访问网络而网络不可用时,它会以错误的方式停止。 有了这个标志,Cargo会尝试在没有网络的情况下进行。

请注意,这可能会导致与在线模式不同的依赖方案。Cargo 会将自己限制在本地的 crate 仓库上, 即使在本地拷贝的索引中可能有更新的版本也是如此。 参见 cargo-fetch(1) 命令来在离线前下载依赖关系。

也可以用 net.offline config value 来指定。

通用选项

+toolchain
如果 Cargo 已经和 rustup 一起安装, 并且 cargo 的第一个参数以 + 开头, 它将被解释为一个rustup工具链的名字 (比如 +stable 或者 +nightly)。 更多关于工具链覆盖工作的信息,请参见 rustup documentation
--config KEY=VALUE or PATH
覆盖一个 Cargo 配置值。参数应该使用 TOML 的 KEY=VALUE 语法,或者提供一个额外配置文件的路径。 这个标志可以被多次指定。更多信息请参见 command-line overrides section
-h
--help
打印帮助信息。
-Z flag
Cargo 的不稳定 (仅限 nightly 版本) 标志。 更多信息请运行 cargo -Z help

其他选项

-j N
--jobs N
要运行的并行作业的数量。 也可以通过 build.jobs config value 配置值来指定。 默认为逻辑CPU的数量。如果是负数,它将最大的并行作业数量设置为逻辑CPU的数量加上所提供的值。不应该是0。
--keep-going
尽可能多地构建依赖关系图中的 crates, 而不是有一个 crate 构建失败则中止构建。 不稳定,需要 -Zunstable-options

环境

更多关于 Cargo 读取的环境变量信息,请参见the reference

退出状态

  • 0: Cargo 成功退出.
  • 101: Cargo 错误退出.

示例

  1. 使用指定文件中的自定义 CSS 生成文档:

    cargo rustdoc --lib -- --extend-css extra.css
    

另请参见

cargo(1), cargo-doc(1), rustdoc(1)

cargo-test(1)

定义

cargo-test - 对包执行单元测试和集成测试

概要

cargo test [options] [testname] [-- test-options]

说明

编译并执行单元测试、集成测试以及文档测试。

测试会过滤参数 TESTNAME 和所有两个破折号(--)开头的参数, 并将它们被传递给测试二进制文件,进而传递给 libtest(rustc 的内置单元测试和宏基准框架)。 如果你同时向Cargo和二进制文件传递参数,那么 -- 后面的参数会传给二进制文件,前面的参数会传给 Cargo。 关于 libtest 参数的细节,请参见 cargo test --help 的输出,并查看 the rustc book 中关于测试如何工作的章节 https://doc.rust-lang.org/rustc/tests/index.html

下面这个例子,将过滤名称中含有foo的测试,并在3个线程中并行运行:

cargo test foo -- --test-threads 3

测试是用 rustc--test 选项建立的,它通过将你的代码与 libtest 链接来创建一个特殊的可执行文件。 这个可执行文件会自动在多个线程中运行所有带有 #[test] 属性注释的函数。 #[bench] 注释的函数也将被运行一次,以验证它们是否正常。

如果软件包包含多个测试目标,每个目标都会像前面提到的那样编译成一个特殊的可执行文件,然后被串行地运行。

可以在目标清单设置中设置 harness = false 来禁用 libtest harness , 在这种情况下,你的代码需要提供自己的 main 函数来处理运行测试。

文档测试

文档测试也是默认运行的,这是由 rustdoc 处理的。 它从库目标的文档注释中提取代码样本,然后执行它们。

与普通的测试目标不同,每个代码块都通过 rustc 编译成一个 doctest 可执行文件。 这些可执行文件在不同的进程中并行运行。 代码块的编译实际上是由 libtest 控制的测试功能的一部分,所以一些选项如 --job 可能不会生效。 请注意,doctests 的这种执行模式是不被保证的,将来可能会发生变化;谨慎依赖它。

关于编写文档测试的更多信息,请参见 rustdoc book

选项

测试选项

--no-run
编译,但不运行测试。
--no-fail-fast
运行所有的测试,无论是否失败。 如果没有这个标志,Cargo 会在第一个可执行程序失败后退出。 Rust test harness 会运行可执行文件中的所有测试, 这个标志只适用于整个可执行文件。

选择包

默认情况下,当没有给出包选择选项时,选择的软件包取决于所选的清单文件 (如果没有给出 --manifest-path ,则基于当前工作目录)。 如果清单在工作空间的根目录,那么将选择工作空间的默认成员,否则将只选择清单定义的包。

工作空间的默认成员可通过根清单中的 workspace.default-members 键显式设置。 如果没有设置,虚拟工作空间将包括所有工作空间成员(相当于通过 --workspace),而非虚拟工作区将只包括根 crate 本身。

-p spec...
--package spec...
只测试指定的软件包。 关于SPEC的格式,见cargo-pkgid(1)。 这个标志可以指定多次,并支持常见的 Unix glob pattern,比如 *, ?[]。 然而,为了避免你的 shell 在 Cargo 处理 glob pattern 之前意外地扩展它们,你必须在每个 pattern 周围使用单引号或双引号。
--workspace
测试工作空间中的所有成员。
--all
--workspace的别名,已弃用。
--exclude SPEC...
排除指定的包。 必须与--workspace标志一起使用。 这个标志可以被多次指定,并且支持常见的 Unix glob pattern,比如 *, ?[]。 然而,为了避免你的 shell 在 Cargo 处理 glob pattern 之前意外地扩展它们,你必须在每个 pattern 周围使用单引号或双引号。

选择目标

当没有给出目标选择选项时, cargo test 将构建所选软件包的以下目标。

  • lib - 用于与二进制文件、示例、集成测试和文档测试链接
  • bins (只有在集成测试已经建立并且所需 feature 可用的情况下)
  • examples - 确保它们能编译
  • lib 作为一个单元测试
  • bins 作为单元测试
  • integration tests 集成测试
  • doc tests 对于类库构建目标的文档测试

可以通过在清单设置中为目标设置 test 标志来改变默认行为。 将 examples 设置为 test = true 会将 examples 作为测试来构建和运行。 将目标设置为 test = false 默认不会对其进行测试。 根据目标名称选择目标的选项会忽略 test 标志,并总是测试给定的目标。

可以通过在清单中为类库设置 doctest = false 来禁用类库的文档测试。

如果选择测试集成测试或基准测试,则自动构建二进制目标。 这样集成测试可以执行二进制文件来测试其行为。 环境变量 CARGO_BIN_EXE_<name> environment variable 在集成测试构建时被设置,以便它能使用 env macro 来定位可执行文件。

传递目标选择标志将只测试指定的目标。

注意 --bin, --example, --test--bench 标志也支持常见的 Unix glob pattern,如 *, ?[] 。 然而,为了避免你的 shell 在 Cargo 处理 glob pattern 之前意外地扩展它们,你必须在每个 glob pattern 周围使用单引号或双引号。

--lib
测试包的类库。
--bin name...
测试指定的二进制文件。这个标志可以被多次指定,并且支持常见的 Unix glob pattern 。
--bins
测试所有二进制目标。
--example name...
测试指定的例子。这个标志可以被多次指定,并且支持常见的 Unix glob pattern 。
--examples
测试所有的例子目标。
--test name...
测试指定的集成测试。这个标志可以被多次指定,并且支持常见的 Unix glob pattern 。
--tests
在测试模式下测试所有在清单中设置了 test = true 标志的目标。 默认情况下,这包括作为单元测试与集成测试构建的库和二进制文件。 请注意,这也会构建任何所需的依赖项,因此 lib 目标可能会被构建两次(一次作为单元测试,另一次作为二进制文件、集成测试等的依赖项)。 通过在目标的清单设置中设置 test 标志,可以启用或禁用目标。
--bench name...
测试指定的基准测试。这个标志可以被多次指定,并且支持常见的 Unix glob pattern 。
--benches
在基准测试模式下测试所有设置了 bench = true 清单标志的目标。 默认情况下,这包括作为基准测试构建的库和二进制文件,以及基准测试目标。 请注意,这也会构建任何所需的依赖项,因此lib目标可能会被构建两次(一次是作为基准,一次是作为二进制文件、基准测试等的依赖项)。 通过在目标的清单设置中设置 bench 标志,可以启用或禁用目标。
--all-targets
测试所有目标。 相当于指定 --lib --bins --tests --benches --examples.
--doc
只测试库的文档。这不能与其他目标选项混合使用。

选择 Feature

feature 标志允许你控制哪些功能被启用。当没有给出特性选项时,每个选定的包都会激活 default 的 feature 。

更多细节请参见the features documentation

-F features
--features features
要激活的 feature 用空格或逗号分隔的列表指定。工作空间成员的 feature 可以用 package-name/feature-name 的语法来启用。 这个标志可以被多次指定,这样可以启用所有指定的特性。
--all-features
激活所有选定包的所有可用 feature 。
--no-default-features
不激活所选包的 default 特性。

编译选项

--target triple
指定架构的测试。 默认为宿主机的架构。三元组的通用格式为 <arch><sub>-<vendor>-<sys>-<abi>。运行 rustc --print target-list 来获取支持的目标列表。 这个标志可以指定多次。

这也可以与 build.target config value 一起使用。

注意,指定这个标志会使 Cargo 在不同的模式下运行,目标 artifacts 被放在一个单独的目录中。 更多细节请参见 build cache 文档。

-r
--release
release 配置文件测试优化的 artifacts 。 请参阅 --profile 选项,通过名称选择一个特定的配置文件。
--profile name
用给定的配置文件进行测试。 关于配置文件的更多细节,请参见 the reference
--ignore-rust-version
即使选择的 Rust 编译器比项目的 rust-version 字段中配置的所需的Rust版本要低,也要测试目标。
--timings=fmts
输出每次编译所需时间的信息,并跟踪一段时间的并发信息。 接受一个可选的逗号分隔的输出格式列表; 没有参数的 --timings 将默认为 --timings=html 。 指定一个输出格式(而不是默认的)是不稳定的,需要 -Zunstable-options 。 有效的输出格式:

  • html (不稳定,需要 -Zunstable-options): 在 target/cargo-timings 目录下写一个方便阅读的文件 cargo-timing.html ,并附上编译报告 。 如果你想查看更早的运行情况,也可以在同一目录下写一份文件名中带有时间戳报告。 HTML输出只适合用户使用,并不提供机器可读的计时数据。
  • json (不稳定,需要 -Zunstable-options): 发出机器可读的JSON格式的计时信息。

输出选项

--target-dir directory
所有生成的 artifacts 和中间文件的目录。 也可以用 CARGO_TARGET_DIR 环境变量或 build.target-dir config value 来指定。 默认为工作空间根目录下的 target

显示选项

默认情况下,Rust test harness 会隐藏测试执行的输出,以保持结果的可读性。 测试输出可以通过向测试二进制文件传递 --nocapture 来恢复(例如,用于调试):

cargo test -- --nocapture
-v
--verbose
使用 verbose 级别输出详细信息。 指定两次此选项来输出 "十分详细" 的输出信息, 这会包含额外的输出信息,比如依赖警告和构建脚本输出。 也可以与 term.verbose config value 一起使用。
-q
--quiet
不要打印任何 cargo 日志信息。 也可以与 term.quiet config value 一起使用。
--color when
控制的日志的颜色。 有效的值如下:

  • auto (默认): 自动检测终端颜色支持是否可用。
  • always: 总是带颜色显示。
  • never: 不带颜色显示.

也可以与 term.color config value 一起使用。

--message-format fmt
诊断信息的输出格式。可以多次指定,由逗号分隔的数值组成。有效值:

  • human (默认): 以人类可读的文本格式显示。与 shortjson冲突。
  • short: 生成更短的、人类可读的文本信息。 与humanjson 冲突。
  • json: 生成 JSON 信息输出到 stdout. 更多细节请参见 the reference。 与 humanshort冲突。
  • json-diagnostic-short: 确保 JSON 信息的 rendered 包含来自 rustc 的 "short" 渲染。 不能与 humanshort 一起使用。
  • json-diagnostic-rendered-ansi: 确保 JSON 信息的 rendered 包含 嵌入式ANSI颜色代码来兼容 rustc 的默认颜色方案。 不能与 humanshort 一起使用。
  • json-render-diagnostics: 指示 Cargo 在打印的JSON信息中不包含 rustc 的诊断信息, 而是由 Cargo 自己来渲染来自 rustc 的 JSON 诊断信息。 Cargo 自己的 JSON 诊断程序和其他来自 rustc 的诊断程序仍然会被生成出来。 不能与 humanshort 一起使用。

清单选项

--manifest-path path
Cargo.toml 文件的路径. 默认情况下,Cargo 会在当前目录或任何父目录下搜索 Cargo.toml 文件。
--frozen
--locked
这两个标志都要求 Cargo.lock 文件是最新的。 如果 .lock 文件缺失,或者需要更新,Cargo 将以错误退出。 --frozen 标志也可以防止 Cargo 访问网络以确定其是否过期。

这些可以用于需要判断 Cargo.lock 文件是否最新(比如CI构建)或者想避免网络访问的环境中。

--offline
禁止 Cargo 在任何情况下访问网络。 如果没有这个标志,当 Cargo 需要访问网络而网络不可用时,它会以错误的方式停止。 有了这个标志,Cargo会尝试在没有网络的情况下进行。

请注意,这可能会导致与在线模式不同的依赖方案。Cargo 会将自己限制在本地的 crate 仓库上, 即使在本地拷贝的索引中可能有更新的版本也是如此。 参见 cargo-fetch(1) 命令来在离线前下载依赖关系。

也可以用 net.offline config value 来指定。

通用选项

+toolchain
如果 Cargo 已经和 rustup 一起安装, 并且 cargo 的第一个参数以 + 开头, 它将被解释为一个rustup工具链的名字 (比如 +stable 或者 +nightly)。 更多关于工具链覆盖工作的信息,请参见 rustup documentation
--config KEY=VALUE or PATH
覆盖一个 Cargo 配置值。参数应该使用 TOML 的 KEY=VALUE 语法,或者提供一个额外配置文件的路径。 这个标志可以被多次指定。更多信息请参见 command-line overrides section
-h
--help
打印帮助信息。
-Z flag
Cargo 的不稳定 (仅限 nightly 版本) 标志。 更多信息请运行 cargo -Z help

其他选项

--jobs 参数会影响测试可执行文件的构建,但不影响运行测试时使用多少个线程。 Rust test harness 包括一个选项来控制使用的线程数:

cargo test -j 2 -- --test-threads=2
-j N
--jobs N
要运行的并行作业的数量。 也可以通过 build.jobs config value 配置值来指定。 默认为逻辑CPU的数量。如果是负数,它将最大的并行作业数量设置为逻辑CPU的数量加上所提供的值。不应该是0。
--keep-going
尽可能多地构建依赖关系图中的 crates, 而不是有一个 crate 构建失败则中止构建。 不稳定,需要 -Zunstable-options
--future-incompat-report
展示一个未来兼容性报告(future-incompat report),显示在执行此命令过程中产生的任何未来不兼容(future-incompatible)的警告

请参阅 cargo-report(1)

环境

更多关于 Cargo 读取的环境变量信息,请参见the reference

退出状态

  • 0: Cargo 成功退出.
  • 101: Cargo 错误退出.

示例

  1. 执行当前包的所有单元和集成测试:

    cargo test
    
  2. 只运行名称与过滤字符串匹配的测试:

    cargo test name_filter
    
  3. 在一个特定的集成测试中只运行一个特定的测试:

    cargo test --test int_test_name -- modname::test_name
    

另请参见

cargo(1), cargo-bench(1), types of tests, how to write tests

cargo-report(1)

定义

cargo-report - 生成并显示各类报告

概要

cargo report type [options]

说明

显示给定 type 报告 - 目前,仅支持 future-incompat

选项

--id id
显示具有指定的Cargo生成的ID的报告
-p spec...
--package spec...
仅显示指定包的报告

示例

  1. 显示最新的future-incompat报告:

    cargo report future-incompat
    
  2. 显示特定包的最新future-incompat报告:

    cargo report future-incompat --package my-dep:0.0.1
    

参阅

Future incompat report

cargo(1)

配置命令

cargo-add(1)

名称

cargo-add -向Cargo.toml清单文件添加依赖项

摘要

cargo add [options] crate...
cargo add [options] --path path
cargo add [options] --git url [crate...]

描述

此命令可以添加或修改依赖关系。

依赖项的源可以通过以下内容指定:

  • crate@version: 以"version"的约束从注册中心取(包)
  • --path path: 从指定的 path 取(包)
  • --git url: 从给定 url 的git仓库拉取

如果没有指定源,那么尽最大努力选择一个,包括:

  • 其他表中存在的依赖 (例如 dev-dependencies)
  • 工作空间成员
  • 注册中心中的最新发行版

当您添加一个已经存在的包时,将使用指定的标志更新现有条目。

一旦成功调用,指定的依赖中的启用的 (+) 和 禁用的 (-) 特性 将在命令输出中被列出

选项

源选项

--git url
从Git URL添加指定的crate
--branch branch
从git添加时使用的分支。
--tag tag
从git添加时使用的标签。
--rev sha
从git添加时使用的特定提交
--path path
要添加的本地crate的文件系统路径
--registry registry
注册中心所使用的名称。注册中心名称被定义在Cargo配置文件中。如果未指定将会使用默认注册中心,该注册中心由registry.default配置项定义,默认为crates-io

部分选项

--dev
作为开发依赖添加。
--build
作为构建依赖添加。
--target target
作为给定目标平台的依赖添加。

依赖选项

--dry-run
不真的写入清单
--rename name
重命名依赖项。
--optional
标记依赖为可选的
--no-optional
标记依赖为必需的
--no-default-features
禁用默认特性
--default-features
重新启用默认特性
--features features
要激活的以逗号或空格分隔的特性。添加多个crate时,特定板条箱的功能可通过包名称/功能名称语法启用。可以多次指定该标志,从而启用所有指定的功能。

显示选项

-v
--verbose
使用详细输出。对于包括额外输出(如依赖关系警告和构建脚本输出)的“非常详细”输出,可以指定两次。也可以用term.verbose配置指定。
-q
--quiet
不要打印cargo日志信息。也可以用term.quiet配置
--color when
控制何时使用彩色输出。有效值:

  • auto (默认):自动检测终端是否支持颜色。
  • always: 总是显示颜色
  • never: 从不显示颜色

也可以用term.quiet配置

清单选项

--manifest-path path
Cargo.toml文件的路径。默认情况下,Cargo在当前目录或任何父目录中搜索Cargo.toml文件。
-p spec
--package spec
仅向指定的包添加依赖项。
--frozen
--locked
这两个标志都要求Cargo.lock文件是最新的。如果lock文件丢失,或者需要更新,Cargo将出错退出。--frozen标志还防止cargo试图访问网络来确定它是否过期。 在您希望断言Cargo.lock文件是最新的(例如CI构建)或希望避免网络访问的环境中,可以使用这些文件。
--offline
防止 Cargo 以任何理由访问网络。如果没有这个标志,当 Cargo 需要访问网络而网络不可用时,Cargo 将出错停止。有了这个标志,如果可能的话,Cargo 将试图在没有网络的情况下前进。

请注意,这可能会导致与在线模式不同的依赖关系解析。Cargo 将自己限制在本地下载的 crate 中,即使在索引的本地副本中可能有更新的版本。请参阅 cargo-fetch(1) 命令,以便在脱机之前下载依赖项。

也可以用 net.offline 配置

Common Options

+toolchain
如果cargo已经安装了rustup,并且 cargo 的第一个参数以 cargo 开头,它将被解释为 rustup 工具链名称(例如 +stable+nightly )。有关工具链覆盖如何工作的更多信息,请参见 rustup 文档
--config KEY=VALUE or PATH
覆盖 Cargo 配置值。该参数应该采用 KEY=VALUE 的 TOML 语法,或者作为额外配置文件的路径提供。可以多次指定该标志。有关更多信息,请参见 命令行覆盖部分
-h
--help
打印帮助信息。
-Z flag
Cargo 的不稳定 (nightly-only) 标志。运行 cargo -Z help 获取详细信息。

环境

有关Cargo读取的环境变量的详细信息,请参见 the reference

退出状态

  • 0: Cargo 成功.
  • 101: Cargo 未能完成.

示例

  1. 添加 regex 作为依赖项

    cargo add regex
    
  2. 添加 trybuild 作为开发依赖项

    cargo add --dev trybuild
    
  3. 添加旧版本的 nom 作为依赖项

    cargo add nom@5
    
  4. 添加对使用 derive 将数据结构序列化到json的支持

    cargo add serde serde_json -F serde/derive
    

另见

cargo(1), cargo-remove(1)

cargo-generate-lockfile(1)

名称

cargo-generate-lockfile - 为一个包生成 lockfile

概要

cargo generate-lockfile [options]

描述

这个命令会为当前的包 (package) 或工作空间 (workspace) 生成 Cargo.lock。如果 lockfile 已经存在,则会用各包的最新可用版本重新生成 Cargo.lock

另见 cargo-update(1) ,其也可以生成 Cargo.lock ,而且有更多针对更新策略的设置选项。

选项

显示选项

-v
--verbose
进行 verbose 输出。可以指定两遍来开启 "very verbose" 模式,输出更多的额外信息,像是依赖项的警告和构建脚本的输出信息。 也可以通过 term.verbose 配置选项 来指定。
-q
--quiet
不打印 cargo log 信息。 也可以通过 term.quiet 配置选项来指定。
--color when
控制*何时*使用彩色输出。可选值有:

  • auto (默认值): 自动检测终端是否支持彩色输出。
  • always: 总是显示彩色。
  • never: 从不显示彩色。

也可以在 term.color 配置选项中设置。

清单选项

--manifest-path path
Cargo.toml 文件的路径。默认情况下,Cargo 会从当前目录或任意的上级目录搜索 Cargo.toml
--frozen
--locked
这两个 flag 都需要 Cargo.lock 文件处于无需更新的状态。如果 lock 文件缺失,或者需要被更新,Cargo 会报错退出。 --frozen flag 还会阻止 Cargo 访问网络来判断 Cargo.lock 是否过期。

这些 flag 可以用于某些场景下你想断言 Cargo.lock 无需更新 (比如在CI中构建) 或者避免网络访问。

--offline
阻止 Cargo 访问网络。如果没有这个 flag,当 Cargo 需要访问网络但是没有网络时,就会报错退出。加上这个 flag,Cargo 会尝试在不联网的情况下继续执行 (如果可以的话) 。

要小心这会导致与在线模式不同的解析结果。Cargo 会限制自己在本地已下载的 crate 中查找版本,即使在本地的 index 拷贝中表明还有更新的版本。 cargo-fetch(1) 命令可以在进入离线模式前下载依赖。

同样的功能也可以通过设置 net.offline 配置选项来实现。

通用选项

+toolchain
如果 Cargo 由 rustup 安装,那么 cargo 后第一个以 + 开头的参数会被认为是 rustup toolchain 名字(例如 +stable+nightly)。 查看 rustup documentation 了解 toolchain overrides 如何工作。
--config KEY=VALUE or PATH
覆盖一个 Cargo 配置的值。参数应该是一个 TOML 语法的 KEY=VALUE,或者提供一个路径来指向一个额外的配置文件 (configuration file)。 这个标记可以指定多次。 参考 command-line overrides 一节 获取更多信息。
-h
--help
打印帮助信息。
-Z flag
不稳定 (nightly-only) 的标志。 执行 cargo -Z help 获取详细信息。

环境

查看 the reference 获取 Cargo 读取的环境变量的更多信息。

退出状态

  • 0: Cargo 执行成功。
  • 101: Cargo 没有执行完成。

使用案例

  1. 创建或更新当前包 (package) 或工作空间 (workspace) 的 lockfile:

    cargo generate-lockfile
    

其他参考

cargo(1), cargo-update(1)

cargo-locate-project(1)

名称

cargo-locate-project - 以 JSON 格式打印 Cargo.toml 文件的位置

概要

cargo locate-project [options]

描述

这个命令会在 stdout 中以 JSON 格式打印清单文件的绝对地址。命令会从当前工作目录出发向上搜索 Cargo.toml 文件。

如果这个项目在一个工作空间 (workspace) 中,会打印该项目而不是工作空间的清单文件。这个行为可以通过 --workspace 标志来改变。工作空间根目录的查找是通过不断向上搜索或者从成员的清单文件中的 package.workspace 字段来得到。

选项

--workspace
定位 Cargo.toml workspace 根目录的位置,而不是当前的 workspace 成员.

显示选项

--message-format fmt
打印项目位置的格式。可选值有:

  • json (默认值): 带着 "root" 字段的 JSON 对象。
  • plain: 仅路径字符串。
-v
--verbose
进行 verbose 输出。可以指定两遍来开启 "very verbose" 模式,输出更多的额外信息,像是依赖项的警告和构建脚本的输出信息。 也可以通过 term.verbose 配置选项 来指定。
-q
--quiet
不打印 cargo log 信息。 也可以通过 term.quiet 配置选项来指定。
--color when
控制*何时*使用彩色输出。可选值有:

  • auto (默认值): 自动检测终端是否支持彩色输出。
  • always: 总是显示彩色。
  • never: 从不显示彩色。

也可以在 term.color 配置选项中设置。

清单选项

--manifest-path path
Cargo.toml 文件的路径。默认情况下,Cargo 会从当前目录或任意的上级目录搜索 Cargo.toml

通用选项

+toolchain
如果 Cargo 由 rustup 安装,那么 cargo 后第一个以 + 开头的参数会被认为是 rustup toolchain 名字(例如 +stable+nightly)。 查看 rustup documentation 了解 toolchain overrides 如何工作。
--config KEY=VALUE or PATH
覆盖一个 Cargo 配置的值。参数应该是一个 TOML 语法的 KEY=VALUE,或者提供一个路径来指向一个额外的配置文件 (configuration file)。 这个标记可以指定多次。 参考 command-line overrides 一节 获取更多信息。
-h
--help
打印帮助信息。
-Z flag
不稳定 (nightly-only) 的标志。 执行 cargo -Z help 获取详细信息。

环境

查看 the reference 获取 Cargo 读取的环境变量的更多信息。

退出状态

  • 0: Cargo 执行成功。
  • 101: Cargo 没有执行完成。

使用案例

  1. 基于当前路径,显示清单文件(manifest)的路径。

    cargo locate-project
    

其他参考

cargo(1), cargo-metadata(1)

cargo-metadata(1)

名称

cargo-metadata - 输出当前包的机器可读的元数据

概要

cargo metadata [options]

描述

在 stdout 中输出工作空间成员的信息和当前包已解析的依赖。

建议在使用时添加 --format-version 标志以保证未来也会以你预期的格式进行输出。

另见 cargo_metadata crate 查看读取该元数据的 Rust API。

输出格式

输出格式如下:

{
    /* 工作空间中的所有包
       其中也包括了所有被 feature 所启用的依赖,除非设置了 --no-deps 标志。
    */
    "packages": [
        {
            /* 包的名称 */
            "name": "my-package",
            /* 包的版本 */
            "version": "0.1.0",
            /* Package ID,引用一个包的唯一标识符。 */
            "id": "my-package 0.1.0 (path+file:///path/to/my-package)",
            /* 来自清单文件中的 license 值,或为 null */
            "license": "MIT/Apache-2.0",
            /* 来自清单文件中的 license-file 值,或为 null */
            "license_file": "LICENSE",
            /* 来自清单文件中的 description 值 ,或为 null */
            "description": "Package description.",
            /* 包的 source ID ,其表示一个包是从何处获取的。
               对于 path 类型的依赖或者工作空间成员,该值为 null。
               对于其他依赖,该值为一个字符串,其格式为:
               - 对于 registry-based 的依赖,为 "registry+URL"。
                 例如: "registry+https://github.com/rust-lang/crates.io-index"
               - 对于 git-based 的依赖,为 "git+URL"。
                 例如: "git+https://github.com/rust-lang/cargo?rev=5e85ba14aaa20f8133863373404cb0af69eeef2c#5e85ba14aaa20f8133863373404cb0af69eeef2c"
            */
            "source": null,
            /* 该包的清单文件中声明的所有依赖 */
            "dependencies": [
                {
                    /* 依赖的名称 */
                    "name": "bitflags",
                    /* 依赖的 source ID,可能为 null,见 package source 的描述。
                    */
                    "source": "registry+https://github.com/rust-lang/crates.io-index",
                    /* The version requirement for the dependency.
                       Dependencies without a version requirement have a value of "*".
                    */
                    /* 对于该依赖的版本请求。没有版本请求的依赖以"*"为值 */
                    "req": "^1.0",
                    /* 依赖的种类。
                       有 "dev", "build",对于普通依赖来说为 null。
                    */
                    "kind": null,
                    /* 如果依赖被重命名,该值为新名,没有重命名则为 null。
                    */
                    "rename": null,
                    /* 布尔值,表示该依赖是否是可选的。 */
                    "optional": false,
                    /* 布尔值,表示该依赖是否启用了 default feature。 */
                    "uses_default_features": true,
                    /* 所有启用的 feature。 */
                    "features": [],
                    /* 该依赖的目标平台,如果不是一个平台特定依赖,则值为 null。
                    */
                    "target": "cfg(windows)",
                    /* 本地依赖(path dependency)在文件系统中的路径,如果不是本地依赖,该字段不会出现。
                    */
                    "path": "/path/to/dep",
                    /* 依赖来自的 registry 的 URL 字符串。如果没有指定或者值为 null,则该依赖来自默认的 registry (crates.io)
                    */
                    "registry": null
                }
            ],
            /* Cargo targets. */
            "targets": [
                {
                    /* target 的种类。
                       - lib targets 会陈列清单文件中的 `crate-type` 值
                         比如 "lib", "rlib", "dylib", "proc-macro"。 (默认值为 ["lib"])
                       - 二进制目标为 ["bin"]
                       - example 为 ["example"]
                       - 集成测试为 ["test"]
                       - benchmark 为 ["bench"]
                       - build script 为 ["custom-build"]
                    */
                    "kind": [
                        "bin"
                    ],
                    /* crate 的种类。
                       - lib 和 example库 会陈列清单文件中的 `crate-type` 值
                         比如 "lib", "rlib", "dylib", "proc-macro"。 (默认值为 ["lib"])
                       - 其他 target 类都为 ["bin"]
                    */
                    "crate_types": [
                        "bin"
                    ],
                    /* target 的名称 */
                    "name": "my-package",
                    /* 目标的*根*源文件的绝对路径。 */
                    "src_path": "/path/to/my-package/src/main.rs",
                    /* target 的 Rust 版本。
                       默认为 package 标注的 Rust 版本。 
                    */
                    "edition": "2018",
                    /* 启用的 feature。
                       如果没有设置 feature,则该字段不存在。
                    */
                    "required-features": ["feat1"],
                    /* 该目标是否应该使用  `cargo doc` 生成文档。 */
                    "doc": true,
                    /* 该目标是否启用文档测试,且该目标是否与文档测试兼容。
                    */
                    "doctest": false,
                    /* 该目标在运行或构建时是否设置 `--test`。
                    */
                    "test": true
                }
            ],
            /* 包中定义的 feature,每一项 feature 启用一系列 feature 或者依赖项。
            */
            "features": {
                "default": [
                    "feat1"
                ],
                "feat1": [],
                "feat2": []
            },
            /* 该包的清单文件的绝对路径 */
            "manifest_path": "/path/to/my-package/Cargo.toml",
            /* 包的元数据。
               若没有指定元数据,该项为 null。
            */
            "metadata": {
                "docs": {
                    "rs": {
                        "all-features": true
                    }
                }
            },
            /* 该包可能发布的 registry 列表。List of registries to which this package may be published.
               若为 null 则发布不受限制,若为空数组,则禁止发布。 */
            "publish": [
                "crates-io"
            ],
            /* 清单文件中的 authors。
               如果没有指定 authors,则该值为空数组。
            */
            "authors": [
                "Jane Doe <user@example.com>"
            ],
            /* 清单文件中的 categories。 */
            "categories": [
                "command-line-utilities"
            ],
            /* 可选字符串。指定 cargo run 执行的默认二进制crate。 */
            "default_run": null,
            /* 可选字符串。声明支持的最小 rust 版本。 */
            "rust_version": "1.56",
            /* 清单文件中的 keywords。 */
            "keywords": [
                "cli"
            ],
            /* 清单文件中的 readme 值,若没有指定则为 null。 */
            "readme": "README.md",
            /* 清单文件中的 repository 值,若没有指定则为 null。 */
            "repository": "https://github.com/rust-lang/cargo",
            /* 清单文件中的 homepage 值,若没有指定则为 null。 */
            "homepage": "https://rust-lang.org",
            /* 清单文件中的 documentation 值,若没有指定则为 null。 */
            "documentation": "https://doc.rust-lang.org/stable/std",
            /* 该包的默认 rust 版本。
               注意,每个 target 可能有不同的 rust 版本。
            */
            "edition": "2018",
            /* 可选字符串。指示该包链接的本地库的名称。
            */
            "links": null,
        }
    ],
    /* 工作空间的成员。
       每个条目都是一个 Package ID 。
    */
    "workspace_members": [
        "my-package 0.1.0 (path+file:///path/to/my-package)",
    ],
    // 整个工作空间的依赖解析图。启用的 feature 是基于 “当前” 的包所启用的 feature。
    // 未启用的可选依赖没有列入其中。
    //
    // 如果使用了 --no-deps 标志,则该项为 null。
    //
    // 默认情况下,该项会包含面向所有目标平台的所有依赖
    // `--filter-platform` 标志可以用来收窄到特定的目标三元组 (target triple)。
    "resolve": {
        /* 依赖图中节点组成的数组。
           每个节点(node)都是一个包(package)。
        */
        "nodes": [
            {
                /* 节点的 Package ID  */
                "id": "my-package 0.1.0 (path+file:///path/to/my-package)",
                /* 该包的依赖项,一个 Package ID 的数组。 */
                "dependencies": [
                    "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)"
                ],
                /* 该包的依赖项。这是 "dependencies" 的另一种表示,其中包含额外的信息。比如依赖的重命名。
                */
                "deps": [
                    {
                        /* 依赖的库target的名称。The name of the dependency's library target.
                           如果该依赖被重命名,则该name是新名。
                        */
                        "name": "bitflags",
                        /* 依赖的 Package ID  */
                        "pkg": "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
                        /* 依赖种类的数组,在 Cargo 1.40 中加入该项。 */
                        "dep_kinds": [
                            {
                                /* 依赖种类。
                                   "dev", "build", 普通依赖为 null。
                                */
                                "kind": null,
                                /* 依赖的目标平台,非平台特定依赖为 null。
                                */
                                "target": "cfg(windows)"
                            }
                        ]
                    }
                ],
                /* 该包中启用的 feature 。 */
                "features": [
                    "default"
                ]
            }
        ],
        /* 工作空间的 root package 。
           如果是 virtual workspace 此项为 null,其他情况为 root package 的 Package ID 。
        */
        "root": "my-package 0.1.0 (path+file:///path/to/my-package)"
    },
    /* 构建文件夹的绝对路径,Cargo 在此处存放构建输出产物。 */
    "target_directory": "/path/to/my-package/target",
    /* 此元数据的 schema 版本
       如果未来有不兼容的变化,该值会改变。
    */
    "version": 1,
    /* 工作空间根文件夹的绝对路径 */
    "workspace_root": "/path/to/my-package"
    /* 工作空间的元数据Workspace metadata.
       如果没有指定元数据,则该项为 null。 */
    "metadata": {
        "docs": {
            "rs": {
                "all-features": true
            }
        }
    }
}

选项

输出选项

--no-deps
仅输出工作空间成员的信息而不下载依赖
--format-version version
指定输出格式的版本。目前 1 是唯一的合法值。
--filter-platform triple
这会过滤 解析信息 的输出,仅包括对于特定目标 (target triple) 的结果。 如果不加这个标志,解析会包括所有的目标 (targets)。

注意, "packages" 数组仍然会包含所有的依赖。每个 package 的信息是 Cargo.toml 中信息的不做修改的再现。

选择 feature

特性标志允许你控制开启哪些特性。当没有提供特性选项时,会为每个选择的包启用 default 特性。

查看 features 文档 获取更多信息。

-F features
--features features
用空格或逗号来分隔多个启用的 feature。 工作空间成员的 feature 可以通过 package-name/feature-name 语法来启用。 该标志可以设置多次,最终将启用指定的所有 feature 。
--all-features
启用指定包的所有可用 feature。
--no-default-features
不使用指定包的 default feature 。

显示选项

-v
--verbose
进行 verbose 输出。可以指定两遍来开启 "very verbose" 模式,输出更多的额外信息,像是依赖项的警告和构建脚本的输出信息。 也可以通过 term.verbose 配置选项 来指定。
-q
--quiet
不打印 cargo log 信息。 也可以通过 term.quiet 配置选项来指定。
--color when
控制*何时*使用彩色输出。可选值有:

  • auto (默认值): 自动检测终端是否支持彩色输出。
  • always: 总是显示彩色。
  • never: 从不显示彩色。

也可以在 term.color 配置选项中设置。

清单选项

--manifest-path path
Cargo.toml 文件的路径。默认情况下,Cargo 会从当前目录或任意的上级目录搜索 Cargo.toml
--frozen
--locked
这两个 flag 都需要 Cargo.lock 文件处于无需更新的状态。如果 lock 文件缺失,或者需要被更新,Cargo 会报错退出。 --frozen flag 还会阻止 Cargo 访问网络来判断 Cargo.lock 是否过期。

这些 flag 可以用于某些场景下你想断言 Cargo.lock 无需更新 (比如在CI中构建) 或者避免网络访问。

--offline
阻止 Cargo 访问网络。如果没有这个 flag,当 Cargo 需要访问网络但是没有网络时,就会报错退出。加上这个 flag,Cargo 会尝试在不联网的情况下继续执行 (如果可以的话) 。

要小心这会导致与在线模式不同的解析结果。Cargo 会限制自己在本地已下载的 crate 中查找版本,即使在本地的 index 拷贝中表明还有更新的版本。 cargo-fetch(1) 命令可以在进入离线模式前下载依赖。

同样的功能也可以通过设置 net.offline 配置选项来实现。

通用选项

+toolchain
如果 Cargo 由 rustup 安装,那么 cargo 后第一个以 + 开头的参数会被认为是 rustup toolchain 名字(例如 +stable+nightly)。 查看 rustup documentation 了解 toolchain overrides 如何工作。
--config KEY=VALUE or PATH
覆盖一个 Cargo 配置的值。参数应该是一个 TOML 语法的 KEY=VALUE,或者提供一个路径来指向一个额外的配置文件 (configuration file)。 这个标记可以指定多次。 参考 command-line overrides 一节 获取更多信息。
-h
--help
打印帮助信息。
-Z flag
不稳定 (nightly-only) 的标志。 执行 cargo -Z help 获取详细信息。

环境

查看 the reference 获取 Cargo 读取的环境变量的更多信息。

退出状态

  • 0: Cargo 执行成功。
  • 101: Cargo 没有执行完成。

使用案例

  1. 以 JSON 格式输出当前包的信息:

    cargo metadata --format-version=1
    

其他参考

cargo(1)

cargo-pkgid(1)

名称

cargo-pkgid - 打印包的完整标准规格。

概要

cargo pkgid [options] [spec]

描述

提供一个 spec 参数,打印出当前工作空间中的一个包或一个依赖的完整的 package ID 指定符 (specifier)。如果 spec 指定的包在依赖图中不明确 (不存在) ,则会报错。如果没有提供 spec 参数,则会打印本地包 (local package) 的指定符。

该命令要求已存在一个可用的 lockfile,且依赖已经被下载。

一个包指定符由名称、版本和源 URL 组成。你可以使用部分指定符来简洁地指定一个包,只要它正好只匹配一个包。 spec 的格式可以为下面一种:

SPEC StructureExample SPEC
namebitflags
name@versionbitflags@1.0.4
urlhttps://github.com/rust-lang/cargo
url#versionhttps://github.com/rust-lang/cargo#0.33.0
url#namehttps://github.com/rust-lang/crates.io-index#bitflags
url#name:versionhttps://github.com/rust-lang/cargo#crates-io@0.21.0

选项

包的选择

-p spec
--package spec
获取指定包的 package ID ,而不是当前的包。

显示选项

-v
--verbose
进行 verbose 输出。可以指定两遍来开启 "very verbose" 模式,输出更多的额外信息,像是依赖项的警告和构建脚本的输出信息。 也可以通过 term.verbose 配置选项 来指定。
-q
--quiet
不打印 cargo log 信息。 也可以通过 term.quiet 配置选项来指定。
--color when
控制*何时*使用彩色输出。可选值有:

  • auto (默认值): 自动检测终端是否支持彩色输出。
  • always: 总是显示彩色。
  • never: 从不显示彩色。

也可以在 term.color 配置选项中设置。

清单选项

--manifest-path path
Cargo.toml 文件的路径。 默认情况下,Cargo 在当前目录或任意的父目录中查找 Cargo.toml
--frozen
--locked
这两个 flag 都需要 Cargo.lock 文件处于无需更新的状态。如果 lock 文件缺失,或者需要被更新,Cargo 会报错退出。 --frozen flag 还会阻止 Cargo 访问网络来判断 Cargo.lock 是否过期。

这些 flag 可以用于某些场景下你想断言 Cargo.lock 无需更新 (比如在CI中构建) 或者避免网络访问。

--offline
阻止 Cargo 访问网络。如果没有这个 flag,当 Cargo 需要访问网络但是没有网络时,就会报错退出。加上这个 flag,Cargo 会尝试在不联网的情况下继续执行 (如果可以的话) 。

要小心这会导致与在线模式不同的解析结果。Cargo 会限制自己在本地已下载的 crate 中查找版本,即使在本地的 index 拷贝中表明还有更新的版本。 cargo-fetch(1) 命令可以在进入离线模式前下载依赖。

同样的功能也可以通过设置 net.offline 配置选项来实现。

通用选项

+toolchain
如果 Cargo 由 rustup 安装,那么 cargo 后第一个以 + 开头的参数会被认为是 rustup toolchain 名字(例如 +stable+nightly)。 查看 rustup documentation 了解 toolchain overrides 如何工作。
--config KEY=VALUE or PATH
覆盖一个 Cargo 配置的值。参数应该是一个 TOML 语法的 KEY=VALUE,或者提供一个路径来指向一个额外的配置文件 (configuration file)。 这个标记可以指定多次。 参考 command-line overrides 一节 获取更多信息。
-h
--help
打印帮助信息。
-Z flag
不稳定 (nightly-only) 的标志。 执行 cargo -Z help 获取详细信息。

环境

查看 the reference 获取 Cargo 读取的环境变量的更多信息。

退出状态

  • 0: Cargo 执行成功。
  • 101: Cargo 没有执行完成。

使用案例

  1. 获取 foo 的包指定符:

    cargo pkgid foo
    
  2. 获取 1.0.0 版 foo 的包指定符:

    cargo pkgid foo@1.0.0
    
  3. 获取 crates.io 上的 foo 的包指定符:

    cargo pkgid https://github.com/rust-lang/crates.io-index#foo
    
  4. 获取本地 foo 包的包指定符:

    cargo pkgid file:///path/to/local/package#foo
    

其他参考

cargo(1), cargo-generate-lockfile(1), cargo-metadata(1)

cargo-remove(1)

定义

cargo-remove - 移除Cargo.toml配置清单文件中的依赖项

概要

cargo remove [options] dependency...

说明

Cargo.toml 配置清单中移除一个或多个依赖项。

选项

条目选项

--dev
移除 开发依赖
--build
移除 构建依赖
--target target
移除指定目标平台的依赖

其他选项

--dry-run
非实际写入配置清单。

显示选项

-v
--verbose
进行详细输出。可以指定两次来开启 "非常详细" ,输出更多的额外信息,像是依赖项的警告和构建脚本的输出信息。 也可以通过 term.verbose 配置
-q
--quiet
不打印 cargo 日志信息。 也可以用 term.quiet 配置
--color when
使用彩色输出。有效值:

  • auto (默认):自动检测终端是否支持彩色。
  • always: 总是显示彩色。
  • never: 总不显示彩色。

也可以用 term.color 配置

配置选项

--manifest-path path
Cargo.toml 文件的路径。默认, Cargo 在当前目录和任意父目录搜索 Cargo.toml 文件。
--frozen
--locked
这些标志都要求 Cargo.lock 文件是最新的。 如果lock文件丢失, 或是需要更新, Cargo会返回错误并退出,--frozen 选项还会阻止cargo通过网络来判断其是否过期。

可以用于断言 Cargo.lock 文件是否最新状态(例如CI构建)或避免网络访问。

--offline
阻止Cargo访问网络。如果不指定该选项,Cargo会在需要使用网络但不可用时停止构建并返回错误。设置该标识,Cargo将尽可能不使用网络完成构建。

需注意,这样可能会导致与在线模式不同的依赖处理,Cargo将限制仅使用已下载到本地的crate,即使本地索引中有更新版本。 查阅 cargo-fetch(1) 命令,在脱机前下载依赖。

也可以用 net.offline 配置

包的选择

-p spec...
--package spec...
移除包。

常规选项

+toolchain
如果Cargo已经通过rustup安装,并且第一个传给 cargo 的参数以 + 开头, 则当作rustup的工具链名称。(例如 +stable+nightly). 查阅 rustup 文档 了解关于工具链覆盖的信息。
--config KEY=VALUE or PATH
覆盖Cargo配置项的值,该参数应当为TOML KEY=VALUE 语法, 或者提供附加的配置文件的路径。该标识可以多次指定。 查阅 命令行覆盖部分 获取更多信息
-h
--help
打印帮助信息。
-Z flag
Cargo不稳定的(每日构建)标志。运行 cargo -Z help 了解详情。

环境

查阅 参考 了解Cargo读取环境变量。

退出状态

  • 0: Cargo 执行成功。
  • 101: Cargo 没有执行完成。

示例

  1. 移除 regex 依赖

    cargo remove regex
    
  2. 移除 trybuild dev-依赖

    cargo remove --dev trybuild
    
  3. x86_64-pc-windows-gnu 依赖表移除 nom

    cargo remove --target x86_64-pc-windows-gnu nom
    

参阅

cargo(1), cargo-add(1)

cargo-tree(1)

定义

cargo-tree - 用树状结构展示依赖图

概要

cargo tree [options]

说明

这个命令在终端显示一个依赖关系树。 下面是一个依赖 "rand" 包的简单项目的例子

myproject v0.1.0 (/myproject)
└── rand v0.7.3
    ├── getrandom v0.1.14
    │   ├── cfg-if v0.1.10
    │   └── libc v0.2.68
    ├── libc v0.2.68 (*)
    ├── rand_chacha v0.2.2
    │   ├── ppv-lite86 v0.2.6
    │   └── rand_core v0.5.1
    │       └── getrandom v0.1.14 (*)
    └── rand_core v0.5.1 (*)
[build-dependencies]
└── cc v1.0.50

标有 (*) 的包已经被 "去重" 了。 该软件包的依赖关系已经在图中的其他地方显示过了,所以没有重复。 使用 --no-dedupe 选项来展示重复的内容。

-e 标志可以用来选择要显示的依赖关系种类。 "features" 种类可以改变输出结果,以显示每个依赖关系所启用的 feature。 例如 cargo tree -e features :

myproject v0.1.0 (/myproject)
└── log feature "serde"
    └── log v0.4.8
        ├── serde v1.0.106
        └── cfg-if feature "default"
            └── cfg-if v0.1.10

在这棵树上,myproject 依赖于具有 serde 特性的 log , 而 log 又依赖于具有 "default" 特性的 cfg-if 。 当使用 -e feature 时,使用 -i 标志来帮助展示这些特性是如何进入包的。 请看下面的例子以了解更多细节。

特性统一

这个命令显示更接近 Cargo 构建的特性统一(feature-unified)的图形,而不是你在 Cargo.toml 中列出的。 例如,如果你在 [dependencies][dev-dependencies] 中都指定了相同的依赖关系,但却使用了不同的特性。 这个命令可能会合并所有特性,并在其中一个依赖项上显示一个 (*) 来表示重复的特性。

因此,要得到大概相同的对 cargo build 工作的预览,cargo tree -e normal,build 是相当接近的; 要得到大概相同的对 cargo test 工作的预览,cargo tree 是相当接近的。 然而,它并不能保证与 Cargo 要构建的内容完全等同,因为编译是复杂的,取决于很多不同的因素。

要了解更多关于特性统一(feature-unified)的信息,请查看专门的章节

选项

树选项

-i spec
--invert spec
显示指定软件包的反向依赖关系。这个标志将反转树,显示依赖给定包的包。

-p 标志可以用来显示软件包的反向依赖关系,只显示给 -p 的软件包的子树。

注意,在工作空间中,默认情况下,它只显示当前目录下工作空间成员的树中的包的反向依赖关系。 可以使用 --workspace 标志来扩展它,使其在整个工作空间显示软件包的反向依赖关系。

--prune spec
从依赖关系树的显示中删去给定的软件包。
--depth depth
依赖关系树的最大显示深度。例如,深度为1时,显示直接依赖关系。
--no-dedupe
不要删除重复的依赖关系。 通常情况下,当一个包已经显示了它的依赖关系,再次出现将不会重新显示它的依赖关系,并且会包括一个 (*) 来表示它已经被显示了。 这个标志令这些重复的内容显示出来。
-d
--duplicates
只显示有多个版本的依赖关系(意味着 --invert )。当与 -p 标志一起使用时,只显示指定软件包的子树中的重复内容。

这对构建时间和可执行文件的大小有好处,可以避免多次构建同一个软件包。 这个标志可以帮助识别冲突的软件包。然后,你可以查看包是否有相同的依赖但是依赖的版本不一, 将旧版本升级到新版本,这样就可以只构建一个实例。

-e kinds
--edges kinds
要显示的依赖的种类。接受一个逗号分隔的列表:

  • all — 展示所有最新的类型
  • normal — 展示正常依赖
  • build — 展示构建依赖
  • dev — 展示开发依赖
  • features — 显示每个依赖关系所启用的特性。如果这是唯一给出的种类,那么它将自动包括其他依赖关系的种类
  • no-normal — 不要包含正常依赖
  • no-build — 不要包含构建依赖
  • no-dev — 不要包含开发依赖
  • no-proc-macro — 不要包含程序宏依赖

normal, build, dev, and all 依赖种类不能与 no-normal, no-build, or no-dev 依赖种类混用。

默认是normal,build,dev

--target triple
过滤与目标三元组匹配的依赖。默认是宿主机平台。使用 all 来包括 所有 目标。

格式化树选项

--charset charset
选择树使用字符集. 有效的值为: "utf8" 或 "ascii"。 默认为 "utf8"。
-f format
--format format
设置每个包的格式字符串。默认是 "{p}"。

这是一个任意的字符串,它将被用来显示每个包。下列字符串将被替换成相应的值:

  • {p} — 包名
  • {l} — 包证书
  • {r} — 包的仓库地址
  • {f} — 逗号分割的包启用的特性列表
  • {lib} — 在 use 声明中使用的类库的名称
--prefix prefix
设置每行如何展示, 前缀 可以是下面的一种:

  • indent (默认) — 以树的格式缩进展示每一行
  • depth — 以列表形式显示,在每个条目前打印数字来展示深度
  • none — 以平铺的列表的形式展示

选择包

默认情况下,当没有给出包选择选项时,所选包取决于所选清单文件(如果没有给出 --manifest-path ,则基于当前工作目录)。 如果清单是工作空间的根,那么将选择工作空间的默认成员,否则将只选择清单定义的包。

工作空间的默认成员可通过根清单中的 workspace.default-members 键明确设置。 如果没有设置,虚拟工作空间将包括所有工作空间成员(相当于传递 --workspace),而非虚拟工作空间将只包括根 crate 本身。

-p spec...
--package spec...
只展示指定的软件包。 关于SPEC的格式,见cargo-pkgid(1)。 这个标志可以指定多次,并支持常见的 Unix glob pattern,比如 *, ?[]。 然而,为了避免你的 shell 在 Cargo 处理 glob pattern 之前意外地扩展它们,你必须在每个 pattern 周围使用单引号或双引号。
--workspace
展示工作空间中的所有成员。
--exclude SPEC...
排除指定的包。 必须与--workspace标志一起使用。 这个标志可以被多次指定,并且支持常见的 Unix glob pattern,比如 *, ?[]。 然而,为了避免你的 shell 在 Cargo 处理 glob pattern 之前意外地扩展它们,你必须在每个 pattern 周围使用单引号或双引号。

清单选项

--manifest-path path
Cargo.toml 文件的路径. 默认情况下,Cargo 会在当前目录或任何父目录下搜索 Cargo.toml 文件。
--frozen
--locked
这两个标志都要求 Cargo.lock 文件是最新的。 如果 .lock 文件缺失,或者需要更新,Cargo 将以错误退出。 --frozen 标志也可以防止 Cargo 访问网络以确定其是否过期。

这些可以用于需要判断 Cargo.lock 文件是否最新(比如CI构建)或者想避免网络访问的环境中。

--offline
禁止 Cargo 在任何情况下访问网络。 如果没有这个标志,当 Cargo 需要访问网络而网络不可用时,它会以错误的方式停止。 有了这个标志,Cargo会尝试在没有网络的情况下进行。

请注意,这可能会导致与在线模式不同的依赖方案。Cargo 会将自己限制在本地的 crate 仓库上, 即使在本地拷贝的索引中可能有更新的版本也是如此。 参见 cargo-fetch(1) 命令来在离线前下载依赖关系。

也可以用 net.offline config value 来指定。

选择特性

feature 标志允许你控制启用哪些特性。当没有给出特性选项时,每个选定的包都会激活默认的功能。

更多的细节请参见the features documentation

-F features
--features features
要激活的 feature 用空格或逗号分隔的列表指定。工作空间成员的 feature 可以用 package-name/feature-name 的语法来启用。 这个标志可以被多次指定,这样可以启用所有指定的特性。
--all-features
激活所有选定包的所有可用 feature 。
--no-default-features
不激活所选包的 default 特性。

显示选项

-v
--verbose
使用 verbose 级别输出详细信息。 指定两次此选项来输出 "十分详细" 的输出信息, 这会包含额外的输出信息,比如依赖警告和构建脚本输出。 也可以与 term.verbose config value 一起使用。
-q
--quiet
不要打印任何 cargo 日志信息。 也可以与 term.quiet config value 一起使用。
--color when
控制的日志的颜色。有效的值如下:

  • auto (默认): 自动检测终端颜色支持是否可用。
  • always: 总是带颜色显示。
  • never: 不带颜色显示.

也可以与 term.color config value 一起使用。

通用选项

+toolchain
如果 Cargo 已经和 rustup 一起安装, 并且 cargo 的第一个参数以 + 开头, 它将被解释为一个 rustup 工具链的名字 (比如 +stable 或者 +nightly)。 更多关于工具链覆盖工作的信息,请参见 rustup documentation
--config KEY=VALUE or PATH
覆盖一个 Cargo 配置值。参数应该使用 TOML 的 KEY=VALUE 语法,或者提供一个额外配置文件的路径。 这个标志可以被多次指定。更多信息请参见 command-line overrides section
-h
--help
打印帮助信息。
-Z flag
Cargo 的不稳定 (仅限 nightly 版本) 标志。 更多信息请运行 cargo -Z help

环境

更多关于 Cargo 读取的环境变量信息,请参见the reference

退出状态

  • 0: Cargo 成功退出.
  • 101: Cargo 错误退出.

示例

  1. 显示当前目录下的包的树:

    cargo tree
    
  2. 显示所有依赖 syn 的包:

    cargo tree -i syn
    
  3. 显示每个软件包上启用的特性:

    cargo tree --format "{p} {f}"
    
  4. 显示所有被多次构建的包。如果树上出现多个 semver 不兼容的版本(比如 1.0.0 和 2.0.0),就会出现这种情况

    cargo tree -d
    
  5. 解释为什么会启用 syn 包的特性:

    cargo tree -e features -i syn
    

-e features 用于显示特征。-i 标志用于反转图表,使其显示依赖于 syn 的包。 下面是命令输出的一个例子。

syn v1.0.17
├── syn feature "clone-impls"
│   └── syn feature "default"
│       └── rustversion v1.0.2
│           └── rustversion feature "default"
│               └── myproject v0.1.0 (/myproject)
│                   └── myproject feature "default" (command-line)
├── syn feature "default" (*)
├── syn feature "derive"
│   └── syn feature "default" (*)
├── syn feature "full"
│   └── rustversion v1.0.2 (*)
├── syn feature "parsing"
│   └── syn feature "default" (*)
├── syn feature "printing"
│   └── syn feature "default" (*)
├── syn feature "proc-macro"
│   └── syn feature "default" (*)
└── syn feature "quote"
    ├── syn feature "printing" (*)
    └── syn feature "proc-macro" (*)

要阅读这个图,你可以从根部沿着每个特性的链条看它为什么被包含。 例如,"full" 特性是由 rustversion crate 添加的,该 crate 是由 myproject (带有默认特性)包含的, 而 myproject 是命令行上选择的包。所有其他的 syn 特性都是由 "默认" 功能添加的("quote" 是由 "printing" 和 "proc-macro" 添加的,它们都是默认特性)。

如果你在交叉引用去重 (*) 的条目时遇到困难,可以尝试使用 --no-dedupe 标志来获得完整的输出。

另请参见

cargo(1), cargo-metadata(1)

cargo-update(1)

定义

cargo-update - 更新本地lock文件中记录的依赖

概要

cargo update [options]

说明

该命令将更新 Cargo.lock 文件中的依赖到最新版本。 如果 Cargo.lock 文件不存在,将以最新的可用版本创建。

选项

更新选项

-p spec...
--package spec...
只更新指定的包。这个标志可以多次指定。 见 cargo-pkgid(1) 的规格格式。

如果包指定为 -p 标志, 则将对lock文件进行保守的更新。 这表述仅规格指定的依赖更新。 只有当规格版本在不更新依赖的情况下,再不能更新时,它所传递的依赖才会被更新。 所有其他的依赖将保持锁定在其当前记录的版本。

如未指定 -p , 更新所有依赖。

--aggressive
当使用 -p, 规格版本的依赖强制更新。 不能和 --precise 使用。
--precise precise
当使用 -p, 允许指定特定版本号的包。如果包来自git仓库,可以是一个git版本(比如SHA哈希或tag)。
-w
--workspace
尝试只更新工作空间中定义的包。 其他包只有在lock文件中不存在时才会更新。 这个选项对于在Cargo.toml中改变版本号后更新Cargo.lock很有用。
--dry-run
显示将更新内容,实际并未写入lock文件。

Display Options

-v
--verbose
进行详细输出。可以指定两次来开启 "非常详细" ,输出更多的额外信息,像是依赖项的警告和构建脚本的输出信息。 也可以通过 term.verbose 配置
-q
--quiet
不打印 cargo 日志信息。 也可以用 term.quiet 配置
--color when
使用彩色输出。有效值:

  • auto (默认):自动检测终端是否支持彩色。
  • always: 总是显示彩色。
  • never: 总不显示彩色。

也可以用 term.color 配置

配置选项

--manifest-path path
Cargo.toml文件路径。 默认情况下,Cargo会在当前目录或任何父目录下搜索Cargo.toml文件。
--frozen
--locked
这些标志都要求 Cargo.lock 文件是最新的。 如果lock文件丢失, 或是需要更新, Cargo会返回错误并退出,--frozen 选项还会阻止cargo通过网络来判断其是否过期。

可以用于断言 Cargo.lock 文件是否最新状态(例如CI构建)或避免网络访问。

--offline
阻止Cargo访问网络。如果不指定该选项,Cargo会在需要使用网络但不可用时停止构建并返回错误。设置该标识,Cargo将尽可能不使用网络完成构建。

需注意,这样可能会导致与在线模式不同的依赖处理,Cargo将限制仅使用已下载到本地的crate,即使本地索引中有更新版本。 查阅 cargo-fetch(1) 命令,在脱机前下载依赖。

也可以用 net.offline 配置

常规选项

+toolchain
如果Cargo已经通过rustup安装,并且第一个传给 cargo 的参数以 + 开头, 则当作rustup的工具链名称。(例如 +stable+nightly). 查阅 rustup 文档 了解关于工具链覆盖的信息。
--config KEY=VALUE or PATH
覆盖Cargo配置项的值,该参数应当为TOML KEY=VALUE 语法, 或者提供附加的配置文件的路径。该标识可以多次指定。 查阅 命令行覆盖部分 获取更多信息
-h
--help
打印帮助信息。
-Z flag
Cargo不稳定的(每日构建)标志。运行 cargo -Z help 了解详情。

环境

查阅 参考 了解Cargo读取环境变量。

退出状态

  • 0: Cargo 执行成功。
  • 101: Cargo 未执行完成。

示例

  1. 更新lock文件中的所有依赖:

    cargo update
    
  2. 只更新特定的依赖:

    cargo update -p foo -p bar
    
  3. 将一个特定的依赖设置为一个特定的版本:

    cargo update -p foo --precise 1.2.3
    

参阅

cargo(1), cargo-generate-lockfile(1)

cargo-vendor(1)

定义

cargo-vendor - 管理所有本地依赖

概要

cargo vendor [options] [path]

说明

此cargo子命令将把项目crates.io和git所有依赖放到指定的 <path> 目录下。 命令完成后,由 <path> 指定的vendor目录将包含所有来自指定依赖的远程资源。 除默认配置清单,还可以用 -s 选项指定其他配置清单。

cargo vendor 命令也会打印出使用外部资源所需的配置,需要将其添加到 .cargo/config.toml 中。

选项

Vendor选项

-s manifest
--sync manifest
为工作空间指定一个额外的Cargo.toml配置清单,将统一管理并同步输出。可以指定多次。
--no-delete
当进行vendor,不删除"vendor"目录,保留vendor目录的所有内容。
--respect-source-config
.cargo/config.toml中默认忽略[source]配置,而是从crates.io下载crate时读取并使用, 比如
--versioned-dirs
通常,添加版本是为了消除同一包的多版本歧义。这个选项使"vendor"目录中的所有目录都版本化,使得追踪包的历史更容易,当只有一部分包发生变化时,可以提升重新版本化的性能。

配置选项

--manifest-path path
Cargo.toml文件路径。 默认情况下,Cargo会在当前目录或任何父目录下搜索Cargo.toml文件。
--frozen
--locked
这些标志都要求 Cargo.lock 文件是最新的。 如果lock文件丢失, 或是需要更新, Cargo会返回错误并退出,--frozen 选项还会阻止cargo通过网络来判断其是否过期。

可以用于断言 Cargo.lock 文件是否最新状态(例如CI构建)或避免网络访问。

--offline
阻止Cargo访问网络。如果不指定该选项,Cargo会在需要使用网络但不可用时停止构建并返回错误。设置该标识,Cargo将尽可能不使用网络完成构建。

需注意,这样可能会导致与在线模式不同的依赖处理,Cargo将限制仅使用已下载到本地的crate,即使本地索引中有更新版本。 查阅 cargo-fetch(1) 命令,在脱机前下载依赖。

也可以用 net.offline 配置

显示选项

-v
--verbose
进行详细输出。可以指定两次来开启 "非常详细" ,输出更多的额外信息,像是依赖项的警告和构建脚本的输出信息。 也可以通过 term.verbose 配置
-q
--quiet
不打印 cargo 日志信息。 也可以用 term.quiet 配置
--color when
使用彩色输出。有效值:

  • auto (默认):自动检测终端是否支持彩色。
  • always: 总是显示彩色。
  • never: 总不显示彩色。

也可以用 term.color 配置

Common Options

+toolchain
如果Cargo已经通过rustup安装,并且第一个传给 cargo 的参数以 + 开头, 则当作rustup的工具链名称。(例如 +stable+nightly). 查阅 rustup 文档 了解关于工具链覆盖的信息。
--config KEY=VALUE or PATH
覆盖Cargo配置项的值,该参数应当为TOML KEY=VALUE 语法, 或者提供附加的配置文件的路径。该标识可以多次指定。 查阅 命令行覆盖部分 获取更多信息
-h
--help
打印帮助信息。
-Z flag
Cargo不稳定的(每日构建)标志。运行 cargo -Z help 了解详情。

环境

查阅 参考 了解Cargo读取环境变量。

退出状态

  • 0: Cargo 执行成功。
  • 101: Cargo 未执行完成。

示例

  1. 将所有的依赖放到本地的 "vendor" 文件夹中。

    cargo vendor
    
  2. 将所有依赖放到本地的 "third-party/vendor" 文件夹中

    cargo vendor third-party/vendor
    
  3. 将当前工作空间以及另一个工作空间改为 "vendor" 。

    cargo vendor -s ../path/to/Cargo.toml
    

参阅

cargo(1)

cargo-verify-project(1)

定义

cargo-verify-project - 检查crate配置清单的正确性

概要

cargo verify-project [options]

说明

该命令将解析本地配置清单并检查其有效性。发送包含结果的JSON对象。如果验证成功,将显示:

{"success":"true"}

一个无效的工作空间将显示:

{"invalid":"human-readable error message"}

选项

显示选项

-v
--verbose
进行详细输出。可以指定两次来开启 "非常详细" ,输出更多的额外信息,像是依赖项的警告和构建脚本的输出信息。 也可以通过 term.verbose 配置
-q
--quiet
不打印 cargo 日志信息。 也可以用 term.quiet 配置
--color when
使用彩色输出。有效值:

  • auto (默认):自动检测终端是否支持彩色。
  • always: 总是显示彩色。
  • never: 总不显示彩色。

也可以用 term.color 配置

配置选项

--manifest-path path
Cargo.toml 文件的路径。默认, Cargo 在当前目录和任意父目录搜索 Cargo.toml 文件。
--frozen
--locked
这些标志都要求 Cargo.lock 文件是最新的。 如果lock文件丢失, 或是需要更新, Cargo会返回错误并退出,--frozen 选项还会阻止cargo通过网络来判断其是否过期。

可以用于断言 Cargo.lock 文件是否最新状态(例如CI构建)或避免网络访问。

--offline
阻止Cargo访问网络。如果不指定该选项,Cargo会在需要使用网络但不可用时停止构建并返回错误。设置该标识,Cargo将尽可能不使用网络完成构建。

需注意,这样可能会导致与在线模式不同的依赖处理,Cargo将限制仅使用已下载到本地的crate,即使本地索引中有更新版本。 查阅 cargo-fetch(1) 命令,在脱机前下载依赖。

也可以用 net.offline 配置

常规选项

+toolchain
如果Cargo已经通过rustup安装,并且第一个传给 cargo 的参数以 + 开头, 则当作rustup的工具链名称。(例如 +stable+nightly). 查阅 rustup 文档 了解关于工具链覆盖的信息。
--config KEY=VALUE or PATH
覆盖Cargo配置项的值,该参数应当为TOML KEY=VALUE 语法, 或者提供附加的配置文件的路径。该标识可以多次指定。 查阅 命令行覆盖部分 获取更多信息
-h
--help
打印帮助信息。
-Z flag
Cargo不稳定的(每日构建)标志。运行 cargo -Z help 了解详情。

ENVIRONMENT

查阅 参考 了解Cargo读取环境变量。

退出状态

  • 0: 工作空间正常。
  • 1: 工作空间失效。

示例

  1. 检查当前工作空间错误:

    cargo verify-project
    

参阅

cargo(1), cargo-package(1)

包的命令

cargo-init(1)

名称

cargo-init - 在一个已存在的文件夹中创建一个新的包 (package)

概要

cargo init [options] [path]

描述

这个命令会在当前文件夹中创建一个新的 Cargo 清单文件。如果指定一个路径作为参数,则会在给定的文件夹中创建。

如果文件夹中已存在典型命名的 Rust 源代码文件,则会被使用。如果没有,则会创建样板 src/main.rs,如果指定了 --lib,则创建的是 src/lib.rs

选项

创建选项

--bin
创建含有一个二进制 target (src/main.rs) 的包。这是默认行为。
--lib
创建含有一个库 target (src/lib.rs) 的包。
--edition edition
指定使用的 Rust 版本。默认为 2021。可选值有:2015、2018、2021。
--name name
设置包的名字。默认为文件夹名。
--vcs vcs
初始化一个新的 VCS 仓库 (git,hg,pijul 或 fossil),或不初始化任何版本控制 (none)。如果没有指定,默认使用 git ,或者 cargo-new.vcs 中设置的值,或者为 none (如果已经在一个 VSC 库中)。
--registry registry
这会设置 Cargo.toml 中的 publish 字段,指定一个 registry 的名字,使得包只能发布到这个 registry 。

Registry 的名称定义在 Cargo config files. 如果没有指定,则使用registry.default 中设置的默认 registry 。 如果没有设置默认 registry 且没有指定 --registry ,则 publish 字段不会被设置,这意味着发布没有任何限制。

显示选项

-v
--verbose
进行 verbose 输出。可以指定两遍来开启 "very verbose" 模式,输出更多的额外信息,像是依赖项的警告和构建脚本的输出信息。 也可以通过 term.verbose 配置
-q
--quiet
不打印 cargo log 信息。 也可以通过 term.quiet 配置
--color when
控制*何时*使用彩色输出。可选值有:

  • auto (默认值): 自动检测终端是否支持彩色输出。
  • always: 总是显示彩色。
  • never: 从不显示彩色。

也可以在 term.color 配置

通用选项

+toolchain
如果 Cargo 由 rustup 安装,那么 cargo 后第一个以 + 开头的参数会被认为是 rustup toolchain 名字(例如 +stable+nightly)。 查看 rustup documentation 了解 toolchain overrides 如何工作。
--config KEY=VALUE or PATH
覆盖一个 Cargo 配置的值。参数应该是一个 TOML 语法的 KEY=VALUE,或者提供一个路径来指向一个额外的配置文件 (configuration file)。 这个标记可以指定多次。 参考 command-line overrides 一节 获取更多信息。
-h
--help
打印帮助信息。
-Z flag
不稳定 (nightly-only) 的标志。 执行 cargo -Z help 获取详细信息。

环境

查看 the reference 获取 Cargo 读取的环境变量的更多信息。

退出状态

  • 0: Cargo 执行成功。
  • 101: Cargo 没有执行完成。

使用案例

  1. 在当前文件夹中创建一个二进制 Cargo 包:

    cargo init
    

其他参考

cargo(1), cargo-new(1)

cargo-install(1)

名称

cargo-install - 构建和安装 Rust 二进制程序

概要

cargo install [options] crate[@version]...
cargo install [options] --path path
cargo install [options] --git url [crate...]
cargo install [options] --list

描述

这个命令管理 Cargo 安装到本地的所有二进制crate。只有具有可执行的 [[bin]][[example]] 的包才能被安装,保存位置为安装根目录(root)的 bin 文件夹。

安装根目录位置按以下的优先级进行检测:

  • 命令中的 --root 选项
  • CARGO_INSTALL_ROOT 环境变量
  • install.root Cargo 配置选项
  • CARGO_HOME 环境变量
  • $HOME/.cargo

可以从多种来源安装一个crate,默认是从 crates.io,使用 --git--path,和 --registry 可以改变安装源。如果安装源包含多个包 (比如 crates.io 或有包含多个crate 的 git 仓库),则需要 crate 参数来指定具体安装哪个 crate 。

安装 crates.io 中的 crate 时,可以通过 --version 指定想要的版本。同样的,从 git 仓库安装时可以指定 branch、tag 或 revision (hash值)。如果一个 crate 有多个二进制程序(binary),可以使用 --bin 来指定安装其中的一个。如果想安装 example,也可以使用 --example 参数。

当这个包已经被安装,但看起来并不是最新版本时,Cargo 会重新安装它。如果以下的任何一个值发生改变,Cargo 就会重新安装该包:

  • 包的版本或者安装源
  • 安装的二进制程序的名字集合
  • 选择的特性(features)
  • 编译配置 (--profile).
  • 编译目标 (--target).

使用 --path 时总会重新进行构建和安装,除非与其他包的程序发生了冲突。 --force 标志可以强制命令 Cargo 重新安装一个包。

从 crates.io 或 git 仓库进行安装时,会默认在一个临时文件夹中构建该crate。如果要改变这种行为,可以设置 CARGO_TARGET_DIR 环境变量为一个相对路径 (译者注:经测试,这个相对路径是相对于执行 cargo install 命令的路径(cwd),构建过程产生的文件会存在该目录中,而可执行文件还是会放到 bin 目录下)。这在持续集成中缓存(cache) 构建文件尤其有用。

默认情况下,包自带的 Cargo.lock 文件会被忽略,这意味着 Cargo 会重新计算使用依赖的版本,很有可能使用到比发布该包时更新的依赖版本。可以使用 --locked 标志来强制要求 Cargo 使用包自带的 Cargo.lock (如果可行的话)。这对于保证构建的可重复性很有用,因为使用的是这个包发布时的那些保证可用的依赖版本。另一个有用之处在于该包发布后可能有某些依赖更新版本导致该包无法构建,或者依赖更新后出了问题,使用 --locked 可以避免这些麻烦。缺点就是你无法使用到依赖的任何修复或功能更新了。注意,Cargo 直到 1.37 版本才开始允许发布 Cargo.lock ,这意味着这之前发布的包中没有 Cargo.lock

选项

安装选项

--vers version
--version version
指定安装的版本。可以是一个 版本请求 , 比如 ~1.2,使Cargo选择满足请求的最新版本。 如果版本中没有操作符 (比如 ^~), 那么格式必须为 MAJOR.MINOR.PATCH, 从而安装精确的版本; 这个行为 和Cargo toml文件中的版本请求 相同。
--git url
被安装的 crate 的 Git URL。
--branch branch
从 git 安装时使用的 branch。
--tag tag
从 git 安装时使用的 tag。
--rev sha
指定从git安装使用的具体commit。
--path path
本地文件系统中 crate 的路径。
--list
列出所有已安装的包及其版本信息。
-f
--force
强行覆盖现有的 crate 或 二进制文件,这可以用于已安装的二进制程序与另一个包的二进制程序重名时。如果你改变了系统中的某些东西 (比如 rustc 的版本),想要以此重新进行构建该二进制程序,这个功能也会很有用。
--no-track
默认情况下,Cargo 会使用root目录下的一个元数据文件来跟踪已安装的包。`--no-track` 这个标志告诉 Cargo 不要使用或创建该文件。使用该标志后,Cargo 会拒绝覆盖任何已存在的文件,除非使用了 --force 标志。同时这也使得Cargo无法防止同时进行多个 Cargo install 的并发调用
--bin name...
仅安装指定的二进制程序。
--bins
安装所有的二进制程序。
--example name...
仅安装指定的 example。
--examples
安装所有的 example。
--root dir
将包安装到此文件夹。
--registry registry
使用的注册机构 (registry) 的名字。注册机构定义在 Cargo config 文件 中. 如果没有指定就使用默认的注册机构,其定义在 registry.default 字段中,该值的默认值为 crates-io
--index index
使用的注册机构的 index 地址。

选择 feature

特性标志允许你控制开启哪些特性。当没有提供特性选项时,会为每个选择的包启用 default 特性。

查看 features 文档 获取更多信息。

-F features
--features features
用空格或逗号来分隔多个启用的 feature。 工作空间成员的 feature 可以通过 package-name/feature-name 语法来启用。 该标志可以设置多次,最终将启用指定的所有 feature 。
--all-features
启用指定包的所有可用 feature。
--no-default-features
不使用指定包的 default feature 。

编译选项

--target triple
为指定的架构安装,默认情况下是宿主架构。 通常的架构三元组格式为 <arch><sub>-<vendor>-<sys>-<abi>。 运行 rustc --print target-list 可以获取所有支持的架构的列表。

也可以通过 build.target 配置

注意,指定这个标志会使Cargo在不同的模式下运行,目标制品放在单独目录。 参见 构建缓存 文档了解详情。

--target-dir directory
存放构建产物和中间文件的文件夹。也可以用 CARGO_TARGET_DIR 环境变量来设置,或者 build.target-dir 设置选项。默认会放在该平台的的临时文件夹下。

当使用 --path 标志时,默认会放在该本地crate的工作空间的 target 文件夹中,除非明确指定了 --target-dir

--debug
构建 dev profile 而不是 release profile。 另见 --profile 选项,可以用名字来指定一个 profile。
--profile name
根据所给的 profile 进行安装。 参考 the reference 查看关于 profile 的更多信息。
--timings=fmts
输出编译所花费时间的信息,同时跟踪并发信息。接收一个由逗号分隔的输出格式;若 --timings 没有参数,则默认使用 --timings=html。 指定输出格式 (而不是使用默认格式) 是不稳定 (unstable) 的,需要设置 -Zunstable-options。 可用的输出格式选项有:

  • html (不稳定,需要 -Zunstable-options): 写入一个人类可读的 cargo-timing.html 文件到 target/cargo-timings 文件夹,其中包含关于编译过程的报告。 同时也会写入一个文件名带着时间戳 (timestamp) 的报告文件,可以让你读取之前的编译报告。HTML 输出文件只适合人类阅读,不提供机器所需的 timing 数据。
  • json (不稳定,需要 -Zunstable-options): 生成机器可读的 JSON timing 信息。

清单选项

--frozen
--locked
这两个 flag 都需要 Cargo.lock 文件处于无需更新的状态。如果 lock 文件缺失,或者需要被更新,Cargo 会报错退出。 --frozen flag 还会阻止 Cargo 访问网络来判断 Cargo.lock 是否过期。

这些 flag 可以用于某些场景下你想断言 Cargo.lock 无需更新 (比如在CI中构建) 或者避免网络访问。

--offline
阻止 Cargo 访问网络。如果没有这个 flag,当 Cargo 需要访问网络但是没有网络时,就会报错退出。加上这个 flag,Cargo 会尝试在不联网的情况下继续执行 (如果可以的话) 。

要小心这会导致与在线模式不同的解析结果。Cargo 会限制自己在本地已下载的 crate 中查找版本,即使在本地的 index 拷贝中表明还有更新的版本。 cargo-fetch(1) 命令可以在进入离线模式前下载依赖。

同样的功能也可以通过设置 net.offline 配置

杂项

-j N
--jobs N
并行执行的任务数。可以通过 build.jobs 配置。默认值为逻辑CPU数。如果设置为负值,则最大的并行任务数为*逻辑CPU数*加*这个负数*。该值不能为0。
--keep-going
依赖图中的 crate 能构建多少就构建多少,而不是一个失败就停止。功能还不稳定,需要 -Zunstable-options

显示选项

-v
--verbose
进行详细输出。可以指定两遍来开启 "非常详细" 模式,输出更多的额外信息,像是依赖项的警告和构建脚本的输出信息。 也可以通过 term.verbose 配置
-q
--quiet
不打印 cargo 日志信息。 也可以通过 term.quiet 配置
--color when
控制使用彩色输出。可选值有:

  • auto (默认值): 自动检测终端是否支持彩色输出。
  • always: 总是显示彩色。
  • never: 从不显示彩色。

也可以在 term.color 配置

--message-format fmt
诊断信息的输出格式。 可以指定多次,可以包含由逗号分隔的多个值。合法的值有:

  • human (默认值): 显示适合人类阅读的格式。与 shortjson 互斥。
  • short: 生成更短的适合人类阅读的格式。 与 humanjson 互斥。
  • json: 将 JSON 信息输出到 stdout。 从 the reference 获取更多详细信息。 与 humanshort 互斥。
  • json-diagnostic-short: 使得 JSON 的 rendered 属性包含 rustc 渲染的 "short" 信息。不能与 humanshort 一起使用。
  • json-diagnostic-rendered-ansi: 使得 JSON 的 rendered 属性包含嵌入的 ANSI 颜色代码以符合 rustc 的默认颜色策略。 不能与 humanshort 一起使用。
  • json-render-diagnostics: 命令 Cargo 在打印的 JSON 中不包含 rustc 的诊断信息,而是由 Cargo 自己渲染 rustc 提供的 JSON 诊断信息。Cargo 自己的 JSON 诊断信息和其他来自 rustc 的信息都会被生成。 不能与 humanshort 一起使用。

通用选项

+toolchain
如果 Cargo 由 rustup 安装,那么 cargo 后第一个以 + 开头的参数会被认为是 rustup toolchain 名字(例如 +stable+nightly)。 查看 rustup documentation 了解 toolchain overrides 如何工作。
--config KEY=VALUE or PATH
覆盖一个 Cargo 配置的值。参数应该是一个 TOML 语法的 KEY=VALUE,或者提供一个路径来指向一个额外的配置文件 (configuration file)。 这个标记可以指定多次。 参考 command-line overrides 一节 获取更多信息。
-h
--help
打印帮助信息。
-Z flag
不稳定 (nightly-only) 的标志。 执行 cargo -Z help 获取详细信息。

环境

查看 the reference 获取 Cargo 读取的环境变量的更多信息。

退出状态

  • 0: Cargo 执行成功。
  • 101: Cargo 没有执行完成。

使用案例

  1. 从 crates.io 安装或更新一个包:

    cargo install ripgrep
    
  2. 从当前的文件夹中安装或重装一个包:

    cargo install --path .
    
  3. 查看已安装的包的列表:

    cargo install --list
    

其他参考

cargo(1), cargo-uninstall(1), cargo-search(1), cargo-publish(1)

cargo-new(1)

定义

cargo-new - 创建一个新的cargo package

概要

cargo new [options] path

说明

该命令会在给定的目录下新建一个cargo package,将创建一个简单的名为Cargo.toml的清单文件模板, 示例源文件,以及一个版本控制系统的忽略清单文件,如果该目录不在版本控制系统仓库下,那么将会创建一个仓库(详情查看下文中的 --vcs 说明)

查阅 cargo-init(1) 来了解类似的命令,用它可以在一个已经存在的目录下创建一个清单文件。

选项

新建选项

--bin
创建一个以binary为目标的package (src/main.rs). This is the default behavior.
--lib
创建一个以library为目标的package (src/lib.rs).
--edition edition
指定使用的Rust的版本. 默认是 2021, 可能的值有: 2015, 2018, 2021
--name name
设置package的名称,默认为给定的目录的名称。
--vcs vcs
为版本控制系统(git, hg, pijul, 或者fossil)初始化一个仓库,否则将不会使用任何版本控制(none)。 如果该选项未被指定,则默认为 git 或者是在配置文件 cargo-new.vcs中指定的值,如果已经在一个版本控制系统仓库下面则相当于传入了 none
--registry registry
指定该选项将找指定的注册项,并将 Cargo.toml 中的 publish 字段设置成它的值。

注册项的定义在 Cargo 配置文件中。 如果未指定该选项,那么配置文件中 registry.default 块中的配置项将会被采用, 如果 registry.default 未被配置,并且 --registry 也未被指定, 那么 publish 就不会被设置, 这意味着发布将不受限制。

输出选项

-v
--verbose
采用详细输出. 可以被设置两次用来表示 "非常详细" ,将包含额外的输出信息,例如依赖的警告以及构建脚本的输出。 也可以通过 term.verbose 来配置 可选值
-q
--quiet
表示不输出任何cargo日志信息, 也可以通过 term.quiet 来配置可选值
--color when
用来控制何时使用彩色的输出,有效值有:

  • auto (默认): 自动检测该终端是否支持彩色输出。
  • always: 总是使用彩色输出。
  • never: 从不使用彩色输出。

也可以通过 term.color 来配置可选值

一般选项

+toolchain
如果Cargo是通过rustup安装的,如果第一个传给 cargo 的参数是以 + 开头的话, 它将被理解为rustup的工具链名称(例如 +stable 或者 +nightly). 查阅 rustup文档获取更多关于重载工具链的工作原理的信息
--config KEY=VALUE or PATH
表示覆盖一个Cargo配置项的值. 传入的参数应当遵循 KEY=VALUE 的TOML语法或者是 一个额外的配置文件的路径。 该选项可以被配置多次. 查阅 命令行重写部分 获取更多信息。
-h
--help
输出帮助信息。
-Z flag
不稳定的 (只在nightly下可用) 标识,执行 cargo -Z help 获取更多信息。

环境

查阅 参考手册 获取Cargo将读取的环境变量的资料

退出状态

  • 0: Cargo 成功退出.
  • 101: Cargo 错误退出.

示例

  1. 在给定的目录下创建一个cargo package:

    cargo new foo
    

另请参见

cargo(1), cargo-init(1)

cargo-search(1)

定义

cargo-search - 在 crates.io 上搜索包

概要

cargo search [options] [query...]

说明

这将对 https://crates.io 上的 crates 进行文本搜索。匹配的 的 crates 将被显示出来,crates 的描述也会以 TOML 格式显示出来,以便复制到 Cargo.toml 中。

选项

搜索选项

--limit limit
限制结果显示数量 (默认: 10, 最大: 100).
--index index
registry 索引使用的地址.
--registry registry
使用的 registry 的名称。 Registry 的名称定义在 Cargo config files。 若此选项未指定,则使用默认 registry, 默认 registry 由 registry.default 定义。它默认为 crates-io

展示选项

-v
--verbose
使用 verbose 级别输出详细信息。 指定两次此选项来输出 "十分详细" 的输出信息, 这会包含额外的输出信息,比如依赖警告和构建脚本输出。 也可以与 term.verbose config value 一起使用。
-q
--quiet
不要打印任何 cargo 日志信息。 也可以与 term.quiet config value 一起使用。
--color when
控制的日志的颜色。 有效的值如下:

  • auto (默认): 自动检测终端颜色支持是否可用。
  • always: 总是带颜色显示。
  • never: 不带颜色显示.

也可以与 term.color config value 一起使用。

通用选项

+toolchain
如果Cargo已经和rustup一起安装, 并且 cargo 的第一个参数以 + 开头, 它将被解释为一个rustup工具链的名字 (比如 +stable 或者 +nightly)。 更多关于工具链覆盖工作的信息,请参见 rustup documentation
--config KEY=VALUE or PATH
覆盖一个 Cargo 配置值。参数应该使用 TOML 的 KEY=VALUE 语法,或者提供一个额外配置文件的路径。 这个标志可以被多次指定。更多信息请参见 command-line overrides section
-h
--help
打印帮助信息。
-Z flag
Cargo 的不稳定 (仅限 nightly 版本) 标志。 更多信息请运行 cargo -Z help

环境

参见the reference 获取关于 Cargo 所读取的环境变量的细节。

额外状态

  • 0: Cargo 成功完成某项任务.
  • 101: Cargo 未能完成某项任务.

例子

  1. 在 crates.io 上搜索一个包: cargo search serde

另请参见

cargo(1), cargo-install(1), cargo-publish(1)

cargo-uninstall(1)

名称

cargo-uninstall - 移除一个 Rust 二进制程序

概要

cargo uninstall [options] [spec...]

描述

这个命令会移除一个用 cargo-install(1) 安装的包。 spec 参数是被移除的包的 package ID specification (见 cargo-pkgid(1) )。

默认会移除该 crate 的所有可执行程序,但可以用 --bin--example 标志来移除指定的二进制程序。

安装根目录位置按以下的优先级进行检测:

  • 命令中的 --root 选项
  • CARGO_INSTALL_ROOT 环境变量
  • install.root Cargo 配置选项
  • CARGO_HOME 环境变量
  • $HOME/.cargo

选项

安装选项

-p
--package spec...
要卸载的包。
--bin name...
只卸载名为 name 的二进制程序。
--root dir
从哪个文件夹中移除该包。

显示选项

-v
--verbose
进行 verbose 输出。可以指定两遍来开启 "very verbose" 模式,输出更多的额外信息,像是依赖项的警告和构建脚本的输出信息。 也可以通过 term.verbose 配置选项 来指定。
-q
--quiet
不打印 cargo log 信息。 也可以通过 term.quiet 配置
--color when
控制*何时*使用彩色输出。可选值有:

  • auto (默认值): 自动检测终端是否支持彩色输出。
  • always: 总是显示彩色。
  • never: 从不显示彩色。

也可以在 term.color 配置

通用选项

+toolchain
如果 Cargo 由 rustup 安装,那么 cargo 后第一个以 + 开头的参数会被认为是 rustup toolchain 名字(例如 +stable+nightly)。 查看 rustup documentation 了解 toolchain overrides 如何工作。
--config KEY=VALUE or PATH
覆盖一个 Cargo 配置的值。参数应该是一个 TOML 语法的 KEY=VALUE,或者提供一个路径来指向一个额外的配置文件 (configuration file)。 这个标记可以指定多次。 参考 command-line overrides 一节 获取更多信息。
-h
--help
打印帮助信息。
-Z flag
不稳定 (nightly-only) 的标志。 执行 cargo -Z help 获取详细信息。

环境

查看 the reference 获取 Cargo 读取的环境变量的更多信息。

退出状态

  • 0: Cargo 执行成功。
  • 101: Cargo 没有执行完成。

使用案例

  1. 卸载一个之前安装的包:

    cargo uninstall ripgrep
    

其他参考

cargo(1), cargo-install(1)

发布命令

cargo-login(1)

名称

cargo-login - 将 registry 的 API token 保存到本地

概要

cargo login [options] [token]

描述

这个命令会将一个 API token 保存到本地磁盘,之后那些需要身份验证的命令 (比如 cargo-publish(1)) 就会自动验证了。这个 token 保存在 $CARGO_HOME/credentials.tomlCARGO_HOME 默认为你 home 目录的 .cargo 文件夹。

如果没有带上 token 参数,则会从 stdin 中读取。

crates.io 的 API token 可以从 https://crates.io/me 获取。

注意保护你的 token,不要将其泄露给他人。

选项

登陆选项

--registry registry
使用的 registry 的名字。 Registry 的名字定义在 Cargo 配置文件中。 如果没有指定,则使用默认的 registry, 其定义于 registry.default 配置选项中,其默认值为 crates-io

显示选项

-v
--verbose
进行 verbose 输出。可以指定两遍来开启 "very verbose" 模式,输出更多的额外信息,像是依赖项的警告和构建脚本的输出信息。 也可以通过 term.verbose 配置选项 来指定。
-q
--quiet
不打印 cargo log 信息。 也可以通过 term.quiet 配置选项来指定。
--color when
控制*何时*使用彩色输出。可选值有:

  • auto (默认值): 自动检测终端是否支持彩色输出。
  • always: 总是显示彩色。
  • never: 从不显示彩色。

也可以在 term.color 配置选项中设置。

通用选项

+toolchain
如果 Cargo 由 rustup 安装,那么 cargo 后第一个以 + 开头的参数会被认为是 rustup toolchain 名字(例如 +stable+nightly)。 查看 rustup documentation 了解 toolchain overrides 如何工作。
--config KEY=VALUE or PATH
覆盖一个 Cargo 配置的值。参数应该是一个 TOML 语法的 KEY=VALUE,或者提供一个路径来指向一个额外的配置文件 (configuration file)。 这个标记可以指定多次。 参考 command-line overrides 一节 获取更多信息。
-h
--help
打印帮助信息。
-Z flag
不稳定 (nightly-only) 的标志。 执行 cargo -Z help 获取详细信息。

环境

查看 the reference 获取 Cargo 读取的环境变量的更多信息。

退出状态

  • 0: Cargo 执行成功。
  • 101: Cargo 没有执行完成。

使用案例

  1. 将 API token 保存到本地磁盘:

    cargo login
    

其他参考

cargo(1), cargo-publish(1)

cargo-owner(1)

名称

cargo-owner - 管理一个 crate 在 registry 上的所有者

概要

cargo owner [options] --add login [crate]
cargo owner [options] --remove login [crate]
cargo owner [options] --list [crate]

描述

该命令会修改一个 crate 在 registry 上的所有者。crate 的所有者可以上传新版本和 yank 旧的版本。非团队成员的所有者(non-team owners)也可以修改所有者,所以授权时要小心。

这个命令需要你经过身份验证,要么通过提供 --token 选项,要么使用 cargo-login(1) 命令。

如果没有指定 crate 的名称,则会使用当前目录下的包的名字。

the reference 中获取更多关于所有者和发布的知识。

选项

所有者选项

-a
--add login...
添加指定的用户或团队为所有者。
-r
--remove login...
在所有者中移除所指定的用户或团队。
-l
--list
展示一个 crate 的全部所有者。
--token token
用于身份验证的 API token 。这会覆盖保存在 credentials file (由 cargo-login(1) 命令创建) 中的 token。

Cargo config 环境变量也可以覆盖 credentials file 中的 token。crates.io 的 token 可以用 CARGO_REGISTRY_TOKEN 环境变量来指定。其他 registry 的 token 可以用 CARGO_REGISTRIES_NAME_TOKEN 环境变量指定,其中 NAME 是 registry 名字的全大写字母表示。

--index index
使用的注册机构的 index 地址。
--registry registry
使用的注册机构 (registry) 的名字。注册机构定义在 Cargo config 文件 中. 如果没有指定就使用默认的注册机构,其定义在 registry.default 字段中,该值的默认值为 crates-io

显示选项

-v
--verbose
进行 verbose 输出。可以指定两遍来开启 "very verbose" 模式,输出更多的额外信息,像是依赖项的警告和构建脚本的输出信息。 也可以通过 term.verbose 配置选项 来指定。
-q
--quiet
不打印 cargo log 信息。 也可以通过 term.quiet 配置选项来指定。
--color when
控制*何时*使用彩色输出。可选值有:

  • auto (默认值): 自动检测终端是否支持彩色输出。
  • always: 总是显示彩色。
  • never: 从不显示彩色。

也可以在 term.color 配置选项中设置。

通用选项

+toolchain
如果 Cargo 由 rustup 安装,那么 cargo 后第一个以 + 开头的参数会被认为是 rustup toolchain 名字(例如 +stable+nightly)。 查看 rustup documentation 了解 toolchain overrides 如何工作。
--config KEY=VALUE or PATH
覆盖一个 Cargo 配置的值。参数应该是一个 TOML 语法的 KEY=VALUE,或者提供一个路径来指向一个额外的配置文件 (configuration file)。 这个标记可以指定多次。 参考 command-line overrides 一节 获取更多信息。
-h
--help
打印帮助信息。
-Z flag
不稳定 (nightly-only) 的标志。 执行 cargo -Z help 获取详细信息。

环境

查看 the reference 获取 Cargo 读取的环境变量的更多信息。

退出状态

  • 0: Cargo 执行成功。
  • 101: Cargo 没有执行完成。

使用案例

  1. 显示一个包的所有者:

    cargo owner --list foo
    
  2. 给一个包添加一个所有者:

    cargo owner --add username foo
    
  3. 给一个包移除一个所有者:

    cargo owner --remove username foo
    

其他参考

cargo(1), cargo-login(1), cargo-publish(1)

cargo-package(1)

名称

cargo-package - 将本地的 package 打包为可分发的 tarball (tar 打包的压缩文件)

概要

cargo package [options]

描述

这个命令会创建一个可分发的,以 .crate 为后缀的压缩文件,其中包含当前目录下的 package 的源代码。该压缩文件会保存在 target/package 文件夹中。该命令具体会执行以下几步:

  1. 加载并检查当前的工作空间,执行一些基础的检查。
    • 不允许 Path dependencies,除非其设置了 version 字段。Cargo 会忽略那些已发布的包的依赖的 path 字段。dev-dependencies e没有此限制。
  2. 创建一个 .crate 压缩文件。
    • 原有的 Cargo.toml 被重写并格式化。
    • [patch], [replace], 和 [workspace] 部分会从清单文件中移除
    • 如果包中包含二进制 或 example target,Cargo.lock 会被打包进文件。 在指定 --locked 的情况下,cargo-install(1) 会使用该 lockfile。
    • 一个 .cargo_vcs_info.json 文件会被打包进去,其中包含了当前 VCS (Version Control System,如 git) 的checkout hash ( 没有使用 --allow-dirty 的情况下)。
  3. 解压该 .crate 文件并构建,以确认其可以正常构建。
    • 这会从头重新构建你的包来保证其能从原始状态成功构建。 --no-verify 标志可以跳过这个步骤。
  4. 检查确认构建脚本没有修改任何源文件。

可以在清单文件的 includeexclude 字段中控制压缩包要包含的文件。

the reference 获取更多关于打包和发布的知识。

.cargo_vcs_info.json 的格式

.cargo_vcs_info.json 的格式为:

{
 "git": {
   "sha1": "aac20b6e7e543e6dd4118b246c77225e3a3a1302"
 },
 "path_in_vcs": ""
}

对于在版本控制仓库的子文件夹下的包,path_in_vcs 会被设置为以仓库为根的相对路径。

选项

Package 选项

-l
--list
打印包中的所有文件,不创建任何新文件。
--no-verify
不通过构建来检验压缩包中的内容
--no-metadata
忽略因缺少人类可读的元数据(如 description 或 license)而产生的警告信息。
--allow-dirty
允许工作目录中有未提交的 VCS 修改。

包的选择

默认情况下,如果没有提供选择包的选项,那么会按照选择的配置清单文件来选择包(当没有指定 --manifest-path 时,按照当前工目录来查找配置清单文件)。 如果工作空间根目录的配置清单文件,则会选择该工作空间的默认成员,否则仅选取配置清单文件所在的那个包。

可以通过 workspace.default-members 来显式设置一个工作空间的默认成员。如果没有设置,在虚拟工作空间下会选择所有的成员,在非虚拟工作空间下仅会选择根 package 。

-p spec...
--package spec...
仅打包指定的 package。 见 cargo-pkgid(1) 中关于 SPEC 格式的描述。此标志可以指定多次,而且支持 common Unix glob patterns ,如 *?[]。但是,为避免你的 shell 误在 Cargo 之前扩展这些 glob pattern,必须用单引号或双引号将每个 pattern 括起来。
--workspace
打包工作空间中的所有成员。
--exclude SPEC...
排除指定的包。必须与 --workspace 标志一起使用。 此标志可以指定多次,而且支持 common Unix glob patterns ,如 *?[]。但是,为避免你的 shell 误在 Cargo 之前扩展这些 glob pattern,必须用单引号或双引号将每个 pattern 括起来。

编译选项

--target triple
为指定的架构而打包,默认为宿主架构。triple 的格式为 <arch><sub>-<vendor>-<sys>-<abi>。 执行 rustc --print target-list 可以展示支持的 target 的列表。该标志可以指定多次。

也可以通过 build.target 配置

注意,指定这个标志会使Cargo在不同的模式下运行,目标制品放在单独目录。 参见 构建缓存 文档了解详情。

--target-dir directory
存放构建产物和中间文件的文件夹。也可以用 CARGO_TARGET_DIR 环境变量来设置,或者 build.target-dir 设置选项。默认会放在工作空间的 target 下。

选择 feature

特性标志允许你控制开启哪些特性。当没有提供特性选项时,会为每个选择的包启用 default 特性。

查看 the features documentation 获取更多信息。

-F features
--features features
用空格或逗号来分隔多个启用的 feature。 工作空间成员的 feature 可以通过 package-name/feature-name 语法来启用。 该标志可以设置多次,最终将启用指定的所有 feature 。
--all-features
启用指定包的所有可用 feature。
--no-default-features
不使用指定包的 default feature 。

清单选项

--manifest-path path
Cargo.toml 文件的路径。 默认情况下,Cargo 在当前目录或任意的父目录中查找 Cargo.toml
--frozen
--locked
这两个 flag 都需要 Cargo.lock 文件处于无需更新的状态。如果 lock 文件缺失,或者需要被更新,Cargo 会报错退出。 --frozen flag 还会阻止 Cargo 访问网络来判断 Cargo.lock 是否过期。

这些 flag 可以用于某些场景下你想断言 Cargo.lock 无需更新 (比如在CI中构建) 或者避免网络访问。

--offline
阻止 Cargo 访问网络。如果没有这个 flag,当 Cargo 需要访问网络但是没有网络时,就会报错退出。加上这个 flag,Cargo 会尝试在不联网的情况下继续执行 (如果可以的话) 。

要小心这会导致与在线模式不同的解析结果。Cargo 会限制自己在本地已下载的 crate 中查找版本,即使在本地的 index 拷贝中表明还有更新的版本。 cargo-fetch(1) 命令可以在进入离线模式前下载依赖。

同样的功能也可以通过设置 net.offline 配置选项来实现。

杂项

-j N
--jobs N
并行执行的任务数。可以通过 build.jobs 配置选项来指定。默认值为逻辑CPU数。如果设置为负值,则最大的并行任务数为*逻辑CPU数*加*这个负数*。该值不能为0。
--keep-going
依赖图中的 crate 能构建多少就构建多少,而不是一个失败就停止。功能还不稳定,需要 -Zunstable-options

显示选项

-v
--verbose
进行 verbose 输出。可以指定两遍来开启 "very verbose" 模式,输出更多的额外信息,像是依赖项的警告和构建脚本的输出信息。 也可以通过 term.verbose 配置选项 来指定。
-q
--quiet
不打印 cargo log 信息。 也可以通过 term.quiet 配置选项来指定。
--color when
控制*何时*使用彩色输出。可选值有:

  • auto (默认值): 自动检测终端是否支持彩色输出。
  • always: 总是显示彩色。
  • never: 从不显示彩色。

也可以在 term.color 配置选项中设置。

通用选项

+toolchain
如果 Cargo 由 rustup 安装,那么 cargo 后第一个以 + 开头的参数会被认为是 rustup toolchain 名字(例如 +stable+nightly)。 查看 rustup documentation 了解 toolchain overrides 如何工作。
--config KEY=VALUE or PATH
覆盖一个 Cargo 配置的值。参数应该是一个 TOML 语法的 KEY=VALUE,或者提供一个路径来指向一个额外的配置文件 (configuration file)。 这个标记可以指定多次。 参考 command-line overrides 一节 获取更多信息。
-h
--help
打印帮助信息。
-Z flag
不稳定 (nightly-only) 的标志。 执行 cargo -Z help 获取详细信息。

环境

查看 the reference 获取 Cargo 读取的环境变量的更多信息。

退出状态

  • 0: Cargo 执行成功。
  • 101: Cargo 没有执行完成。

使用案例

  1. 创建当前包的 .crate 压缩文件:

    cargo package
    

其他参考

cargo(1), cargo-publish(1)

cargo-publish(1)

定义

cargo-publish - 上传包到注册中心

概要

cargo publish [options]

说明

该命令将在当前目录下创建一个待分发的、压缩的 .crate 文件,其中包含包的源代码,并将其上传到注册中心。 默认的注册中心是 https://crates.io 。将执行以下步骤:

  1. 进行一些检查,包括:
    • 检查配置清单中的 package.publish 键,看是否限制发布到哪些注册中心。
  2. 按照 cargo-package(1) 中的步骤,创建 .crate 文件。
  3. 将crate上传到注册中心。需注意,服务器将对crate进行额外的检查。

该命令要求您使用 --token 选项或使用 cargo-login(1) 进行认证。

参考 了解关于包和发布的详情。

选项

发布选项

--dry-run
在不上传的情况下执行所有检查。
--token token
认证时要使用的 API token。这将覆盖存储在证书文件中的令牌(由 cargo-login(1))。

Cargo配置环境变量可用于覆盖存储在证书文件中的令牌。 crates.io的令牌可以用CARGO_REGISTRY_TOKEN环境变量指定。其他注册中心的令牌可以用以下形式的环境变量来指定 CARGO_REGISTRIES_NAME_TOKENNAME 是注册中心的名称,全部大写字母。

--no-verify
不通过构建来验证内容。
--allow-dirty
允许将带有未提交修改内容的VCS工作目录打包。
--index index
使用的注册中心索引URL。
--registry registry
要发布到的注册中心名称,定义在 Cargo 配置文件。 如果未指定, 在Cargo.toml package.publish 字段有单独的键, 那么将发布到该注册中心。 否则,将使用默认的注册中心, 由 registry.default 键定义, 默认为crates-io

包的选择

默认情况下,选中当前工作目录下的包。可用 -p 标志选择工作空间中不同的包。

-p spec
--package spec
要发布的包,见 cargo-pkgid(1) 了解 SPEC 规格。

编译选项

--target triple
对于给定架构发布。默认是主机的架构。常规格式是三元组 <arch><sub>-<vendor>-<sys>-<abi>。 运行rustc --print target-list获得支持的目标列表。 这个标志可被多次指定。

也可以通过 build.target 配置

注意,指定这个标志会使Cargo在不同的模式下运行,目标制品放在单独目录。 参见 构建缓存 文档了解详情。

--target-dir directory
所有生成制品和中间文件的目录。 也可以用 CARGO_TARGET_DIR 环境变量, 或 build.target-dir 配置。 默认为工作空间的根target

特性选择

特性标志允许你控制开启哪些特性。当没有提供特性选项时,会为每个选择的包启用 default 特性。

特性文档 了解更多内容。

-F features
--features features
激活的特性列表用空格或逗号分隔。可以用package-name/feature-name语法启用工作空间成员的特性。这个标志可以被多次指定,从而可以启用所有指定的特性。
--all-features
激活所有选定包的所有可用特性。
--no-default-features
不激活所选包的default特性。

配置选项

--manifest-path path
Cargo.toml 文件的路径。默认, Cargo 在当前目录和任意父目录搜索 Cargo.toml 文件。
--frozen
--locked
这些标志都要求 Cargo.lock 文件是最新的。 如果lock文件丢失, 或是需要更新, Cargo会返回错误并退出,--frozen 选项还会阻止cargo通过网络来判断其是否过期。

可以用于断言 Cargo.lock 文件是否最新状态(例如CI构建)或避免网络访问。

--offline
阻止Cargo访问网络。如果不指定该选项,Cargo会在需要使用网络但不可用时停止构建并返回错误。设置该标识,Cargo将尽可能不使用网络完成构建。

需注意,这样可能会导致与在线模式不同的依赖处理,Cargo将限制仅使用已下载到本地的crate,即使本地索引中有更新版本。 查阅 cargo-fetch(1) 命令,在脱机前下载依赖。

也可以用 net.offline 配置

其它选项

-j N
--jobs N
并行执行的任务数。可以通过 build.jobs 配置。默认值为逻辑CPU数。如果设置为负值,则最大的并行任务数为*逻辑CPU数*加*这个负数*。该值不能为0。
--keep-going
尽可能的构建依赖图中的 crate ,而不是一个失败就停止。功能还不稳定,需要 -Zunstable-options

Display Options

-v
--verbose
进行详细输出。可以指定两遍来开启 "非常详细" 模式,输出更多的额外信息,像是依赖项的警告和构建脚本的输出信息。 也可以通过 term.verbose 配置
-q
--quiet
不打印 cargo 日志信息。 也可以通过 term.quiet 配置
--color when
控制使用彩色输出。可选值有:

  • auto (默认值): 自动检测终端是否支持彩色输出。
  • always: 总是显示彩色。
  • never: 从不显示彩色。

也可以在 term.color 配置

常规选项

+toolchain
如果Cargo已经通过rustup安装,并且第一个传给 cargo 的参数以 + 开头, 则当作rustup的工具链名称。(例如 +stable+nightly). 查阅 rustup 文档 了解关于工具链覆盖的信息。
--config KEY=VALUE or PATH
覆盖Cargo配置项的值,该参数应当为TOML KEY=VALUE 语法, 或者提供附加的配置文件的路径。该标识可以多次指定。 查阅 命令行覆盖部分 获取更多信息
-h
--help
打印帮助信息。
-Z flag
Cargo不稳定的(每日构建)标志。运行 cargo -Z help 了解详情。

环境

查阅 参考 了解Cargo读取环境变量。

退出状态

  • 0: Cargo 执行成功。
  • 101: Cargo 没有成功完成。

示例

  1. 发而当前的包:

    cargo publish
    

参阅

cargo(1), cargo-package(1), cargo-login(1)

cargo-yank(1)

定义

cargo-yank - 从索引中删除推送的crate

概要

cargo yank [options] crate@version
cargo yank [options] --version version [crate]

说明

yank命令从服务器的索引中删除先前发布的crate的版本。 该命令不会删除任何数据,该crate仍可通过注册中心的下载链接进行下载。

请注意,crate的已锁死版本仍然能够下载使用。而Cargo将不允许新的crate使用锁死版本。

该命令要求使用 --token 选项或使用 cargo-login(1)进行认证。

如果未指定crate名称,将使用当前目录包的名称。

选项

Yank 选项

--vers version
--version version
yank 或 un-yank 的版本。
--undo
撤消yank,将版本放回到索引中。
--token token
认证时要使用的 API token。这将覆盖存储在证书文件中的令牌(由 cargo-login(1))。

Cargo配置环境变量可用于覆盖存储在证书文件中的令牌。 crates.io的令牌可以用CARGO_REGISTRY_TOKEN环境变量指定。其他注册中心的令牌可以用以下形式的环境变量来指定 CARGO_REGISTRIES_NAME_TOKENNAME 是注册中心的名称,全部大写字母。

--index index
要使用的注册中心索引的URL。
--registry registry
要使用的注册中心的名称。定义在 Cargo 配置文件中。 如果没有指定,则使用默认,由 registry.default 键配置,默认为 crates-io

显示选项

-v
--verbose
详细输出。 可以指定两次以 "非常详细" 输出,包含附加内容,如依赖警告和构建脚本输出。 也可以用 term.verbose 配置
-q
--quiet
不打印cargo日志信息。 也可以用 term.quiet 配置
--color when
使用彩色输出。有效值:

  • auto (默认):自动检测终端是否支持彩色。
  • always: 总是显示彩色。
  • never: 总不显示彩色。

也可以用 term.color 配置

常规选项

+toolchain
如果Cargo已经和rustup一起安装,并且cargo的第一个参数为 +, 它将被解释为Rustup工具链的名称 (比如 +stable+nightly). 见 rustup 文档 了解相关工具链覆盖的详细信息。
--config KEY=VALUE or PATH
覆盖Cargo配置值。参数应是TOML语法中的 KEY=VALUE, 或作为一个额外的配置文件的路径提供。这个标志可以被多次指定。 见 command-line 覆盖部分 了解详细信息。
-h
--help
打印帮助信息。
-Z flag
Cargo 不稳定 (每日构建) 的标志。 运行 cargo -Z help 获得详细信息。

ENVIRONMENT

参考 以了解Cargo所读取环境变量的详情。

退出状态

  • 0: Cargo 成功。
  • 101: Cargo 未能完成。

示例

  1. 在索引Yank crate:

    cargo yank foo@1.0.7
    

参阅

cargo(1), cargo-login(1), cargo-publish(1)

常见问题

有计划使用 GitHub 作为包存储仓库吗?

没有。Cargo 会使用 crates.io,就像 npm 的 npmjs.com 和 Rubygems 的 rubygems.org

我们将永远支持使用 git 仓库作为包的一个来源,因为其可以用在早期开发和临时覆盖中,但还是会将注册中心作为包的主要来源。

为什么建立 crates.io 而不是使用 GitHub 作为 registry ?

我们认为支持多种下载包的方式是很重要的,其中包括从 GitHub 下载并将其拷贝到你的包中。

尽管如此,我们还是认为 crates.io 提供了一些重要的便利,会成为人们用 Cargo 下载包的主要方式。

作为先例,Node.js 的 npm 和 Ruby 的 bundler 都同时支持一个中心化的注册中心模型和基于 git 的模型,大部分的包都是从它们生态的注册中心下载的,少数的包使用基于 git 的下载。

让中心化的注册中心在这些语言中得以流行的优势有:

  • 可发现性。核心的注册中心提供了便捷的地方来查找已有的包。结合标记技术,注册中心可以提供生态广泛的信息,诸如最受欢迎或最被依赖的包的列表。
  • 速度。核心的注册中心可以让我们快速有效地获取包的元数据,然后高效地只下载那些被发布的包,而不会下载那些恰巧保存在 git 仓库中的无用内容。这能显著提高依赖解析和下载的速度。随着依赖图的增大,从 git 仓库中下载的方式很快就会陷入困境。另外不是每个人都拥有高速低延迟的网络。

Cargo 可以和 C 代码(或者其他语言)一起工作吗?

当然! Cargo 用于处理编译 Rust 代码,但我们也了解很多 Rust 包链接到 C 代码,编译其他语言的工具已经发展了几十年的时间。

我们的解决方案是:Cargo 允许包指定(用Rust写的)脚本,在调用 rustc 之前执行。用于实现平台特定的设置和重构包之间的公共构建的功能。

Cargo 可以用在 make (或 ninja,...) 之中吗?

当然。在我们设计让 Cargo 独立编译 Rust 包,也考虑到一些人想要在其他构建工具中调用 Cargo。

我们设计让Cargo在这些情境下很好地工作,花了很多精力在错误代码和机器可读的输出上。 这些方面我们还有很多工作要做,在常见的脚本中使用Cargo是从一开始就设计好的,并且会继续作为高优先级的任务。

Cargo 可以处理多平台的包或者交叉编译吗?

Rust 本身提供了基于平台控制代码段的功能。Cargo 也支持 平台特定依赖,而且我们计划在 Cargo.toml 中支持为不同平台进行更多设置。

长期来看,我们正在研究用 Cargo 进行交叉编译的简便方法。

Cargo 是否支持环境,比如 productiontest

我们通过使用编译设置(profiles)来支持环境:

  • 环境指定标志(如 -g --opt-level=0 用于开发环境,而 --opt-level=3 用于生产环境)。
  • 环境指定依赖,如 hamcrest 用于测试断言。
  • 环境指定 #[cfg]
  • cargo test 命令。

Cargo 可以在 Windows 上使用吗?

当然!

Cargo 的所有 commits 提交都要求通过 Windows 上的测试。如果你在 Windows 上运行 Cargo 时遇到问题,我们将其视为一个 bug,请提一个 issue

为什么二进制 crate 有 Cargo.lock,而库 crate 却没有?

Cargo.lock 的目的在于描述一次成功构建发生时,当时完整的状态。Cargo 借助 lockfile 在不同时刻和不同系统中提供确定性的构建结果,保证使用的依赖版本与 Cargo.lock 被创建时使用的完全一致。

这种特性最适合应用 (application) 以及那些处于依赖链末端的包 (二进制crate) 。因此,建议每个二进制 crate 都添加 Cargo.lock

对于库而言情况就有所不同了。一个库不仅仅是库的开发者在用,而会是下游的所有使用者。 依赖该库的用户不会检查这个库的 Cargo.lock (即使这个文件存在)。这是应该的,因为对于库的用户来说,一个库应该被确定性地重新构建。

如果一个库被几个依赖传递性地使用,那么应该只保留该库的一份拷贝 (SemVer兼容的前提下)。 如果 Cargo 使用所有依赖的 Cargo.lock ,就可能会使用到该库的多个版本,甚至造成版本冲突。

换句话说,库指定了自己的依赖的 SemVer 语义化版本,但是无法看到(依赖图的)全貌。 只有像是二进制程序这样的末端产品才能看到全貌,决定使用依赖的哪个具体版本。

库可以使用 * 来指定依赖的版本吗?

从2016年1月22日开始,crates.io 拒绝所有带着 * 依赖的包(不仅是库)。

库可以,但是,库不应该可以。一个 * 版本请求好像在说:"能在任何版本都会正常工作",但这是不可能的。库总是应该指定可以工作的一个版本范围,即使是"所有的 1.x.y 版本" 这种宽泛的范围。

为什么有 Cargo.toml

作为与 Cargo 交互最多的部分,关于为什么配置文件叫 Cargo.toml 的问题从来没有停过。开头的大写字母 C 是为了让这个配置清单文件和其他类似的配置文件(configuration file)放在一起。 文件排序一般会把大写字母开头的文件放在小写字母开头的文件之前,这保证 Cargo.toml 会和 Makefile 这类文件放在一起。后面的 .toml 表示这是 TOML 格式 的文件。

Cargo 不允许使用其他的配置文件名如 cargo.tomlCargofile,从而更容易识别 Cargo 仓库。提供可选的其他名字在历史上经常导致某些情况被忘记处理,从而导致错误。

如何在离线状态使用 Cargo ?

Cargo 经常被用于限制或者没有网络的场景,比如在飞机上、CI 环境、或者嵌入到大型的产品部署中。当 Cargo 尝试从网络获取资源时,用户经常感到惊讶,因此经常要求 Cargo 可以在离线环境中使用。

Cargo 其实不会主动去访问网络,除非你叫它去做。也就是说,如果不需要来自 crates.io 、 git 仓库或其他网络位置的 crate 时,Cargo 绝不会去访问网络。 反过来说,如果 Cargo 尝试访问网络,那一定是它需要通过网络来获取所需的资源。

Cargo 会十分激进地缓存信息以最少化网络访问。它保证,如果 cargo build (或其他类似的指令) 执行成功,那么下一次 cargo build 绝不会再访问网络,除非 Cargo.toml 在这期间被修改。阻止网络访问的方法归结为 Cargo.lock 文件以及相对应的对 crate 的 cache。如果两者之一丢失,那么当下次构建时需要访问网络。

从 Rust 1.11.0 开始,Cargo 可以使用一个新的标志 --frozen,其断言 Cargo 不能访问网络。一旦传递了这个标志,当 Cargo 试图访问网络时会立刻报错退出。 错误信息中包含需要访问网络的原因以帮助排查错误。注意,这个标志 不会改变 Cargo 的行为 ,其仅仅是在之前的命令已经准备好相应的资源后,声明 Cargo 接下来不应该访问网络。

在 Rust 1.36.0 中加入了 --offline 标志。这个标志告诉 Cargo 不要访问网络,同时尽可能用缓存的数据完成执行(如果可能的话)。 你可以用 cargo fetch 在断网之前下载好需要的依赖,然后通过 --offline (或者 cargo设置选项)) 将这些依赖用在另一个项目中。

源替换 获取更多信息。

为什么 Cargo 重新构建了我的代码?

Cargo 负责增量编译你项目中的 crate。这意味着如果你连续进行两次 cargo build,第二次运行不应该重新构建你的 crates.io 依赖。然而某些时候会发生 bug 导致 Cargo 重新构建你的代码。

我们很长时间内都想给这个问题提供更好的诊断信息,但是还没有取得进展。与此同时,你至少可以通过设置 CARGO_LOG 来对重新构建(rebuild)的原因进行一些诊断。

$ CARGO_LOG=cargo::core::compiler::fingerprint=info cargo build

这会使得 Cargo 打印出一大堆关于诊断和重新构建的信息,里面经常会有一点线索,但是大部分时候需要你费点力气去分析,因为这些信息暂时还不是那么容易阅读。 注意 CARGO_LOG 需要设置在你认为不应该但是却导致了重新构建的命令上。不幸的是 Cargo 目前还不支持事后分析——"为什么会发生重新构建?"

曾经的一些issue告诉我们以下情况会导致 crate 被重新构建:

  • 一个构建脚本打印了 cargo:rerun-if-changed=foo ,但是 foo 这个文件并不存在而且不会被生成。这导致 Cargo 一直执行构建脚本以生成这个文件,但是始终无法生成。这种情况的解决办法就是停止打印 rerun-if-changed

  • 连续的两次 Cargo build 可能会在某个依赖上启用不同的特性。例如第一个构建命令构建整个工作空间,第二个命令仅仅构建一个 crate,这可能会导致某个依赖使用了不同的特性,导致这个依赖和依赖它的内容被重新构建。很遗憾这没有完美的解决办法,如果可能的话,最好使得,不管你在工作空间中构建什么时,都让一个 crate 的特性保持不变。

  • 一些文件系统在时间戳(timestamp)上显示出不寻常的行为。Cargo 主要利用文件的时间戳来决定重新构建是否应该发生,但是如果你用的是一个非标准的文件系统,其可能会影响到时间戳 (例如截断或偏离)。在这种情况下,可以开一个 issue ,我们会试着看看能否以某种方法适配这个文件系统。

  • 一个并发的构建进程要么在删除构建制品,要么在修改文件。有时你有一个后台进程尝试构建或者检查项目。这个后台进程可能令人惊讶的删除了某些构建制品或者改变了文件,这会导致奇怪的重新构建。最好的解决方法是调整后台进程,避免与你的工作发生冲突。

如果在尝试 debug 你的问题后,还是无法解决,请开一个issue

《翻译不加料》

译者之地。

出于动态更新,保持原义等方面考虑,翻译中并未添加过多译注。 但翻译过程中语言不对称所造成的信息丢失再所难免。 鉴于此增补一些内容,请酌情阅读。

动态更新。

Cargo 原文内容在不断更新增加中,文档的翻译会进行一个较长时间段的动态更新,初步考虑是季度为单位的。 因为少量原文变更时动态更新中文翻译有较大人力和时间消耗,同时也很难把翻译校准。 这可以参考一些技术类书籍的内容有效性,语言类的在1、2年都不会过时。Cargo、Rust都有很好的向后兼容性 在一个大版次内翻译内容都将是适用的。

同时,中文翻译也将是动态更新的,一方面译者尽力多次的校对增补,另一方面会吸收其他贡献者的翻译增补。

欢迎增补。

从增补的角度来讲,有两种做法:

一种是这种增补性的文章,这种文章的优点是没有破坏原文章,但缺点增加了 读者的负担,可能需要花更多的时间来阅读。

一种是对翻译的进一步校对润色。这也是较好的一个选择。但翻译的过程必然会有一些英文原义有所丢失。 以及译者自身的限制,这种情况下

保持原义。

以及尽力保持原义,翻译时未加料,只有少量的译注。

名词补充。

尤其是一些专用名词

增加章节。

所以增加了这样一个章节,从中文的角度来解释一些可能需要阐释的要点。

词汇表

制品

artifact "制品"是指编译进程最终创建的文件或文件集,包括可链接库、可执行的二进制文件和生成的文档。

Cargo

Cargo 是Rust的包管理器,也是本书涉及的主要内容。

Cargo.lock

参阅 lock 文件

Cargo.toml

参阅 配置清单

Crate

Rust crate 是指一个库或一个可执行程序,分别称为 library cratebinary crate

Cargo package定义的每个target都是crate

广义来说,术语 crate 可以指目标源代码或目标产生的编译制品,也可以指从注册中心获取的压缩包。

指定crate源代码可以细分为modules "模块"。

版本

Rust版本 是Rust语言的发展标志。包的版本是在 Cargo.toml 配置清单中指定的,不同的目标可以指定对应版本来使用。更多信息请参阅版本指南

特性

feature "特性" 的含义取决于上下文:

  • feature是一个命名的标志,允许有条件的编译。一个特性可以指一个可选的依赖,也可以指一个任意的名字,在 Cargo.toml manifest 中定义,可在源代码中检查。

  • Cargo有不稳定特性标记,可以用来启用Cargo本身的实验性特性。

  • Rust编译器和Rustdoc有自己的不稳定特性标志 (参阅不稳定篇Rustdoc篇)。

  • CPU 目标有目标特性,指定CPU的性能。

索引

index "索引" 是注册中心crates 的可搜索列表。

Lock 文件

Cargo.lock lock文件 记录 workspacepackage中使用的每个依赖的确切版本。它是由Cargo自动生成的。参阅 Cargo.toml vs Cargo.lock

配置清单

其名为 Cargo.toml 的文件中,配置清单是对packageworkspace的描述。

[虚拟配置清单][virtual manifest] Cargo.toml 文件,仅描述一个工作空间,不包含包。

成员

member "成员"是属于workspacepackage

模块

Rust的模块系统将代码组织成称为 modules "模块"的逻辑单元,在代码中提供独立的命名空间。

指定的 crate 的源代码可以被细分为一个或多个独立的模块。这样做通常是为了将代码组织在相关的功能区域,或者来控制源代码中的标识符(结构体、函数等)的可见性(public/private) "公共/私有"。

Cargo.toml文件主要关注它所定义的package、crates、它们所依赖的crates的包。尽管如此,在使用Rust时,你会经常注意到 "模块" 这个术语,所以你应该了解模块与crate的关系。

package "包" 是对源文件集合和 Cargo.toml manifest 文件的描述。包对应的名称和版本,用来指定包之间的依赖关系。

package "包" 包含多个target,每个都是一个crateCargo.toml 文件描述了包内的crate的二进制或库的类型,以及每个crate的一些元数据--如何构建每个crate,它们的直接依赖是什么,等等,这正是本书所描述的。

package root "包的根" 是指包的 Cargo.toml 配置清单所在的目录。(相对于工作区根)。

package ID specification,或 SPEC ,是一个字符串,用来唯一地引用一个特定来源包的特定版本。

尽管多个crates是很常见的,但往往中小型的Rust项目只需要一个包。

较大的项目可能涉及多个软件包,在这种情况下,Cargo workspaces 可以用来管理软件包之间的共同依赖和其他相关元数据。

包管理

广义上讲,包管理器 是软件生态系统中的一个程序(或相关程序的集合),它可以自动获取、安装和升级制品。在编程语言的生态系统中,软件包管理器是以开发者为中心的工具,其主要功能是从一些中心存储库中下载库的制品和它们的依赖;这种功能通常与执行软件构建的功能相结合(通过调用特定语言的编译器)。

Cargo是Rust生态系统中的软件包管理器。Cargo下载 Rust package的依赖项(artifacts被称为crates)、编译包、制作可分享的包,并(可选择)将它们上传到Rust社区的 package 注册中心

包注册中心

参阅 注册中心

项目

package 的另一个名称。

注册中心

registry "注册中心" 服务,拥有可下载的crates集合,可以作为package的依赖而被安装使用。Rust生态系统中的默认注册中心是crates.io。 该注册中心有一个index,包含了所有crate的列表,并告知Cargo如何下载需要的crate。

一个source "源" 是拥有crates的提供者,它可以作为 package 的依赖项。源有以下几种类型:

  • 注册中心源 — 参阅 注册中心
  • 本地注册源 — 一组以压缩文件形式存储在文件系统中的crates。参阅 本地注册源
  • 目录源 — 一组以压缩文件形式存储在文件系统中的crates。参阅 目录源.
  • 路径源 — 在文件系统是独立包(如路径依赖)或多个软件包的集合(比如[路径覆盖])。
  • Git源 — 位于git仓库中的包(比如git 依赖git 源)。

详见 源替换

Spec

参阅 package ID specification

目标

target "目标"术语的含义取决于上下文:

  • Cargo 目标 — Cargo packages targets ,对应于将要生成的 制品。包可以有库、二进制、示例、测试和性能测试目标。在 Cargo.toml manifest中配置目标列表,通常由源文件的目录层级自动推断。

  • 目标目录 — Cargo将所有构建的制品和中间文件放在 目标 目录中。默认情况下是一个名称为 target 的目录,位于 workspace 根目录下,如果不使用工作区,则为包的根目录。该目录可以通过 --target-dir 命令行选项、CARGO_TARGET_DIR环境变量build.target-dir 配置选项 来改变。

  • 目标架构 — 操作系统以及机器架构中所构建的制品通常被称为 目标

  • 目标三元组 — 三元组架构是指定目标体系结构的特定格式。三元组可以被称为 目标三元组 ,它是生成制品的体系结构,而 host triple 是编译器运行的体系结构。目标三元组可以通过命令行选项 --targetbuild.target 配置选项 指定。三元组的一般格式是 <arch><sub>-<vendor>-<sys>-<abi> :

    • arch = CPU基础架构, 例如 x86_64, i686, arm, thumb, mips 等。
    • sub = CPU子架构, 例如 arm has v7, v7s, v5te 等。
    • vendor = 供应商 , 例如 unknown, apple, pc, nvidia 等.
    • sys = 系统名称, 例如 linux, windows, darwin 等。 none 是没有操作系统的裸机.
    • abi = ABI, 例如 gnu, android, eabi 等。

    一些可省略参数。运行 rustc --print target-list 获取列表。

测试目标

Cargo 测试目标 生成的二进制文件有助于验证代码的正确操作和准确性。有两种类型的测试制品:

  • 单元测试单元测试是可执行的二进制文件,由库或二进制目标直接编译生成。它包含库或二进制代码的全部内容,并运行 #[test] 注解的函数,旨在验证各个单元的代码。
  • 集成测试目标集成测试目标 是由 测试目标 编译的可执行二进制文件,该目标是一个独立的 crate ,其来源位于 tests 目录下或由 Cargo.toml manifest 中的 [[test]] table 指定。它的目的是只测试一个库的公共API,或执行一个二进制文件以验证操作。

工作空间

workspace 是一个或多个 packages 的集合,它们共享共同的依赖(拥有共享的Cargo.lock lock file)、输出目录,各项设置,如配置文件。

虚拟工作区Cargo.toml manifest 没有定义包,只列出工作区 成员

工作区根 是工作区的 Cargo.toml 配置清单所在的目录。 (相对于package root)。

Git 认证

在使用git依赖和注册中心时,Cargo支持一些形式的认证。本附录包含一些关于设置git认证的内容,以便与Cargo配合使用。

如果你需要其他的认证方法,可以设置 net.git-fetch-with-cli 配置值,使Cargo执行 git 可执行文件来处理获取远程仓库,而不是使用内置支持。 这可以通过 CARGO_NET_GIT_FETCH_WITH_CLI=true 环境变量来启用。

HTTPS 认证

HTTPS认证需要 credential.helper 机制。有多个凭证辅助工具,你在全局git配置文件中指定你要使用那个。

# ~/.gitconfig

[credential]
helper = store

Cargo不要求密码,所以对于大多数辅助工具来说,你需要在运行Cargo之前给辅助工具提供用户名及密码。一种方式是运行私有git仓库的 git clone 并输入用户名及密码。

提示:
macOS用户可能要考虑使用osxkeychain辅助工具。
Windows用户可能要考虑使用GCM辅助工具。

注意: Windows用户需要确保 sh shell在你的 PATH 中可用。 这通常是在安装Git for Windows时才有。

SSH 认证

SSH 认证需要运行 ssh-agent 来获取 SSH 密钥。确保设置了适当的环境变量(在大多数类似 Unix 的系统上为 SSH_AUTH_SOCK),并添加了正确的密钥(用 ssh-add)。

Windows可以使用Pageant(PuTTY的一部分)或 ssh-agent 。要使用 ssh-agent ,Cargo需要使用作为Windows一部分分发的OpenSSH,因为Cargo不支持MinGW或Cygwin使用的模拟Unix-domain套接字。 关于用Windows安装的更多信息可以在微软安装文档找到,密钥管理页面有关于如何启动 ssh-agent 和添加密钥的说明。

注意: Cargo不支持git的简化SSH URL,如 git@example.com:user/repo.git 。 使用完整的SSH URL 如 ssh://git@example.com/user/repo.git .

注意: Cargo的内置SSH库不使用SSH配置文件(如OpenSSH的~/.ssh/config)。 高级选项应使用 net.git-fetch-with-cli