Привіт, Cargo!

Cargo - це система побудови та пакетний менеджер Rust. Більшість растацеанців використовують цей інструмент для керування проєктами Rust, бо Cargo виконує багато задач, таких, як збірка коду, завантаження бібліотек, від яких залежить ваш код, та збірка цих бібліотек. (Бібліотеки, потрібні коду, звуться залежностями.)

Найпростіші програми Rust, як та, яку ми щойно написали, не мають жодних залежностей. Якби ми зібрали проєкт "Hello world" за допомогою Cargo, то скористалися б тільки тією частиною Cargo, що відповідає за збірку коду. Коли ж ви писатимете складніші програми Rust, то додаватимете залежності, і якщо почнете проєкт за допомогою Cargo, додавати залежності буде значно легше.

Оскільки переважна більшість проєктів Rust використовують Cargo, надалі в книзі вважатиметься, що ви теж використовуєте Cargo. Cargo встановлюється з Rust, якщо ви скористалися офіційним встановлювачем, як сказано в підрозділі Встановлення . Якщо ви встановили Rust у інший спосіб, перевірте, чи встановлений Cargo, ввівши це у свій термінал:

$ cargo --version

Якщо ви побачите номер версії, то Cargo встановлений! Але якщо ви бачите помилку на кшталт не знайдено команду, зверніться до документації по вашому методу встановлення, щоб визначити, як окремо встановити 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.

Файл: Cargo.toml

[package]
name = "hello_cargo"
version = "0.1.0"
edition = "2021"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]

Блок коду 1-2: Вміст файлу Cargo.toml, створеного командою cargo new

Це файл у форматі TOML (Tom’s Obvious, Minimal Language - "Томова очевидна мінімальна мова"), який Cargo використовує як формат для конфігурації.

Перший рядок, [package] (пакет) - це заголовок розділу, що показує, що наступні інструкції стосуються конфігурації пакета. Коли ми додамо більше інформації до цього файлу, ми додамо й інші розділи.

Наступні три рядки встановлюють конфігураційну інформацію, потрібну Cargo для компілювання вашої програми: ім'я, версію і яке видання Rust використовувати. Про ключ edition (видання) детальніше розповідається в Додатку E.

Останній рядок, [dependencies], розпочинає розділ, де можна вказувати залежності вашого проєкту. Пакети з кодом в Rust звуться крейтами (<0>crate</0>). Нам не потрібні інші крейти для цього проєкту, але вони знадобляться для першого проєкту у Розділі 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

Погляньмо, як відрізняється збірка і запуск програми “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
   Compiling 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 дозволить вам швидше дізнатися, чи ваш проєкт все ще компілюється! Ось чому багато растацеанців запускають 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 someurl.com/someproject
$ cd someproject
$ cargo build

Для отримання додаткової інформації про Cargo перегляньте документацію.

Підсумок

Це був непоганий початок вашої подорожі по Rust! У цьому розділі ви навчилися:

  • Встановлювати останню стабільну версію Rust за допомогою rustup
  • Оновлюватися до нової версії Rust
  • Відкривати локально встановлену документацію
  • Писати і запускати програму “Hello, world!” за допомогою rustc безпосередньо
  • Створювати і запускати новий проєкт за допомогою домовленостей Cargo

Настав час побудувати більш змістовну програму, щоб призвичаїтися до читання та написання коду Rust. У Розділі 2 ми створимо програму для відгадування числа. Якщо ви натомість бажаєте почати з вивчення, як загальні концепції програмування працюють в Rust, переходьте до Розділу 3, а потім поверніться до Розділу 2.