前言:我很确定这应该很容易理解,但我没有运气。我实际上一直在与货运经理斗争,我一直希望它像include
中的简单C
陈述,但当然,这并不是那么简单。如果您对如何更好地构建此项目有意见,请分享它们。
假设我在Rust中有一个用Cargo管理的库。该包名为point
,目录如下所示。
point/
├── Cargo.lock
├── Cargo.toml
├── src
└── lib.rs
这个箱子没有依赖关系。
现在,我已经构建了另一个将使用此point
箱子的库。该库名为sat
。此库如下所示:
sat/
├── Cargo.lock
├── Cargo.toml
├── src
├── circle.rs
├── lib.rs
├── point/
└── polygon.rs
请注意point/
是上面提到的点目录。我将point
作为单独的库而非sat
中的模块包含在内的原因是circle
和polygon
模块都依赖于point
(我无法找到一种方法让point
在sat
中作为模块工作而不重复代码。这与问题无关,但与惯用的Rust库结构相关,所以感觉可以自由评论更好的方法来设置它。
以下是Cargo.toml
sat/
文件
$ 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> );
}
答案 0 :(得分:2)
我不想要包含
中point
crate ,因为它已包含在sat
(强调我的)
这并不意味着什么。完全可能(以及所需的功能)您使用的crate版本可能是依赖项所使用的crate的不同版本。这允许您在依赖项尚未更新时使用较新版本的功能(反之亦然)。这可以防止一种特定类型的“依赖地狱”。
不幸的是,它引入了另一种类依赖地狱,其中crate A的公共接口暴露了来自crate B(版本1)的类型,我们正在尝试使用crate A的公共接口与crate B(版本2)。这会产生一系列令人困惑的错误,例如“预期Foo
,找到Foo
”。这些消息是actively worked on。
要实现的关键是通过在公共API中添加外部类型,您的公共API现在受外部类型的影响。这意味着当外部包装箱碰到版本时,您需要碰撞您的版本以保持语义版本控制!
后一种情况是您试图加入的。
您有两种选择:
第一个看起来像这样:
<强>点/ 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);
应用/ SRC / main.rs 强>
extern crate sat;
use sat::{Point, Circle};
fn main() {
let p = Point(0, 0);
let c = Circle(p);
}
这可能是你最接近你想要的。否则,您需要将依赖包添加到sat
和app
。这并非闻所未闻,与hyper
一起玩的大多数板条箱都做同样的事情。
我将point作为单独的库而不是sat中的模块包含的原因是
circle
和polygon
模块都依赖于point
。我无法找到让point
作为sat
中的模块工作而无需重复代码的方法。
你应该弄清楚这一点。 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));
}