14更多关于Cargo和Crate.io的内容

  • 使用发布配置来自定义构建
  • 将库发布到 crates.io
  • 使用工作空间来组织更大的项目
  • 从 crates.io 安装二进制文件
  • 使用自定义的命令来扩展 Cargo

更多内容,参考 Cargo 文档

采用发布配置自定义构建

在 Rust 中 发布配置(release profiles)是预定义的、可定制的带有不同选项的配置

Cargo 有两个主要配置:

  • 运行 cargo build 时采用的 dev 配置
    • 是开发时的默认配置
  • 运行 cargo build --releaserelease 配置
    • 时发布构建时的默认配置

如果需要修改,在 Cargo.toml 文件中添加对应的 [profile.*] 部分

例如:

1
2
3
4
5
[profile.dev]
opt-level = 0 # opt-level 控制 Rust 对代码进行何种程度的优化,0~3,数值越高优化级别越高,需要的编译时间也越多。

[profile.release]
opt-level = 3

将 crate 发布到 crates.io

编写有用的文档注释

/// 为 Rust 的文档注释(documentation comments)

  • 支持 Markdown 格式;
  • 会生成 HTML 文档,这些文档展示公有 API (有 pub 标注的api)的注释部分的内容;
  • 这些文档帮助使用者如何使用这个 crate,而不是关注如何实现的。

生成:

  • cargo doc 命令生成文档,这个命令实际由 Rust 分发的工具 rustdoc 运行并将生成的 HTML 文档放入 target/doc 目录。
  • 使用 cargo doc --open 会构建当前 crate 文档(同时还有所有 crate 依赖的文档)的 HTML 并在浏览器中打开。

文档注释作为测试

文档注释中可添加代码示例,好处:

  1. 清楚的表明如何使用库的方法;
  2. cargo test 也会像测试那样运行文档中的示例代码;
    • 这样可以避免当代码修改后,注释与代码不匹配的问题。
    • 运行 cargo test ,结果中的 Doc-test 部分就是文档测试部分

注释包含项的结构

//! 这中注释风格,通常用于 crate 根文件(通常是 src/lib.rs)或模块的根文件,为 crate 或模块整体提供文档。

使用 pub use 导出合适的公有 API

有时我们项目的结构可能是一个包含多个层级的分层结构,对外公布时,对于使用者来说过多的层级可能不是很方便。

解决:

通过使用 pub use 重导出(re-export)项来调整公有 API 的结构,使对外的公有结构不同于内部结构。

  • 重导出获取位于一个位置的公有项并将其公开到另一个位置,好像它就定义在这个新位置一样。

问题:如何将原有的内部结构重新导出到顶层结构?语法是什么?

1
self::<mod名称>::...? 原有内部结构路径?

注:使用 pub use 重导出公有 API 结构之后,用户仍然可以使用原有的内部结构

发布新 crate 之前

通过 cargo publish 命令可以将本地 crate 发布到 crates.io 仓库中。

发布之前,需要修改要对外发布的 crate 的 元信息(在 Cargo.toml 文件中)。

  • crate 在 crates.io 上是唯一的,发布之前需要查询确认,名称遵循先到先得的分配原则。
  • 其他元信息可以通过执行 cargo publish 命令后看编译器报错修改。
  • 可以参考 发布 crate 章节内容

发布到 crates.io

注意,发布时需要注意,发布是永久性的(permanent)。

对应版本不可能被覆盖,代码不能被删除。

  • 主要目的时保证所有项目的依赖都可以正常获取;

发布现存 crate 的新版本

通过修改 Cargo.toml 文件中的 version的值,

然后运行 cargo publish

从 crates.io 撤回版本

通过命令 cargo yank --vers <要撤回的版本号>

  • 注意,撤回并没有删除任何代码。撤回只是新项目不能依赖该版本,原有已经依赖的项目不受影响。

撤销撤回操作:

cargo yank --vers <之前撤回的版本号> --undo

Cargo 工作空间

随着项目的扩大,希望将原有的库 crate 拆分成多个库 crat。

这种情况使用 Cargo 提供的工作空间(workspaces)。

  • 它可以帮助我们管理多个相关的系统开发的包;

创建工作空间

工作空间 是一系列共享同样的 Cargo.lock 和输出目录的包。

有很多组织工作空间的方式,需要之后多学习。

先学习最常用的一种方式。

目录结构

共有内容:

  • Cargo.lock
  • target 结果目录

工作空间在顶级目录下有一个 target 目录,是所有 crate 共有的,不管在外面还是在子 crate 目录下编译都会将构建结果生成在顶级目录下的 target 目录中。

  • 这样避免单独在 crate 中编译生成构建结果导致的重复构建问题;

最外层 Carog.toml 文件内容,样例:

1
2
3
4
5
6
[workspace]

members = [
"adder",
"add-one",
]

目录结构样例:

1
2
3
4
5
6
7
8
9
10
11
├── Cargo.lock
├── Cargo.toml
├── add-one
│ ├── Cargo.toml
│ └── src
│ └── lib.rs
├── adder
│ ├── Cargo.toml
│ └── src
│ └── main.rs
└── target

工作空间中 crate 相互依赖

cargo 并不假设工作空间中的 crates 会相互依赖,所以需要明确表明工作空间中 crate 的依赖关系。

  • 在需要依赖其他库 crate 的 crate 中 Cargo.toml 文件的 [dependencies] 部分添加路径依赖

例如:

在上面给出的目录结构中,让 adder 依赖库crate add-one,需要在 adder/Cargo.toml中添加路径依赖

1
2
3
[dependencies]

add-one = { path = "../add-one"}

为了在顶层 add 目录运行二进制 crate,需要通过 -p 参数和包名称来运行 cargo run 指定工作空间中我们希望使用的包

1
2
3
4
$ cargo run -p adder
Finished dev [unoptimized + debuginfo] target(s) in 0.0 secs
Running `target/debug/adder`
Hello, world! 10 plus one is 11!

在工作空间中依赖外部 crate

工作空间中只在根目录有一个 Cargo.lock 文件,

  • 这保证了所有的 crate都使用完全相同版本的依赖。

但是,每个库crate 中依赖的外部 crate仅能在它自己项目中使用,不能在其他crate中使用,除非需要使用该依赖的crate也在它们的 Cargo.toml 文件中添加依赖声明。

解决:

如果工作空间中多个 crate 中需要使用相同的外部crate,那么可以在工作空间的顶级 Cargo.toml 中声明依赖

使用 Cargo install 从 crates.io安装二进制程序

cargo install 命令用于在本地安装和使用二进制 crate。

用于开发者们安装 crates.io 上共享的工具。

只有拥有二进制目标文件的crate 能够被安装。

  • 二进制目标文件,是在 crate 有 src/main.rs 或者其他指定为二进制文件时所创建的可执行程序。
    • 库crate 是自身不能执行但适合包含在其他程序中。

Cargo 自定义扩展命令

cargo --list 查看所有 cargo 可以使用的本地命令

开发依赖

当为编写测试引入依赖包时,仅希望该包在测试阶段使用,添加到 Cargo.toml 文件中的 [dev-dependencies]

还可以参考如下内容

Packaging and distributing a Rust tool - Command Line Applications in Rust (rust-cli.github.io)

  • 版权声明: 本博客所有文章除特别声明外,著作权归作者所有。转载请注明出处!
  • Copyrights © 2022-2023 ligongzhao
  • 访问人数: | 浏览次数:

请我喝杯咖啡吧~

支付宝
微信