2016-05-15 14 views
0

前言:我相当确定这应该是一件容易理解的事情,但我没有任何运气。我实际上一直在与货运经理奋斗,我一直希望它像C中的简单include声明,但它当然没有那么简单。如果您对如何更好地构建此项目有所建议,请分享。使用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一个模块,就是circlepolygon模块都依赖于point(我不能想出一个办法让pointsat作为一个模块工作不重复代码,这与问题并不真正相关,但与惯用的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>); 

} 

回答

2

我不希望有包括point,因为它已经包含在sat

(重点煤矿)

这并不意味着什么。完全有可能(和所需的功能)您使用的包的版本可以是依赖项正在使用的包的不同版本。这允许您使用新版本的功能,而依赖项尚未更新(反之亦然)。这可以防止一个特定类型的“依赖地狱”。

不幸的是,它引入了另一一种依赖地狱的地方箱A的公共接口公开从箱B中的类型(1版),我们正在尝试使用板条箱上贴了与箱子B(第2版)的公共接口。这会产生一系列令人困惑的错误,如“预计Foo,发现Foo”。这些消息是actively worked on

要实现的关键是通过将外部类型放入公共API中,您的公共API现在受外部类型的影响。这意味着当外部箱子碰撞版本时,您需要碰撞版本以保持语义版本控制!

这后一种情况是你正试图选择进入。

你有两个选择:

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

第一个看起来是这样的:

点/ 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一起玩的箱子都做同样的事情。


我之所以包括点作为一个单独的库,而不是作为内饱和的模块,是,无论是circlepolygon模块取决于point。我无法想出一种方法来让point作为sat中的模块工作,而无需重复代码。

你应该弄清楚。包装箱是巨大的,当你有一块可重用的代码你当然应该使用它们,但它们不是重用代码的唯一方式

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)); 
}