Привет, Cargo!
Cargo — это система сборки и менеджер пакетов Rust. Большинство Rustacean используют этот инструмент для управления своими проектами на Rust, поскольку Cargo берёт на себя множество задач, таких как сборка вашего кода, загрузка библиотек, от которых зависит код, и сборка этих библиотек. (Библиотеки, которые требуются вашему коду, называются зависимостями.)
Простейшие программы Rust, подобные той, что мы писали до этого, не имеют зависимостей. Если бы мы создавали проект «Hello, world!» с использованием Cargo, использовалась бы только часть Cargo, отвечающая за сборку кода. Однако по мере написания более сложных программ вы начнёте добавлять зависимости, и если проект изначально создан с использованием Cargo, добавление зависимостей будет значительно проще.
Поскольку подавляющее большинство проектов Rust использует Cargo, оставшаяся часть этой книги предполагает, что вы также используете Cargo. Cargo устанавливается вместе с Rust, если вы использовали официальные установщики, описанные в разделе «Установка». Если вы устанавливали Rust другим способом, проверьте наличие Cargo, выполнив в терминале следующую команду:
$ cargo --version
Если вы видите номер версии, значит Cargo установлен! Если появляется ошибка,
например command not found, обратитесь к документации используемого метода
установки, чтобы узнать, как установить Cargo отдельно.
Создание проекта с помощью Cargo
Давайте создадим новый проект с использованием Cargo и посмотрим, чем он отличается от нашего первоначального проекта «Hello, world!». Вернитесь в каталог projects (или туда, где вы решили хранить код). Затем в любой операционной системе выполните:
$ cargo new hello_cargo
$ cd hello_cargo
Первая команда создаёт новый каталог и проект с именем hello_cargo. Мы назвали проект hello_cargo, а Cargo создаёт свои файлы в каталоге с таким же именем.
Перейдите в каталог hello_cargo и выведите список файлов. Вы увидите, что Cargo сгенерировал два файла и один каталог: файл Cargo.toml и каталог src, содержащий файл main.rs.
Cargo также инициализировал новый Git-репозиторий вместе с файлом
.gitignore. Git-файлы не будут созданы, если cargo new выполняется
внутри уже существующего Git-репозитория; это поведение можно изменить,
используя cargo new --vcs=git.
Примечание: Git является распространённой системой контроля версий. Вы можете изменить
cargo new, чтобы использовать другую систему контроля версий или не использовать её вовсе, применяя флаг--vcs. Выполнитеcargo new --help, чтобы увидеть доступные параметры.
Откройте Cargo.toml в предпочитаемом вами текстовом редакторе. Он должен выглядеть примерно так, как показано в листинге 1-2.
[package]
name = "hello_cargo"
version = "0.1.0"
edition = "2024"
[dependencies]
cargo newЭтот файл использует формат TOML (Tom’s Obvious, Minimal Language), который является форматом конфигурации Cargo.
Первая строка [package] представляет собой заголовок секции, указывающий,
что последующие параметры относятся к настройке пакета. По мере добавления
новой информации в этот файл мы будем добавлять и другие секции.
Следующие три строки задают информацию конфигурации, необходимую Cargo для
компиляции программы: имя, версию и используемую редакцию Rust. О ключе
edition мы поговорим в Приложении E.
Последняя строка [dependencies] обозначает начало секции, в которой
перечисляются зависимости проекта. В Rust пакеты кода называются
крейтами (crates). Для данного проекта нам не понадобятся дополнительные
крейты, однако они понадобятся нам в первом проекте Главы 2, поэтому мы
вернёмся к этой секции позже.
Теперь откройте src/main.rs и посмотрите его содержимое:
Имя файла: src/main.rs
fn main() {
println!("Hello, world!");
}
Cargo сгенерировал для вас программу «Hello, world!», точно такую же, как мы написали в листинге 1-1! Пока различия между нашим проектом и проектом, созданным Cargo, заключаются в том, что Cargo поместил код в каталог src, а в корневом каталоге находится конфигурационный файл Cargo.toml.
Cargo предполагает, что исходные файлы находятся внутри каталога src. Каталог верхнего уровня проекта предназначен только для файлов README, лицензионной информации, файлов конфигурации и всего остального, что не относится непосредственно к коду. Использование Cargo помогает организовать проекты: для каждой вещи существует своё место, и всё находится на своих местах.
Если вы начали проект без использования Cargo, как мы делали с проектом
«Hello, world!», вы можете преобразовать его в проект Cargo. Переместите код
проекта в каталог src и создайте соответствующий файл Cargo.toml.
Один из простых способов получить этот файл — выполнить cargo init,
который создаст его автоматически.
Сборка и запуск проекта Cargo
Теперь посмотрим, чем отличается сборка и запуск программы «Hello, world!» с использованием Cargo. Из каталога hello_cargo соберите проект, выполнив следующую команду:
$ cargo build
Compiling hello_cargo v0.1.0 (file:///projects/hello_cargo)
Finished dev [unoptimized + debuginfo] target(s) in 2.85 secs
Эта команда создаёт исполняемый файл в каталоге target/debug/hello_cargo (или target\debug\hello_cargo.exe в Windows), а не в текущем каталоге. Поскольку по умолчанию выполняется сборка в режиме отладки (debug build), Cargo помещает бинарный файл в каталог с именем debug. Вы можете запустить исполняемый файл следующей командой:
$ ./target/debug/hello_cargo # или .\target\debug\hello_cargo.exe в Windows
Hello, world!
Если всё прошло успешно, в терминале должна появиться строка
Hello, world!. Первый запуск cargo build также заставляет Cargo создать
новый файл верхнего уровня: Cargo.lock. Этот файл отслеживает точные версии
зависимостей вашего проекта. В данном проекте нет зависимостей, поэтому файл
содержит совсем немного информации. Вам никогда не придётся изменять этот
файл вручную; Cargo управляет его содержимым самостоятельно.
Мы только что собрали проект с помощью cargo build и запустили его через
./target/debug/hello_cargo, но также можно использовать cargo run,
чтобы выполнить компиляцию и запуск исполняемого файла одной командой:
$ cargo run
Finished dev [unoptimized + debuginfo] target(s) in 0.0 secs
Running `target/debug/hello_cargo`
Hello, world!
Использование cargo run удобнее, чем необходимость помнить про запуск
cargo build, а затем указывать полный путь к бинарному файлу, поэтому
большинство разработчиков используют именно cargo run.
Обратите внимание, что на этот раз мы не увидели вывода, сообщающего,
что Cargo компилирует hello_cargo. Cargo определил, что файлы не изменились,
поэтому не выполнял повторную сборку, а просто запустил бинарный файл.
Если бы исходный код был изменён, Cargo пересобрал бы проект перед запуском,
и вы увидели бы следующий вывод:
$ cargo run
Compiling hello_cargo v0.1.0 (file:///projects/hello_cargo)
Finished dev [unoptimized + debuginfo] target(s) in 0.33 secs
Running `target/debug/hello_cargo`
Hello, world!
Cargo также предоставляет команду cargo check. Эта команда быстро проверяет,
что код компилируется, но не создаёт исполняемый файл:
$ cargo check
Checking hello_cargo v0.1.0 (file:///projects/hello_cargo)
Finished dev [unoptimized + debuginfo] target(s) in 0.32 secs
Почему вам может не понадобиться исполняемый файл? Часто cargo check
работает значительно быстрее, чем cargo build, потому что пропускает этап
создания исполняемого файла. Если вы постоянно проверяете свою работу во время
написания кода, использование cargo check ускорит процесс получения
информации о том, продолжает ли ваш проект успешно компилироваться! Поэтому
многие Rustacean периодически запускают cargo check во время написания
программы, чтобы убедиться, что она по-прежнему компилируется. Затем, когда
исполняемый файл уже нужен, они запускают cargo build.
Подведём итог тому, что мы узнали о Cargo:
- Мы можем создать проект с помощью
cargo new. - Мы можем собрать проект с помощью
cargo build. - Мы можем собрать и запустить проект одним действием с помощью
cargo run. - Мы можем проверить проект на наличие ошибок без создания бинарного файла,
используя
cargo check. - Вместо сохранения результатов сборки в том же каталоге, где находится код, Cargo сохраняет их в каталоге target/debug.
Дополнительным преимуществом использования Cargo является то, что команды остаются одинаковыми независимо от используемой операционной системы. Поэтому с этого момента мы больше не будем приводить отдельные инструкции для Linux и macOS по сравнению с Windows.
Сборка для выпуска
Когда ваш проект наконец будет готов к выпуску, вы можете использовать
cargo build --release, чтобы выполнить компиляцию с оптимизациями.
Эта команда создаст исполняемый файл в каталоге target/release,
а не target/debug. Оптимизации позволяют вашему Rust-коду работать
быстрее, но их включение увеличивает время компиляции программы. Именно
поэтому существуют два различных профиля: один для разработки, когда
необходимы быстрые и частые пересборки, и другой для сборки финальной
версии программы, которую вы предоставите пользователю и которую не придётся
постоянно пересобирать, но которая должна работать максимально быстро.
Если вы измеряете производительность кода, обязательно используйте
cargo build --release и выполняйте тестирование с исполняемым файлом
из каталога target/release.
Использование соглашений Cargo
Для простых проектов Cargo не предоставляет значительных преимуществ по
сравнению с использованием только rustc, но по мере усложнения программ
его ценность становится очевидной. Когда программы начинают состоять из
нескольких файлов или требуют зависимостей, намного проще позволить Cargo
управлять процессом сборки.
Несмотря на то что проект hello_cargo является простым, он уже использует
большую часть реальных инструментов, с которыми вы будете работать на
протяжении всего пути изучения Rust. Более того, для работы с любыми
существующими проектами вы можете использовать следующие команды, чтобы
получить код через Git, перейти в каталог проекта и выполнить сборку:
$ git clone example.org/someproject
$ cd someproject
$ cargo build
Для получения дополнительной информации о Cargo ознакомьтесь с его документацией.
Итоги
Вы уже сделали отличный старт в изучении Rust! В этой главе вы узнали, как:
- установить последнюю стабильную версию Rust с помощью
rustup; - обновить Rust до новой версии;
- открыть локально установленную документацию;
- написать и запустить программу «Hello, world!» напрямую с использованием
rustc; - создать и запустить новый проект, используя соглашения Cargo.
Сейчас хороший момент для создания более серьёзной программы, чтобы привыкнуть к чтению и написанию Rust-кода. Поэтому в Главе 2 мы создадим программу «Угадай число». Если же вы предпочитаете сначала изучить работу основных концепций программирования в Rust, перейдите к Главе 3, а затем вернитесь к Главе 2.