Введение
В реальных программах на 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, а затем убедились, что этот граф работает в автономном режиме.


