使用Cargo

时间:2016-05-15 23:50:36

标签: rust rust-cargo

前言:我很确定这应该很容易理解,但我没有运气。我实际上一直在与货运经理斗争,我一直希望它像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中的模块包含在内的原因是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> );

}

1 个答案:

答案 0 :(得分:2)

  

我不想要包含point crate ,因为它已包含在sat

(强调我的)

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

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

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

后一种情况是您试图加入的。

您有两种选择:

  1. Re-export the types you need
  2. 人们需要使用相同的箱子和相同版本的文件。
  3. 第一个看起来像这样:

    <强>点/ 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);
    }
    

    这可能是你最接近你想要的。否则,您需要将依赖包添加到satapp。这并非闻所未闻,与hyper一起玩的大多数板条箱都做同样的事情。

      

    我将point作为单独的库而不是sat中的模块包含的原因是circlepolygon模块都依赖于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));
    }