Cargo使用文档-指定依赖项

原文链接:http://doc.crates.io/specifying-dependencies.html#platform-specific-dependencies

你的crates可以依赖于其他的库:

1.crates.io

2.git库

3.本地文件系统的子目录

也可以临时覆盖依赖项的位置-比如说,这样就能够测试你的工作内容的依赖项的BUG修复。你可以对不同的平台有不同的依赖项,以及只在开发期间使用的依赖项。

一、从crates.io指定依赖项

Cargo被设计为默认会从crates.io上搜寻依赖项。在这种方式下,只需要指定一个库名称和版本号,比如:

[dependencies]
time = "0.1.12"

字符串"0.1.12"要求是语义化标准版本(SemVer),因为这种字符串没有运算符,

^符号(Caret requirements)

^符号允许以SemVer兼容方式升级到指定版本。只要新的版本号主要,次要,补丁组中最左边非零数字不被修改,这个升级就是被允许的,在这种情况下,如果我们运行

cargo update -p time

如果这个版本可用的话,cargo将会帮我们把time库升级到0.1.13,而绝不会升级到0.2.0,如果我们以^1.0方式指定版本,将会升级到1.1版本但是不会升级到2.0.0.0.x。

~符号(Tilde requirements)

~指定了一个可以更新的最小版本。比如,如果你指定了一个主.次.补丁版本或者主.次版本,那么只能允许补丁级别的版本更改。如果只指定了主版本,那么可以允许次版本和补丁版本的升级。

eg:

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

 *符号(Wildcard)

*允许它所在位置的任意版本的升级

eg:

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

>、<符号(Inequality)

二、从git仓库指定依赖

为了使用一个在git仓库上的库,你需要提供的最小信息是用git关键字指定的仓库地址

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

Cargo将从这个位置去适配git仓库,然后到git仓库任意位置(不一定需要在git仓库的根目录下)中查找Cargo.toml文件,从中查找到所有需要的crates。

因为我们没有指定任何其他的信息,Cargo会假定我们使用的是master分支的最近一次提交的内容,来构建我们的工程。我们可以把git关键字与rev,tag,或者branch关键字结合来指定其他信息。下面是一个指定使用next分支上最近内容的例子:

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

三、指定依赖路径

随时间的推移, 我们的hello_world工程的规模已经大大的增加,已经到了我们该分割成一个单独的crate来提供给他人使用的时候了。Cargo允许通过指定依赖路径来做到这一点,通常是在一个库内的子crates,让我们从在hello_world工程中创建一个新的crate开始:

$ cd hello_world/
$ cargo new hello_utils

以上将创建一个新的hello_utils目录(它的cargo.toml和src文件夹已经配置好),为了告诉Cargo这些,打开hello_world/Cargo.toml文件,将hello_utils添加到你的依赖中:

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

这将告诉Cargo我们的hello_world工程依赖一个叫hello_utils的crate,这个crate可以在hello_utils目录下找到(依据我们在Cargo.toml中写入的内容)。

这就是所有我们要做的,下次执行cargo build命令的时候,将会自动构建hello_utils和它所有的依赖项,而且其他工程也可以开始使用这个crate了。然而,在crates.io中,不允许使用仅指定路径的依赖项。如果我们想要发布我们的hello_world crate,我们需要先发布一个hello_utils的版本到crates.io上(或者指定一个git仓库位置),并且也要在依赖行中指定它的版本:

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

 

覆盖依赖项(Overriding dependencies)

在Cargo中有多种方式来支持覆盖依赖项,并控制依赖图。不过,这些选项通常只能在工作空间级别适用,并且不能通过依赖关系传播。换句话说,"应用程序"可以覆盖依赖项,而"库"不行。

在很多场景中,都有要覆盖依赖项,或者以其他方式改变依赖项的需要。然而,他们中的大多数都归结于在被发表到crates.io之前,有能力使用crate。例如:

  • 一个你正在开发中的crate也被一个你在开发中的更大的应用程序所使用,并且你将要在那个更大的应用中测试一个在crate中的BUG。
  • 一个上游crate有一个新特性,或者在其git存储库的主分支上要修复BUG,你希望测试它。
  • 你将要为你的crate发布一个新的主版本,但是你希望在整个项目中进行集成测试,以确保新的主要版本能够工作。
  • 你已经为一个上游crate中发现的BUG提交啦一个修复程序,但是你想要立刻在你的应用程序中依赖这个已经修复BUG的版本,以避免被已经合并的BUG给阻塞(影响)。

这些目前都是通过[patch] manifest部分解决的。要注意的是,[patch]特征目前还没有稳定而且将要在2017-08-31发布。在Rust历史里,有些应用场景已经通过[replace]部分解决了,但是我们将在这里记录[patch]部分。

测试一个BUG修复(Testing a bugfix)

假设你正在使用[uuid] crate,但是在你使用的时候,发现了一个BUG。你是相当有进取心的,所以你决定也试着取修复这个BUG,最初你的配置中会这样写:

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

[dependencies]
uuid = "0.1.0"

我们首先会克隆uuid仓库到本地,通过一下命令:

$ git clone https://github.com/rust-lang-nursery/uuid

然后,我们编辑my-library的配置文件:

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

这里我们声明我们正在修补源crates.io的一个新的依赖项。这将为我们的本地工程有效的将uuid的的本地检出版本添加到crates.io注册表。

然后,我们需要确信我们的锁文件(Cargo.lock)被更新到可以使用uuid的这个新版本,这样我们的工程会使用位于本地的检出版本,而不是一个crates.io上的版本。

[patch]的工作方式是它将加载位于../path/to/uuid的依赖项并且当crates.io????。

这意味着本地检出的版本很重要,并且会影响补丁是否会被使用。我们的配置里声明uuid = "1.0",这意味着我们只会使用>=1.0.0,<2.0.0版本,并且Cargo的贪心算法也意外着我们将解析到该范围内的最大版本。通常情况下,这并不重要,因为git仓库的版本将会更大,或者匹配发布到crates.io上的最大版本,但是记住这一点很重要。

在任何情况下,通常所有你需要做的是:

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

就是这样,现在,你在使用uuid的本地版本构建工程(留意在这次构建输出下的这个file://)。如果你没有看到file://的版本正在构建,那么你可能需要运行: cargo update -p uuid --precise $version,这里$version是本地检出的uuid拷贝的版本。

一旦你修复了BUG,你会发现下一件你要做的事情很可能是将其提交给uuid crate。一旦你做完这些你就可以更新[patch]部分。[patch]列下的部分类似[dependencies]部分,因此一旦你的提交请求被合并,你可以改变你的依赖路径为:

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

处理一个未发布的小版本(Working with an unpublished minor version)

现在,让我们从处理BUG修复到添加功能。在开发my-library的时候,你发现在uuid crate中需要一个全新的特性。你已经实现了这个特性,使用[patch]在本地测试过,并且提交了一个请求。让我们看看在它实际发布之前,如何继续使用并测试它。

(未完待续...)

posted @ 2017-08-18 17:26  MaybeDog  阅读(4636)  评论(0编辑  收藏  举报