为什么我们需要在 Rust 中指定所有依赖项(包括传递项)?

sif*_*ify 2 rust rust-cargo

例如,我的项目依赖于 crate A,A 依赖于 B,那么我的项目不能使用 crate B,直到我将 B 放入我项目的 Cargo.toml 的依赖项部分。

在java中如果使用maven或者gradle,可以直接使用B,不需要在pom.xml或者build.gradle中声明。为什么货物不走这条路?

Alo*_*oso 9

原因是semver兼容性。

例如,假设您的 crate 依赖于版本为 1.0 的A,而依赖于版本为 1.0 的B

your_crate  -->  A 1.0  -->  B 1.0
Run Code Online (Sandbox Code Playgroud)
  • 现在,B发布了与 1.0 版不兼容的新 2.0 版。
  • A升级到B版本 2.0 并发布次要版本 1.1。此版本与 1.0 兼容,即使其依赖项不兼容。
  • 您升级到A版本 1.1。
your_crate  -->  A 1.1  -->  B 2.0
Run Code Online (Sandbox Code Playgroud)

问题是,如果您能够以传递方式访问依赖项,您的代码就会中断,因为B 2.0 与B 1.0不兼容。


对此有两种解决方案:

  1. A的维护者可以重新导出B 中的所有内容:

    // crate a
    pub use b;
    
    Run Code Online (Sandbox Code Playgroud)

    就像在 Java 中一样,这允许您访问传递依赖项B 的项

    // your crate
    use a::b;
    
    Run Code Online (Sandbox Code Playgroud)

    但是,这意味着A不能发布在B中包含主要版本碰撞的次要版本。所以当B发布 2.0 版本时,A也必须发布一个新的主要版本。

  2. 你也可以依赖B。这意味着 Cargo 将尝试选择满足A和您的 crate要求的B版本。如果不能,则包含多个版本的B

    your_crate  -->  A 1.1  -->  B 2.0
                -->  B 1.0
    
    Run Code Online (Sandbox Code Playgroud)