Пакеты и крейты
Первыми частями системы модулей, которые мы рассмотрим, будут пакеты и крейты.
Крейт — это наименьший объем кода, который компилятор Rust рассматривает за раз. Даже если вы запустите rustc
вместо cargo
и передадите один файл с исходным кодом (как мы уже делали в разделе "Написание и запуск программы на Rust" Главы 1), компилятор посчитает этот файл крейтом. Крейты могут содержать модули, и модули могут быть определены в других файлах, которые компилируются вместе с крейтом, как мы увидим в следующих разделах.
Крейт может иметь один из двух видов: бинарный крейт или библиотечный крейт. Бинарные крейты — это программы, которые вы можете скомпилировать в исполняемые файлы, которые вы можете запускать: например программа командной строки или сервер. У каждого бинарного крейта должна быть функция с именем main
, которая определяет, что происходит при запуске исполняемого файла. Все крейты, которые мы создавали до сих пор, были бинарными крейтами.
Library crates don’t have a main
function, and they don’t compile to an executable. Instead, they define functionality intended to be shared with multiple projects. For example, the rand
crate we used in Chapter 2 provides functionality that generates random numbers. Most of the time when Rustaceans say “crate”, they mean library crate, and they use “crate” interchangeably with the general programming concept of a “library”.
Корень крейта — это исходный файл, из которого компилятор 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. В директории проекта есть файл 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 разместить несколько файлов: каждый файл будет отдельным бинарным крейтом.