Хватит разговоров: покажите код
Что вы узнаете: вашу первую программу на Rust —
fn main(),println!()и то, чем макросы Rust принципиально отличаются от препроцессорных макросов C/C++. К концу главы вы сможете написать, скомпилировать и запустить простые программы на Rust.
fn main() {
println!("Hello world from Rust");
}
- Этот синтаксис должен быть понятен всем, кто знаком с языками в стиле C
- Все функции в Rust начинаются с ключевого слова
fn - Точка входа по умолчанию для исполняемых файлов —
main() println!выглядит как функция, но на самом деле это макрос. Макросы в Rust сильно отличаются от препроцессорных макросов C/C++: они гигиеничны, типобезопасны и работают с синтаксическим деревом, а не с текстовой подстановкой
- Все функции в Rust начинаются с ключевого слова
- Два удобных способа быстро опробовать фрагменты кода на Rust:
- Онлайн: Rust Playground — вставьте код, нажмите Run и поделитесь результатом. Установка не нужна
- Локальный REPL: установите
evcxr_replдля интерактивного REPL Rust (как REPL Python, только для Rust):
cargo install --locked evcxr_repl
evcxr # Запустить REPL и вводить выражения Rust интерактивно
Локальная установка Rust
- Rust можно установить локально одним из следующих способов
- Windows: https://static.rust-lang.org/rustup/dist/x86_64-pc-windows-msvc/rustup-init.exe
- Linux / WSL:
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
- Экосистема Rust состоит из следующих компонентов
rustc— самостоятельный компилятор, но им редко пользуются напрямую- Основной инструмент —
cargo, швейцарский армейский нож для управления зависимостями, сборки, тестирования, форматирования, линтинга и т. д. - Тулчейн Rust бывает в каналах
stable,betaиnightly(экспериментальный), но мы будем использоватьstable. Командаrustup updateобновляет установкуstable, которая выходит каждые шесть недель
- Мы также установим плагин
rust-analyzerдля VSCode
Пакеты Rust (крейты)
- Бинарные файлы Rust создаются из пакетов (далее — крейты)
- Крейт может быть самостоятельным или зависеть от других крейтов. Крейты-зависимости могут быть локальными или удалёнными. Сторонние крейты обычно скачиваются из централизованного репозитория под названием
crates.io. - Инструмент
cargoавтоматически загружает крейты и их зависимости. Концептуально это эквивалентно подключению C-библиотек - Зависимости крейта описываются в файле
Cargo.toml. Там же задаётся тип цели для крейта: самостоятельный исполняемый файл, статическая библиотека, динамическая библиотека (встречается редко) - Справка: https://doc.rust-lang.org/cargo/reference/cargo-targets.html
- Крейт может быть самостоятельным или зависеть от других крейтов. Крейты-зависимости могут быть локальными или удалёнными. Сторонние крейты обычно скачиваются из централизованного репозитория под названием
Cargo и традиционные системы сборки C
Сравнение управления зависимостями
graph TD
subgraph "Традиционный процесс сборки на C"
CC["Исходные файлы C<br/>(.c, .h)"]
CM["Ручной Makefile<br/>или CMake"]
CL["Компоновщик"]
CB["Итоговый бинарный файл"]
CC --> CM
CM --> CL
CL --> CB
CDep["Ручное управление<br/>зависимостями"]
CLib1["libcurl-dev<br/>(apt install)"]
CLib2["libjson-dev<br/>(apt install)"]
CInc["Ручные пути включения<br/>-I/usr/include/curl"]
CLink["Ручная компоновка<br/>-lcurl -ljson"]
CDep --> CLib1
CDep --> CLib2
CLib1 --> CInc
CLib2 --> CInc
CInc --> CM
CLink --> CL
C_ISSUES["[ОШИБКА] Конфликты версий<br/>[ОШИБКА] Различия платформ<br/>[ОШИБКА] Отсутствующие зависимости<br/>[ОШИБКА] Важен порядок компоновки<br/>[ОШИБКА] Нет автоматических обновлений"]
end
subgraph "Процесс сборки Rust с Cargo"
RS["Исходные файлы Rust<br/>(.rs)"]
CT["Cargo.toml<br/>[dependencies]<br/>reqwest = '0.11'<br/>serde_json = '1.0'"]
CRG["Система сборки Cargo"]
RB["Итоговый бинарный файл"]
RS --> CRG
CT --> CRG
CRG --> RB
CRATES["crates.io<br/>(реестр пакетов)"]
DEPS["Автоматическое разрешение<br/>зависимостей"]
LOCK["Cargo.lock<br/>(фиксация версий)"]
CRATES --> DEPS
DEPS --> CRG
CRG --> LOCK
R_BENEFITS["[OK] Семантическое версионирование<br/>[OK] Автоматическая загрузка<br/>[OK] Кроссплатформенность<br/>[OK] Транзитивные зависимости<br/>[OK] Воспроизводимые сборки"]
end
style C_ISSUES fill:#ff6b6b,color:#000
style R_BENEFITS fill:#91e5a3,color:#000
style CM fill:#ffa07a,color:#000
style CDep fill:#ffa07a,color:#000
style CT fill:#91e5a3,color:#000
style CRG fill:#91e5a3,color:#000
style DEPS fill:#91e5a3,color:#000
style CRATES fill:#91e5a3,color:#000
Структура проекта Cargo
my_project/
|-- Cargo.toml # Конфигурация проекта (аналог package.json)
|-- Cargo.lock # Точные версии зависимостей (генерируется автоматически)
|-- src/
| |-- main.rs # Главная точка входа для бинарного файла
| |-- lib.rs # Корень библиотеки (если создаёте библиотеку)
| `-- bin/ # Дополнительные бинарные цели
|-- tests/ # Интеграционные тесты
|-- examples/ # Примеры кода
|-- benches/ # Бенчмарки
`-- target/ # Артефакты сборки (аналог build/ или obj/ в C)
|-- debug/ # Отладочные сборки (быстрая компиляция, медленное выполнение)
`-- release/ # Релизные сборки (медленная компиляция, быстрое выполнение)
Основные команды Cargo
graph LR
subgraph "Жизненный цикл проекта"
NEW["cargo new my_project<br/>[FOLDER] Создать проект"]
CHECK["cargo check<br/>[SEARCH] Быстрая проверка синтаксиса"]
BUILD["cargo build<br/>[BUILD] Скомпилировать проект"]
RUN["cargo run<br/>[PLAY] Собрать и выполнить"]
TEST["cargo test<br/>[TEST] Запустить все тесты"]
NEW --> CHECK
CHECK --> BUILD
BUILD --> RUN
BUILD --> TEST
end
subgraph "Дополнительные команды"
UPDATE["cargo update<br/>[CHART] Обновить зависимости"]
FORMAT["cargo fmt<br/>[SPARKLES] Форматировать код"]
LINT["cargo clippy<br/>[WRENCH] Линтинг и подсказки"]
DOC["cargo doc<br/>[BOOKS] Сгенерировать документацию"]
PUBLISH["cargo publish<br/>[PACKAGE] Опубликовать на crates.io"]
end
subgraph "Профили сборки"
DEBUG["cargo build<br/>(отладочный профиль)<br/>Быстрая компиляция<br/>Медленное выполнение<br/>Отладочные символы"]
RELEASE["cargo build --release<br/>(релизный профиль)<br/>Медленная компиляция<br/>Быстрое выполнение<br/>Оптимизирован"]
end
style NEW fill:#a3d5ff,color:#000
style CHECK fill:#91e5a3,color:#000
style BUILD fill:#ffa07a,color:#000
style RUN fill:#ffcc5c,color:#000
style TEST fill:#c084fc,color:#000
style DEBUG fill:#94a3b8,color:#000
style RELEASE fill:#ef4444,color:#000
Пример: cargo и крейты
- В этом примере у нас есть самостоятельный исполняемый крейт без других зависимостей
- Используйте следующие команды, чтобы создать новый крейт под названием
helloworld
cargo new helloworld
cd helloworld
cat Cargo.toml
- По умолчанию
cargo runскомпилирует и запуститdebug-версию крейта (без оптимизаций). Чтобы запуститьrelease-версию, используйтеcargo run --release - Обратите внимание: сам бинарный файл находится в папке
target, внутри папкиdebugилиrelease - Возможно, вы также заметили файл
Cargo.lockрядом с исходниками. Он генерируется автоматически и не должен редактироваться вручную- Конкретное назначение
Cargo.lockмы рассмотрим позже
- Конкретное назначение