Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Привет, Cargo!

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

Самые простые программы на Rust, подобные той, что мы написали до сих пор, не имеют зависимостей. Если бы мы собрали проект «Hello, world!» с помощью Cargo, он использовал бы только ту часть Cargo, которая отвечает за сборку вашего кода. По мере написания более сложных программ на Rust вы будете добавлять зависимости, и если вы начнёте проект с помощью Cargo, добавление зависимостей будет гораздо проще.

Поскольку подавляющее большинство проектов на Rust используют Cargo, в дальнейшей части книги предполагается, что вы тоже используете Cargo. Cargo устанавливается вместе с Rust, если вы использовали официальные установщики, описанные в разделе «Установка». Если вы установили Rust другим способом, проверьте, установлен ли Cargo, введя в терминале следующую команду:

$ cargo --version

Если вы видите номер версии — отлично! Если вы видите ошибку, например 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 внутри.

Он также инициализировал новый репозиторий Git вместе с файлом .gitignore. Файлы Git не будут созданы, если вы запустите cargo new внутри существующего репозитория Git; вы можете изменить это поведение, используя cargo new --vcs=git.

Примечание: Git — это распространённая система контроля версий. Вы можете изменить cargo new на использование другой системы контроля версий или отключить её, используя флаг --vcs. Запустите cargo new --help, чтобы увидеть доступные параметры.

Откройте Cargo.toml в текстовом редакторе по вашему выбору. Он должен выглядеть похоже на код в Листинге 1-2.

Filename: Cargo.toml
[package]
name = "hello_cargo"
version = "0.1.0"
edition = "2024"

[dependencies]
Listing 1-2: Содержимое Cargo.toml, сгенерированное командой cargo new

Этот файл имеет формат TOML (Tom’s Obvious, Minimal Language), который является форматом конфигурации Cargo.

Первая строка, [package], — это заголовок раздела, указывающий, что следующие инструкции настраивают пакет. По мере добавления в этот файл дополнительной информации мы будем добавлять другие разделы.

Следующие три строки задают информацию о конфигурации, необходимую Cargo для компиляции вашей программы: имя, версию и редакцию Rust для использования. Мы поговорим о ключе edition в Приложении E.

Последняя строка, [dependencies], — это начало раздела, в котором вы перечисляете все зависимости вашего проекта. В Rust пакеты кода называются крейтами. Нам не понадобятся другие крейты для этого проекта, но они понадобятся в первом проекте в Главе 2, поэтому мы используем этот раздел зависимостей тогда.

Теперь откройте src/main.rs и посмотрите на него:

Имя файла: src/main.rs

fn main() {
    println!("Hello, world!");
}

Cargo сгенерировал для вас программу «Hello, world!», точно такую же, какую мы написали в Листинге 1-1! Пока что различия между нашим проектом и проектом, сгенерированным Cargo, consist в том, что Cargo поместил код в каталог src, и у нас есть файл конфигурации Cargo.toml в верхнем каталоге.

Cargo ожидает, что ваши исходные файлы будут находиться внутри каталога src. Верхнеуровневый каталог проекта предназначен только для файлов README, информации о лицензии, файлов конфигурации и всего остального, не связанного с вашим кодом. Использование Cargo помогает организовать ваши проекты. Для всего есть своё место, и всё на своём месте.

Если вы начали проект, который не использует Cargo, как мы сделали с проектом «Hello, world!», вы можете преобразовать его в проект, который использует Cargo. Переместите код проекта в каталог src и создайте соответствующий файл Cargo.toml. Один из простых способов получить этот файл 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), а не в вашем текущем каталоге. Поскольку сборка по умолчанию — это сборка для отладки, 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 ускорит процесс, позволяя вам знать, компилируется ли ваш проект! Поэтому многие разработчики на Rust периодически запускают 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.