Как использовать локальный неопубликованный крейт (crate) в Rust?
Правильный способ подключения локального крейта через путь
Ваша основная идея верна — использование path в Cargo.toml — это стандартный способ подключения локального неопубликованного крейта. Однако ошибка возникает из-за того, что Cargo не может найти крейт по указанному пути. Давайте разберёмся по шагам.
Шаг 1: Проверьте структуру папок
Убедитесь, что путь в path указан относительно файла Cargo.toml, который его содержит. В вашем случае ../my_lib означает «подняться на уровень выше и войти в папку my_lib». Если структура именно такая, как вы описали, путь корректен. Но часто начинающие путают относительные пути — попробуйте указать абсолютный путь для проверки:
[dependencies]
my_lib = { path = "/полный/путь/до/my_lib" }
Если это сработает, значит проблема именно в относительном пути. Рекомендую использовать относительные пути, но проверьте, что вы запускаете cargo build именно из папки my_app.
Шаг 2: Убедитесь, что крейт — библиотека
Ваш my_lib должен быть библиотекой (lib), а не исполняемым файлом (bin). В my_lib/Cargo.toml не должно быть секции [[bin]], а в src/lib.rs — функции main. Если вы случайно создали бинарный крейт, добавьте в Cargo.toml:
[lib]
name = "my_lib"
path = "src/lib.rs"
Или просто переименуйте src/main.rs в src/lib.rs.
Шаг 3: Правильная структура проекта (рекомендуемый способ)
Лучшая практика для Rust-проектов с локальными зависимостями — использовать workspace. Это позволяет управлять несколькими крейтами в одном репозитории. Создайте корневой Cargo.toml:
[workspace]
members = [
"my_lib",
"my_app",
]
Теперь переместите папки my_lib и my_app внутрь корневой директории проекта. В my_app/Cargo.toml зависимость будет выглядеть так:
[dependencies]
my_lib = { path = "../my_lib" } # относительно my_app
Или, если вы используете workspace, можно указать просто имя крейта, и Cargo сам найдёт его среди членов workspace:
[dependencies]
my_lib = { path = "../my_lib" } # всё ещё работает, но можно и без path, если крейт опубликован
Шаг 4: Проверьте версию и имя крейта
Убедитесь, что в my_lib/Cargo.toml поле name совпадает с тем, что вы указываете в зависимости. Регистр важен: my_lib и My_Lib — разные имена. Также проверьте, что версия указана (хотя для локальных путей это не обязательно).
Полный пример рабочей конфигурации
my_lib/Cargo.toml:
[package]
name = "my_lib"
version = "0.1.0"
edition = "2021"
[lib]
name = "my_lib"
path = "src/lib.rs"
my_lib/src/lib.rs:
pub fn greet(name: &str) -> String {
format!("Hello, {}!", name)
}
my_app/Cargo.toml:
[package]
name = "my_app"
version = "0.1.0"
edition = "2021"
[dependencies]
my_lib = { path = "../my_lib" }
my_app/src/main.rs:
use my_lib::greet;
fn main() {
println!("{}", greet("Rust developer"));
}
Что ещё стоит знать?
- Отладка: Запустите
cargo build -v(verbose), чтобы увидеть, какие пути ищет Cargo. - Кэш: Иногда помогает
cargo cleanи повторная сборка. - Git: Если вы используете git, не забудьте добавить
Cargo.lockв репозиторий для воспроизводимости сборок. - Публикация: Когда крейт будет готов, вы сможете легко переключиться с
pathна версию из crates.io, просто заменив зависимость наmy_lib = "0.1.0".
Надеюсь, это поможет! Если ошибка остаётся — проверьте права доступа к папке my_lib и убедитесь, что в ней есть Cargo.toml.
Альтернативный подход: использование git-зависимости
Если вы не хотите использовать workspace или относительные пути (например, когда проект хранится в разных репозиториях), можно подключить локальный крейт через git. Для этого инициализируйте git-репозиторий в папке my_lib и сделайте хотя бы один коммит. Затем в my_app/Cargo.toml укажите:
[dependencies]
my_lib = { git = "file:///полный/путь/до/my_lib" }
Обратите внимание на file:// — это указывает Cargo на локальный git-репозиторий. Преимущество этого метода в том, что вы можете указывать конкретные ветки, теги или коммиты:
my_lib = { git = "file:///путь/до/my_lib", branch = "dev" }
Недостаток — нужно постоянно коммитить изменения в my_lib, чтобы они подтягивались в my_app. Для быстрой разработки это неудобно, но для изолированных проектов или CI/CD может быть полезно.
Также помните: если вы используете git-зависимость, Cargo будет клонировать репозиторий каждый раз при сборке, если не закеширует его. Для локальной разработки путь через path или workspace всё же предпочтительнее.