这是什么意思?“这正是因为不应该为库的所有用户确定性地重新编译库。”

sti*_*ing 3 version-control rust rust-cargo

我是 Rust 新手,正在尝试了解 Cargo 的事情。我在他们的常见问题解答中读到“为什么二进制文件在版本控制中具有 Cargo.lock,而不是库?” 但不明白这是什么意思。

\n

“依赖该库的用户不会检查库\xe2\x80\x99s Cargo.lock(即使它存在)。这正是因为不应该为库的所有用户确定性地重新编译库。

\n

如果一个库最终被多个依赖项传递使用,则很可能只需要该库的单个副本(基于 semver 兼容性)。如果 Cargo 使用了所有依赖项的 Cargo.lock 文件,则可以使用该库的多个副本,甚至可能会出现版本冲突。”

\n

如果有人能解释这一点,我们将不胜感激。谢谢。

\n

Dre*_*acy 6

假设我们有以下箱子:

  • string-tools:这是某种常用的库,导出一个FastString结构,可以更快地实现一些常用功能。该库有两个版本:1.0.1 和 1.0.2。1.0.2 版本最近发布。
  • database:与您最喜欢的数据库交互的库。它需要进行一些字符串处理,因此它使用该string-tools库。中的公共方法之一database具有如下签名:
    fn get_username(id: u64) -> string_tools::FastString
    
    Run Code Online (Sandbox Code Playgroud) 该库没有机会或需要更新到 1.0.2 版本string-tools- 也许它不受补丁中修复的任何错误的影响。因此,Cargo.lock 将版本固定string-tools为 1.0.1。
  • client:该库用于与客户端交互。它还依赖于string-tools, 并且有一个这样的方法:
    fn show_name(name: string_tools::FastString)
    
    Run Code Online (Sandbox Code Playgroud) 该库使用的是最新版本string-tools,版本 1.0.2。这也是 Cargo.lock 中的版本。

您想编写一个使用databaseclient库的网站。当您构建项目时,Cargo 会使用 Cargo.lock 中指定的版本来编译每个库的依赖项。这意味着database使用版本 1.0.1string-toolsclient使用版本 1.0.2。但现在想象一下您已经编写了一些如下代码:

client::show_name(database::get_username(id));
Run Code Online (Sandbox Code Playgroud)

应该可以编译。毕竟,该get_username函数返回一个string_tools::FastStringshow_name函数接受的 a 。但事实并非如此!这是因为FastString返回的get_username来自 1.0.1 版本string_tools,而show_name想要FastString1.0.2 版本!这是行不通的;毕竟,当string-tools编写 1.0.2 版本的补丁时,作者可能会向该类型添加一个附加字段。编译器没有什么合理的事情可以做。

通过让 Cargo 忽略库上的 Cargo.lock 文件可以避免此类问题。相反,它所做的是针对 1.0.2 版本编译database和。这是正确的,因为 1.0.1 和 1.0.2 是“semver 兼容版本”。这意味着可以将其中一个更改为另一个,但事情仍然必须编译。现在您不再收到编译器错误,因为一个函数返回的类型和另一个函数接受的类型不再不同。clientstring_tools