Анатомия проекта
Базовая компоновка проекта, а также общие файлы и папки, используемые cargo.
Директория/Файл - Комментарий
📁 .cargo/ - Проектно-локальная конфигурация cargo, может содержать config.toml.
📁 benches/ - Бенчмарки для вашего крейта, проходящие через cargo bench, требуют по умолчанию ночной версии rust.
📁 examples/ - Примеры того, как использовать ваш крейт.- my_example.rs Отдельные примеры запускаются как cargo run --example my_example.
📁 src/ - Фактический исходный код для вашего проекта.
-- main.rs - Точка входа по умолчанию для приложений, это то, что использует cargo run.
-- lib.rs - Точка входа по умолчанию для библиотек. Здесь начинается поиск my_crate::f().
📁 src/bin/ - Место для дополнительных двоичных файлов, даже в библиотечных проектах.
-- extra.rs - Дополнительный двоичный файл, запускается cargo run --bin extra.
📁 tests/ - Интеграционные тесты находятся эдесь, запускаясь через cargo test. Модульные тесты часто остаются в каталоге src/.
.rustfmt.toml - В случае, если вы хотите настроить, как работает cargo fmt.
.clippy.toml - Специальная конфигурация для определенных clippy lints, используемых через cargo clippy.
build.rs - Предварительный скрипт, полезный при компиляции C/FFI, ...
Cargo.toml - Основной манифест проекта. Определяет зависимости, артефакты.
Cargo.lock - Сведения о зависимостях для сборки, содержащиеся в git для приложений, а не для libs.
rust-toolchain.toml - Определение инструментов (канал, компоненты, путей) для этого проекта.
Минимальные примеры для различных точек входа могут выглядеть следующим образом:
Приложение
Библиотеки
Модульные тесты
Интеграционные тесты
Тесты производительности
Построение скриптов
Макросы
Деревья модулей и импорт:
Деревья модулей
Исходные файлы модулей работают следующим образом:
- Дерево модулей должно быть явно определено, не является неявно построенным из дерева файловой системы.
- Корень дерева модуля равен библиотеке, приложению, ... точка входа (например, lib.rs).
Фактически определения модулей работают следующим образом:
- `mod m {}` определяет модуль в файле, в то время как `mod m;` прочитает m.rs или m/mod.rs.
- Путь к .rs на основе вложенности, например, `mod a { mod b { mod c; }}}` либо a/b/c.rs, либо a/b/c/mod.rs.
- Файлы не идут из корня дерева модулей через какой-нибудь `mod m;`, не будет затронут компилятором!
Пространства имен
Rust имеет три типа пространств имен:
`struct X;` - Вычисляется в типах и в функциях, определяет тип `X` как константу.
`struct X();` - Вычисляется в типах и в функциях, определяет тип `X` как функцию.
- В любой заданной области, например в модуле, может существовать только один элемент на пространство имен, например:
-- `enum X {}` и `fn X() {}` могут сосуществовать.
-- `struct X;` и `const X` не может сосуществовать.
- С использованием `my_mod::X;` все элементы, называемые 'X', будут импортированы.
Из-за соглашений об именах (например, fn и mod написаны строчными буквами) и здравого смысла (большинство разработчиков просто не называют все вещи X) вам не придется беспокоиться об этих видах в большинстве случаев. Однако они могут быть фактором при проектировании макросов.
Cargo
Команды и инструменты, которые полезно знать.
cargo build означает, что вы можете написать cargo build, либо просто cargo b, --release можно заменить на -r.
Дополнительные компоненты rust устанавливаются утилитой rustup, добавляет необходимый инструмент.
Большое количество дополнительных cargo плагинов можно найти здесь.
Кросс-компиляция
- Установка через `rustup target install X`.
- Установите собственные нативные инструменты (зависит от ОС). Получить от поставщика (Google, Apple, ...), может быть доступно не на всех платформах (например, нет инструментов iOS в Windows). Некоторые инструменты требуют дополнительных шагов сборки (например, make-standalone-toolchain.sh Android).
- Обновите ~/.cargo/config.toml следующим образом:
или
Установите переменные среды (необязательно, подождите, пока компилятор пожалуется перед настройкой):
…
Установите ли вы их, зависит от того, как компилятор жалуется, не обязательно все необходимы.
Некоторые платформы могут быть чрезвычайно чувствительными к тому, как указаны пути (например, `\` против `/`).
Компиляция приложения: cargo build --target=X
Директивы инструментов
Специальные токены, встроенные в исходный код, используются инструментарием или препроцессорной обработки.
Макросы
Внутри декларативного макроса на примере macro_rules! осуществляется:
Документирование
Внутри документа комментируют:
#![globals]
Атрибуты, влияющие на весь трейт или приложение:
C - означает на уровне крейта (обычно указывается как #![ my_attr] в файле верхнего уровня).
M - модуля.
F - функции.
S - статических.
#[code]
Атрибуты, в первую очередь управляющие эмитируемым кодом:
M - модуля.
F - функции.
S - статических.
T - типа.
X - означает что-то особенное.
* - означает практически любой предмет.
#[quality]
[1] - Есть некоторые споры, какой из них является лучшим для обеспечения высокого качества крейтов. Активно поддерживаемые крейты для нескольких разработчиков, вероятно, выигрывают от более агрессивного отрицания или запрета линта; менее регулярно обновляемые, вероятно больше от консервативного использования warn (так как будущие обновления компилятора или clippy могут внезапно сломать, в этом случае работающий код будет с незначительными проблемами).
C - означает на уровне крейта (обычно указывается как #![ my_attr] в файле верхнего уровня).
M - на уровне модуля.
F - на уровне функции.
T - на уровне типа.
X - означает что-то особенное.
* - означает практически любой предмет.
#[macros]
! - макрос.
M - на уровне модуля.
F - на уровне функции.
X - означает что-то особенное.
#[cfg]
Атрибуты, управляющие условной компиляцией:
Следует отметить, что опции обычно можно задавать несколько раз, т.е. одна и та же команда может использоваться с несколькими значениями. Можно ожидать, что #[cfg (target_feature = «avx»)] и #[cfg (target_feature = «avx2»)] будут истинными одновременно.
* - означает практически любой предмет.
build.rs
Переменные среды и выходные данные, связанные со сценарием перед построением.
Доступно в build.rs через env::var()?. Список не является исчерпывающим.
Выводится из build.rs через println!(). Список не является исчерпывающим.
Примеры исходного кода статьи тут.
Статья на list-site.