Cargo.toml 与 Cargo.lock
Cargo.toml
和 Cargo.lock
用于两个不同的目的。在我们讨论它们之前,这里有一个总结
Cargo.toml
用于以广义的方式描述您的依赖项,由您编写。Cargo.lock
包含有关您的依赖项的确切信息。它由 Cargo 维护,不应手动编辑。
如有疑问,请将 Cargo.lock
提交到版本控制系统(例如 Git)。有关原因和替代方案的更多信息,请参阅常见问题解答中的“为什么要在版本控制中使用 Cargo.lock?”。我们建议将其与验证最新依赖项配对使用
让我们更深入地研究一下。
Cargo.toml
是一个清单文件,我们可以在其中指定有关包的大量不同元数据。例如,我们可以说我们依赖于另一个包
[package]
name = "hello_world"
version = "0.1.0"
[dependencies]
regex = { git = "https://github.com/rust-lang/regex.git" }
此包对 regex
库有一个依赖项。在这种情况下,我们声明我们依赖于 GitHub 上的特定 Git 存储库。由于我们没有指定任何其他信息,因此 Cargo 假定我们打算使用默认分支上的最新提交来构建我们的包。
听起来不错?好吧,有一个问题:如果您今天构建此包,然后将其发送给我,而我明天构建此包,则可能会发生不好的事情。在此期间,regex
可能会有更多提交,我的构建将包含新提交,而您的构建则不会。因此,我们将获得不同的构建。这很糟糕,因为我们希望构建是可重现的。
我们可以通过在 Cargo.toml
中定义特定的 rev
值来解决此问题,以便 Cargo 在构建包时确切知道要使用哪个版本
[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 将获取最新的提交,并在我们第一次构建时将该信息写入我们的 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"
您可以看到这里有更多信息,包括我们用来构建的确切版本。现在,当您将包交给其他人时,即使我们没有在 Cargo.toml
中指定,他们也会使用完全相同的 SHA。
当我们准备好选择新版本的库时,Cargo 可以重新计算依赖项并为我们更新
$ cargo update # updates all dependencies
$ cargo update regex # updates just “regex”
这将写出一个新的 Cargo.lock
,其中包含新的版本信息。请注意,cargo update
的参数实际上是一个包 ID 规范,而 regex
只是一个简短的规范。