Привіт, Cargo! (Hello, Cargo!)
Cargo — це система збирання та менеджер пакетів Rust. Більшість растацеанців (Rustaceans) використовують цей інструмент для керування своїми проєктами Rust, тому що Cargo бере на себе багато завдань, таких як збирання вашого коду, завантаження бібліотек, від яких залежить ваш код, і збирання цих бібліотек. (Ми називаємо бібліотеки, які потрібні вашому коду, залежностями.)
Найпростіші програми Rust, як та, яку ми написали досі, не мають жодних залежностей. Якби ми зібрали проєкт “Hello, world!” за допомогою Cargo, він використовував би лише ту частину Cargo, яка відповідає за збирання вашого коду. У міру того як ви пишете складніші програми Rust, ви додаватимете залежності, і якщо ви почнете проєкт за допомогою Cargo, додавати залежності буде значно простіше.
Оскільки переважна більшість проєктів Rust використовує Cargo, решта цієї книги припускає, що ви теж використовуєте Cargo. Cargo встановлюється разом із Rust, якщо ви користувалися офіційними інсталяторами, про які йшлося в розділі “Встановлення (Installation)”. Якщо ви встановили 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 у текстовому редакторі на ваш вибір. Він має виглядати подібно до коду в Лістингу (Listing) 1-2.
[package]
name = "hello_cargo"
version = "0.1.0"
edition = "2024"
[dependencies]
Цей файл має формат TOML (Tom’s Obvious, Minimal Language), який є форматом конфігурації Cargo.
Перший рядок, [package], є заголовком розділу, що вказує, що наступні оператори налаштовують пакет. У міру того як ми додаватимемо більше інформації до цього файлу, ми додаватимемо й інші розділи.
Наступні три рядки задають інформацію конфігурації, яка потрібна Cargo для компіляції вашої програми: назву, версію та редакцію (edition) Rust, яку слід використовувати. Про ключ edition ми поговоримо в Додатку E.
Останній рядок, [dependencies], — це початок розділу, у якому ви можете перелічити будь-які залежності вашого проєкту. У Rust пакети коду називають крейтами (crates). Для цього проєкту нам не знадобляться інші крейти, але вони знадобляться в першому проєкті в Розділі 2, тож тоді ми використаємо цей розділ dependencies.
Тепер відкрийте src/main.rs і погляньте:
Ім’я файлу: src/main.rs
fn main() {
println!("Hello, world!");
}
Cargo згенерував для вас програму “Hello, world!”, так само як ту, яку ми написали в Лістингу (Listing) 1-1! Поки що відмінності між нашим проєктом і проєктом, згенерованим Cargo, полягають у тому, що 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), а не у вашому поточному каталозі. Оскільки стандартне збирання — це debug-збирання, Cargo поміщає бінарний файл у каталог із назвою debug. Ви можете запустити виконуваний файл цією командою:
$ ./target/debug/hello_cargo # or .\target\debug\hello_cargo.exe on 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 пришвидшить процес повідомлення вам про те, чи ваш проєкт і далі компілюється! Тому багато растацеанців (Rustaceans) періодично запускають 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.