Avatar ·

Как использовать локальный неопубликованный крейт в Rust?

Всем привет! Я только начал изучать Rust и пытаюсь структурировать свой проект. У меня есть основное приложение, и я хочу вынести часть общей логики (например, работу с API или утилиты) в отдельный крейт, чтобы использовать его в нескольких проектах. Проблема в том, что этот крейт ещё не готов для публикации на crates.io — это внутренняя библиотека, которую я хочу тестировать локально. Я создал папку `my_lib` рядом с основным проектом. Внутри неё лежит `Cargo.toml` и `src/lib.rs`. В `Cargo.toml` основного проекта я пробовал указать зависимость разными способами, но Cargo ругается. Вот пример структуры: ``` /workspace ├── main_project │ ├── Cargo.toml │ └── src │ └── main.rs └── my_lib ├── Cargo.toml └── src └── lib.rs ``` В `main_project/Cargo.toml` я пробовал: ```toml [dependencies] my_lib = { path = "../my_lib" } ``` Но получаю ошибку: `failed to select a version for the requirement 'my_lib = "^0.1.0"'`. Или я просто не понимаю, как правильно указывать версию. Также пробовал использовать `git =` с локальным путём, но это не сработало. Подскажите, как правильно подключить локальный крейт, который находится на диске, но не опубликован? Нужно ли его как-то регистрировать или достаточно правильного пути? И можно ли обновлять его код без пересборки основного проекта? Заранее спасибо за помощь! <<>>

Решение: используйте атрибут path в Cargo.toml

Вы почти всё сделали правильно. Ошибка возникает из-за того, что Cargo ожидает, что локальный крейт имеет указанную версию в своём Cargo.toml, но при использовании path версия не обязательна для совпадения. Проблема в том, что Cargo пытается разрешить версию, а у локального крейта может быть несовместимая версия или она не указана. Давайте исправим это.

Пошаговая инструкция

  1. Убедитесь, что в my_lib/Cargo.toml есть поле version
    Откройте my_lib/Cargo.toml и добавьте версию, например:
[package]
name = "my_lib"
version = "0.1.0"
edition = "2021"
  1. Укажите зависимость в основном проекте с помощью path
    В main_project/Cargo.toml напишите:
[dependencies]
my_lib = { path = "../my_lib" }

Обратите внимание: путь указывается относительно файла Cargo.toml основного проекта. Если ваш проект находится в /workspace/main_project, а крейт — в /workspace/my_lib, то путь ../my_lib корректен.

  1. Соберите проект
    Выполните cargo build в папке main_project. Cargo автоматически найдёт локальный крейт и соберёт его как часть зависимостей.

Проверка работоспособности

В my_lib/src/lib.rs определите простую функцию:

pub fn greet(name: &str) -> String {
    format!("Hello, {}!", name)
}

В main_project/src/main.rs используйте её:

use my_lib::greet;

fn main() {
    println!("{}", greet("Rust developer"));
}

После cargo run вы увидите Hello, Rust developer!.

Важные замечания

  • Версия не обязана совпадать — при использовании path Cargo игнорирует версию в секции [dependencies]. Убедитесь только, что версия указана в самом крейте.
  • Обновление кода крейта — если вы измените код в my_lib, просто пересоберите основной проект командой cargo build. Cargo сам перекомпилирует зависимость. Никаких дополнительных действий не требуется.
  • Рабочее пространство (workspace) — если вы планируете разрабатывать несколько крейтов вместе, рассмотрите использование Cargo Workspaces. Это упростит управление зависимостями и сборкой.
  • Отладка ошибок — если Cargo всё равно ругается, проверьте:
    • Правильность пути (используйте абсолютные пути для теста: path = "/home/user/workspace/my_lib").
    • Наличие Cargo.toml в папке крейта.
    • Отсутствие циклических зависимостей.

Таким образом, локальный неопубликованный крейт подключается просто и гибко. Вы можете свободно редактировать его код и сразу видеть изменения в основном проекте. Это идеально для разработки внутренних библиотек до их публикации.

<<>>

Альтернативный подход: использование Cargo Workspaces

Если вы планируете активно разрабатывать оба крейта (основной проект и библиотеку) одновременно, лучше организовать их как единое рабочее пространство (workspace). Это избавит от проблем с относительными путями и упростит сборку.

Как настроить workspace

Создайте в корневой папке workspace файл Cargo.toml (или используйте существующий) со следующим содержимым:

[workspace]
members = [
    "main_project",
    "my_lib",
]

Затем в main_project/Cargo.toml укажите зависимость так же, как и раньше:

[dependencies]
my_lib = { path = "../my_lib" }

Но теперь Cargo будет управлять всеми крейтами как единым целым. Выполняйте cargo build из корневой папки workspace, и Cargo соберёт все члены workspace.

Преимущества workspace

  • Единая команда сборки — cargo build из корня собирает всё сразу.
  • Общие зависимости — Cargo оптимизирует версии крейтов, чтобы избежать дублирования.
  • Удобство разработки — изменения в my_lib автоматически учитываются при сборке main_project.
  • Тестирование — можно запускать тесты для всех крейтов одной командой cargo test.

Этот подход особенно полезен для больших проектов, где несколько крейтов зависят друг от друга. Для простого случая с одним крейтом достаточно первого ответа, но workspace даёт больше гибкости в будущем.