#rust #rust-cargo #lib
#Ржавчина #rust-cargo #библиотека
Вопрос:
Я довольно новичок в rust и пытаюсь понять, как лучше всего создавать повторно используемые компоненты разделяемой библиотеки. У меня есть репозиторий github с именем rust-libs, который настроен как грузовое рабочее пространство. Дерево проекта для этого репозитория выглядит следующим образом:
├── 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 в каждом элементе просто определяет зависимости этого элемента и его версию — например, describable/Cargo.toml:
[package]
name = "lib_describable"
version = "1.0.0"
authors = ["my-name <me@email.com>"]
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 <me@email.com>"]
edition = "2018"
[dependencies]
lib_describable = { path = "../describable" }
[lib]
name = "lib_health_check"
path = "src/lib.rs"
Обратите внимание, что я называю библиотеку префиксом lib_, чтобы избежать каких-либо столкновений с другими библиотеками rust.
The lib.rs файл в каждом элементе рабочей области просто определяет общедоступные модули, которые я хочу экспортировать — например, describable/src/lib.rs:
pub mod describable;
Реализация для этого находится в describable/src/describable.rs:
pub trait Describable {
fn describe(amp;self) -> String;
}
Реализация в health_check/ src /health_check.rs:
use lib_describable::describable::Describable;
pub trait HealthCheckable: Describable {
fn check_health(amp;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://git@github.com/xxx/rust-libs.git", tag = "describable_1.0.0_d2db9ff" }
lib_health_check = { git = "ssh://git@github.com/xxx/rust-libs.git", tag = "health_check_1.0.0_d2db9ff" }
...
[[bin]]
name = "my-app"
path = "src/bin/main.rs"
xxx — это просто запутанное имя моей учетной записи на 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(amp;self) -> String {
// returns a description of this DB
}
}
impl HealthCheckable for MySpecialDb {
fn check_health(amp;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, похоже, не нравится строка implementcheckable для 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)
Есть ли что-то очевидное, что я делаю неправильно, чтобы вызвать эту ошибку?
Комментарии:
1. Я почти уверен, что cargo думает
lib_describable(git)
иначе, чемlib_health_check(git) -> lib_describable(path)
, возможно, вы сможете переопределить зависимости, чтобы привести их в соответствие2. @kmdreko В этом разделе документации описывается, как вносить исправления в другие версии ящика. Я тоже не мог заставить это сработать в моем сценарии. Был бы очень признателен, если бы вы могли, пожалуйста, набросать, как это исправить.
Ответ №1:
К сожалению, похоже, что это не поддерживаемая конфигурация в Cargo, как видно из ответов, которые я получил по вопросу, который я поднял здесь: https://github.com/rust-lang/cargo/issues/8956
Поэтому я преобразовал свое репозиторий рабочей области в репозиторий грузовой библиотеки, где все мои библиотеки теперь имеют одну версию.