Пакети та крейти (Packages and Crates)
Перші частини системи модулів, які ми розглянемо, — це пакети та крейти.
Крейт — це найменший обсяг коду, який компілятор Rust розглядає за раз. Навіть якщо ви запускаєте rustc замість cargo і передаєте один файл вихідного коду (як ми робили ще в “Основи програми Rust” у розділі 1), компілятор вважає цей файл крейтом. Крейт може містити модулі, а модулі можуть бути визначені в інших файлах, які компілюються разом із крейтом, як ми побачимо в наступних розділах.
Крейт може бути в одному з двох форматів: бінарний крейт або бібліотечний крейт. Бінарні крейти — це програми, які ви можете скомпілювати у виконуваний файл, який можна запускати, наприклад програму командного рядка або сервер. Кожен має містити функцію під назвою main, яка визначає, що відбувається під час запуску виконуваного файлу. Усі крейти, які ми створили дотепер, були бінарними крейтами.
Бібліотечні крейти не мають функції main і не компілюються у виконуваний файл. Натомість вони визначають функціональність, призначену для спільного використання з кількома проєктами. Наприклад, крейт rand, який ми використовували в розділі 2, надає функціональність, що генерує випадкові числа. Найчастіше, коли растацеанці (Rustaceans) кажуть “крейт”, вони мають на увазі бібліотечний крейт, і використовують “крейт” як взаємозамінне з загальним програмним поняттям “бібліотеки”.
Корінь крейту — це файл вихідного коду, з якого компілятор Rust починає роботу і який утворює кореневий модуль вашого крейту (ми детально пояснимо модулі в “Визначення модулів для керування областю видимості та приватністю”).
Пакет — це набір одного або кількох крейтів, що надає набір функціональності. Пакет містить файл Cargo.toml, який описує, як зібрати ці крейти. Cargo насправді є пакетом, який містить бінарний крейт для інструмента командного рядка, яким ви користувалися для збирання свого коду. Пакет Cargo також містить бібліотечний крейт, від якого залежить бінарний крейт. Інші проєкти можуть залежати від бібліотечного крейту Cargo, щоб використовувати ту саму логіку, яку використовує інструмент командного рядка Cargo.
Пакет може містити скільки завгодно бінарних крейтів, але не більше одного бібліотечного крейту. Пакет має містити принаймні один крейт, чи то бібліотечний, чи то бінарний.
Давайте розглянемо, що відбувається, коли ми створюємо пакет. Спочатку ми вводимо команду cargo new my-project:
$ cargo new my-project
Created binary (application) `my-project` package
$ ls my-project
Cargo.toml
src
$ ls my-project/src
main.rs
Після того як ми запускаємо cargo new my-project, ми використовуємо ls, щоб побачити, що створює Cargo. У каталозі my-project є файл Cargo.toml, який дає нам пакет. Також є каталог src, що містить main.rs. Відкрийте Cargo.toml у своєму текстовому редакторі та зауважте, що там немає згадки про src/main.rs. Cargo дотримується домовленості, що src/main.rs — це корінь крейту бінарного крейту з тією самою назвою, що й пакет. Аналогічно, Cargo знає, що якщо каталог пакета містить src/lib.rs, пакет містить бібліотечний крейт з тією самою назвою, що й пакет, а src/lib.rs — це його корінь крейту. Cargo передає файли кореня крейту до rustc, щоб зібрати бібліотеку або бінарний файл.
Тут у нас є пакет, який містить лише src/main.rs, тобто він містить лише бінарний крейт під назвою my-project. Якщо пакет містить src/main.rs і src/lib.rs, він має два крейти: бінарний і бібліотечний, обидва з тією самою назвою, що й пакет. Пакет може мати кілька бінарних крейтів, якщо розмістити файли в каталозі src/bin: кожен файл буде окремим бінарним крейтом.