gpt4 book ai didi

rust - 使用 Cargo 使较低级别的 crate 在顶部可用

转载 作者:行者123 更新时间:2023-11-29 08:27:36 25 4
gpt4 key购买 nike

前言:我相当确定这应该很容易弄清楚,但我没有任何运气。实际上,我一直在与 Cargo 管理器作斗争,我一直希望它像 C 中的一个简单的 include 语句一样,但它当然不是这样简单的。如果您对总体上如何更好地构建此项目有任何意见,请分享。

假设我有一个用 Cargo 管理的 Rust 库。该箱名为 point,目录如下所示。

point/
├── Cargo.lock
├── Cargo.toml
├── src
   └── lib.rs

这个箱子没有依赖关系。

现在,我已经构建了另一个库,它将使用这个point crate。这个库叫做 sat 这个库看起来像这样:

sat/
├── Cargo.lock
├── Cargo.toml
├── src
   ├── circle.rs
   ├── lib.rs
   ├── point/
   └── polygon.rs

注意point/就是上面说的point目录。我之所以将 point 作为一个单独的库,而不是作为 sat 中的一个模块,是因为 circlepolygon 模块依赖于 point(我想不出一种方法让 pointsat 中作为一个模块工作而无需重复代码. 这与问题并不真正相关,但与惯用的 Rust 库结构相关,所以请随意评论更好的设置方法)。

这是 sat/Cargo.toml 文件

$ cat sat/Cargo.toml 
[package]
name = "sat"
version = "0.1.0"

[dependencies]
point = { path = "src/point" }

现在,这一切都很好。但是,假设我想创建一个使用 sat 作为外部包装箱的应用程序。 如何在不包含 point 库本身的情况下访问此应用程序中的 point 库?

这是一个例子,point 库中有一个名为Point 的结构。 sat 库中有一个名为 Circle 的结构。假设我的示例源代码如下所示:

$ cat src/main.rs

extern crate sat;

// I don't want to have to include the point crate because it is already
// included in sat
// extern crate point;

fn main() {

// declare a polygon
// structure is: crate::module::struct::staticFunction
let polygon = sat::polygon::Polygon::new( <parameters> );

// I cannot declare a Point, because point is not a module in sat
// this errors out.
// However, this is the sort of thing that I would like to do.
let point = sat::point::Point::new( <parameters> );

}

最佳答案

I don't want to have to include the point crate because it is already included in sat

(强调我的)

这实际上没有任何意义。您使用的 crate 版本完全有可能(和所需的功能)是依赖项正在使用的 crate 的不同版本。这允许您在依赖项尚未更新时使用较新版本的功能(反之亦然)。这可以防止一种特定类型的“依赖 hell ”。

不幸的是,它引入了另一种依赖 hell ,其中 crate A 的公共(public)接口(interface)暴露了 crate B(版本 1)的类型,我们试图将 crate A 的公共(public)接口(interface)与 crate B 一起使用(版本 2)。这会产生一系列令人困惑的错误,例如“预期的 Foo,找到的 Foo”。这些消息正在 actively worked on .

要认识到的关键是,通过在您的公共(public) API 中放置外部类型,您的公共(public) API 现在会受到外部类型的影响。这意味着当外部 crate 更新版本时,您需要更新您的版本以维护语义版本控制!

后一种情况是您尝试选择加入的情况。

你有两个选择:

  1. Re-export the types you need .
  2. 人们需要使用同一个 crate 和同一个版本的文档。

第一个看起来像这样:

指向/src/lib.rs

pub struct Point(pub u8, pub u8);

sat/src/lib.rs

extern crate point;

pub use point::Point;

pub struct Circle(pub point::Point);

app/src/main.rs

extern crate sat;

use sat::{Point, Circle};

fn main() {
let p = Point(0, 0);
let c = Circle(p);
}

这可能是最接近您要查找的内容。否则,您需要显式地将依赖包添加到 satapp 中。这并非闻所未闻,大多数使用 hyper 的 crate 都做同样的事情。


The reason I included point as a separate library, instead of as a module within sat, is that both the circle and polygon modules depend on point. I couldn't figure out a way to get point to work as a module in sat without repeating code.

你或许应该明白这一点。 Crates 很棒,当你有一段可重用的代码时,你当然应该使用它们,但它们不是重用代码的唯一方式:

pub mod point {
pub struct Point(pub u8, pub u8);
}

pub mod square {
use point::Point;

pub struct Square(pub Point, pub Point);
}

pub mod circle {
use point::Point;

pub struct Circle(pub Point);
}

fn main() {
let c = circle::Circle(point::Point(0, 0));
let s = square::Square(point::Point(0, 0), point::Point(1, 1));
}

关于rust - 使用 Cargo 使较低级别的 crate 在顶部可用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37244888/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com