我对 Rust 相当陌生,正在尝试了解如何最好地创建可重用的共享库组件。我有一个名为 rust-libs 的 github 存储库,它被设置为货物工作区。该存储库的项目树如下所示:
├── Cargo.lock
├── Cargo.toml
├── describable
│ ├── Cargo.toml
│ └── src
│ ├── describable.rs
│ └── lib.rs
└── health_check
├── Cargo.toml
└── src
├── health_check.rs
└── lib.rs
顶级 Cargo.toml 文件包含:
[workspace]
members = [
"describable",
"health_check"
]
每个成员中的 Cargo.toml 文件仅定义该成员及其版本的依赖关系 - 例如可描述/Cargo.toml:
[package]
name = "lib_describable"
version = "1.0.0"
authors = ["my-name <[email protected]>"]
edition = "2018"
[lib]
name = "lib_describable"
path = "src/lib.rs"
和health_check/Cargo.toml:
[package]
name = "lib_health_check"
version = "1.0.0"
authors = ["my-name <[email protected]>"]
edition = "2018"
[dependencies]
lib_describable = { path = "../describable" }
[lib]
name = "lib_health_check"
path = "src/lib.rs"
请注意,我使用 lib_ 前缀命名该库,只是为了避免与其他 Rust 库发生任何冲突。 每个工作区成员中的
lib.rs 文件仅定义我想要导出的公共模块 - 例如可描述/src/lib.rs:
pub mod describable;
其实现位于describable/src/describable.rs
:
pub trait Describable {
fn describe(&self) -> String;
}
中的实现是:
use lib_describable::describable::Describable;
pub trait HealthCheckable: Describable {
fn check_health(&mut self) -> Result<(), String>;
}
对特定成员进行任何更改时,我总是在其Cargo.toml
文件中更新其版本号。 CircleCI 用于自动构建此存储库。如果构建成功,则 CircleCI 作业会使用多个 git 标签(工作区中的每个成员一个)来标记此存储库,这些标签的形式为 <member-name>_<member-version-from-its-cargo-toml>_<git-short-commit-sha>
,例如对于上述两个成员,它可能会使用这些标签来标记构建:
describable_1.0.0_d2db9ff
health_check_1.0.0_d2db9ff
然后我有一个单独的 git 存储库,其中包含一个使用这些共享库成员构建的 Rust 二进制文件。该项目在其Config.toml
中引用共享库成员,如下所示:
...
[dependencies]
...
lib_describable = { git = "ssh://[email protected]/xxx/rust-libs.git", tag = "describable_1.0.0_d2db9ff" }
lib_health_check = { git = "ssh://[email protected]/xxx/rust-libs.git", tag = "health_check_1.0.0_d2db9ff" }
...
[[bin]]
name = "my-app"
path = "src/bin/main.rs"
只是我的github帐户的混淆名称。该项目中的文件 src/bin/main.rs 包含以下形式的代码:
extern crate lib_describable;
extern crate lib_health_check;
use lib_describable::describable::Describable;
use lib_health_check::health_check::HealthCheckable;
pub trait MyDb: Describable + HealthCheckable {
// some functions defined here that are not important for this issue
}
pub struct MySpecialDb { ... }
impl Describable for MySpecialDb {
fn describe(&self) -> String {
// returns a description of this DB
}
}
impl HealthCheckable for MySpecialDb {
fn check_health(&mut self) -> Result<(), String> {
// performs some health check specific to this DB and returns either Ok(()) if its healthy or Err("...some error message...") if it is unhealthy
}
}
impl MyDb for MySpecialDb { ... }
我发现的问题是 rust 编译器似乎不喜欢impl HealthCheckable for MySpecialDb
行并报告以下形式的错误:
the trait bound `...::MySpecialDb: lib_describable::describable::Describable` is not satisfied
the trait `lib_describable::describable::Describable` is not implemented for `...::MySpecialDb`
note: perhaps two different versions of crate `lib_describable` are being used?rustc(E0277)
是否有明显的事情表明我在这里做错了导致此错误?