Добавление и использование зависимости-крейта

RustBeginner
Практиковаться сейчас

Введение

В реальных программах на Rust часто используют специализированные библиотеки вместо того, чтобы реализовывать каждую возможность с нуля. Опубликованная библиотека Rust называется крэйтом, а крэйт, используемый вашим пакетом, — зависимостью. Безопасный выбор и добавление зависимостей — обычная часть разработки на Rust.

В этой лабораторной работе вы добавите анализатор командной строки clap в подготовленную программу приветствия. Вы внесёте два небольших изменения в исходный код, посмотрите на автоматически созданную справку и проверку аргументов, а также разберётесь, чем отличаются Cargo.toml и Cargo.lock. Зависимость предварительно загружена во время настройки, поэтому первая сборка будет быстрой, но добавить её в проект вам предстоит самостоятельно.

Добавление зависимости с помощью Cargo

На этом шаге вы добавите clap в подготовленный пакет и проверите изменение манифеста, которое Cargo внесёт за вас.

Проект находится в /home/labex/project/hello-cli. Перейдите в этот каталог перед выполнением команд Cargo:

cd /home/labex/project/hello-cli

Откройте манифест пакета в nano:

nano Cargo.toml

Cargo.toml описывает пакет и его прямые зависимости. Пустая таблица [dependencies] означает, что сейчас проект использует только стандартную библиотеку Rust. Нажмите Ctrl+X, чтобы выйти из nano, не изменяя файл.

Команда cargo add безопасно обновляет таблицу зависимостей. Добавьте clap версии 4.6.7 и включите его возможность derive:

cargo add clap@4.6.7 --features derive

Возможность включает необязательную часть крэйта. В данном случае derive включает макросы, которые превращают структуры и перечисления Rust в анализаторы командной строки. Cargo обозначает включённые возможности знаком +, а отключённые — знаком -; отключённые возможности не являются ошибкой.

Снова откройте манифест:

nano Cargo.toml

Теперь таблица зависимостей содержит строку такого вида:

clap = { version = "4.6.7", features = ["derive"] }

Версия задаёт требование совместимости. Cargo может выбрать более новый совместимый выпуск 4.x, а точные выбранные версии отдельно записываются в Cargo.lock. Нажмите Ctrl+X, чтобы закрыть nano.

Создание анализатора командной строки с помощью derive

На этом шаге вы свяжете структуру Cli с clap с помощью derive-макроса и метаданных команды.

Откройте подготовленный исходный файл:

nano src/main.rs

В вводном курсе вы уже использовали #[derive(Debug)]. Derive-макрос просит крэйт сгенерировать реализацию трейта на основе структуры типа. Замените первый комментарий TODO над struct Cli следующими двумя строками:

#[derive(Parser)]
#[command(version, about = "Create a friendly greeting")]

#[derive(Parser)] генерирует логику разбора аргументов. Атрибут #[command(...)] задаёт сведения обо всей команде: version получает версию пакета из Cargo.toml, а about задаёт краткое описание.

Сохраните файл с помощью Ctrl+O, нажмите Enter, затем выйдите с помощью Ctrl+X. Проверьте программу, не запуская её:

cargo check

При первой проверке компилируются clap и поддерживающие его крэйты, поэтому могут появиться несколько строк Compiling и Checking. Если последняя строка начинается с Finished, это означает, что зависимость и сгенерированный анализатор успешно скомпилировались вместе.

Теперь запросите справку программы. Разделитель -- отделяет параметры Cargo от аргументов вашей программы:

cargo run --quiet -- --help

В выводе будут описание, обязательное значение <NAME>, а также автоматически созданные параметры справки и версии:

Create a friendly greeting

Usage: hello-cli <NAME>
...

Вы задали структуру данных, а clap на её основе создал единообразную справку и проверку аргументов.

Добавление необязательного флага повторения

На этом шаге вы добавите типизированный параметр и используете его значение в небольшом цикле.

Сначала запустите команду с одним позиционным именем:

cargo run --quiet -- Ada
Hello, Ada!

name: String становится обязательным позиционным значением, потому что у него нет атрибута #[arg(...)]. Снова откройте исходный файл:

nano src/main.rs

Замените второй комментарий TODO внутри Cli следующим кодом:

    /// Number of greetings to print
    #[arg(short, long, default_value_t = 1)]
    times: u8,

Комментарий к полю становится текстом справки. short создаёт параметр -t, long — параметр --times, а default_value_t = 1 задаёт типизированное значение по умолчанию, если параметр не указан. Поскольку поле имеет тип u8, clap также отклоняет значения, которые не являются допустимыми 8-битными беззнаковыми целыми числами.

Замените последний комментарий TODO и единственную строку println! следующим кодом:

    for _ in 0..cli.times {
        println!("Hello, {}!", cli.name);
    }

Символ подчёркивания означает, что счётчик цикла намеренно не используется. Сохраните файл, выйдите из nano, затем запустите программу для вывода трёх приветствий:

cargo run --quiet -- Ada --times 3
Hello, Ada!
Hello, Ada!
Hello, Ada!

Также проверьте недопустимое значение:

cargo run --quiet -- Ada --times many

Эта команда должна завершиться ошибкой. clap выведет сообщение о том, что many не является допустимым значением u8, и завершит работу с ненулевым кодом до того, как main использует некорректное значение.

Проверка и повторное использование графа зависимостей из lock-файла

На этом шаге вы изучите разрешённый граф зависимостей Cargo и убедитесь, что lock-файл позволяет воспроизвести его без доступа к сети.

clap — ваша прямая зависимость, но сам он использует вспомогательные крэйты. Выведите первый уровень разрешённого графа:

cargo tree --depth 1

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

hello-cli v0.1.0 (...)
└── clap v4...

Откройте созданный lock-файл:

nano Cargo.lock

Cargo.lock содержит сгенерированные данные, поэтому обычно его не редактируют вручную. В нём записаны точные версии и контрольные суммы, выбранные Cargo для всего графа зависимостей. Для приложения вроде этого CLI храните lock-файл вместе с проектом, чтобы коллеги и автоматизированные сборки могли использовать то же разрешение зависимостей. Нажмите Ctrl+X, чтобы закрыть nano.

Теперь потребуйте использовать существующий lock-файл и локальный кэш крэйтов:

cargo check --locked --offline

Параметр --locked запрещает изменять Cargo.lock. Параметр --offline отключает доступ к сети. Последняя строка Finished подтверждает, что проект можно проверить с уже загруженным графом зависимостей, не выбирая незаметно другие версии.

Итоги

Вы добавили прямую зависимость-крэйт с помощью Cargo, включили необязательную возможность, создали типизированный анализатор clap с помощью derive и увидели автоматически созданные справку и проверку аргументов. Кроме того, вы отделили совместимое требование из Cargo.toml от точного графа зависимостей в Cargo.lock, а затем убедились, что этот граф работает в автономном режиме.