Clause
← Уся документація

Англійський оригінал змінився після перекладу, тож частина тексту може бути застарілою. Читати англійською

Перекладено з англійського оригіналу · 1e3a39c8-dirty · 2026-10-26

Проєкти TOML

Маніфест проєкту вибирає впорядковані групи вихідних файлів Erlang і незалежно налаштовує кожну ціль. Усі дії CLI приймають проєкти. Див. робочий приклад.

Маніфест (схема 1)

schema_version = 1

[[targets]]
name = "app"
sources = ["main.erl", "src/workers/*.erl", "shared/**/*.erl"]
source_dirs = ["src/support"]
output = "build/app"
entry = "main:main"
build_dir = "build"

[targets.options]
source_search_paths = ["src", "generated"]
include_dirs = ["include", "vendor/include"]
defines = ["DEBUG", "LIMIT=100", 'LABEL="demo"']
enable_features = ["maybe_expr"]
disable_features = ["compr_assign"]
ignore_dirs = ["src/legacy", "deps/*/test"]
ignore_modules = ["telemetry", "*_SUITE"]
keep_exports = false
shell = false
cache_inference_in_dirs = ["deps/*"]

[targets.options.applications]
my_dependency = "vendor/my_dependency"

CLI і вибір цілей

clau [options] <source.erl>...
clau [options] --project <path> [--target <name>]...
clau --new-project <filename>

Кожна вибрана ціль — це окремий пакет компіляції з власними сесіями препроцесування. Планування (декодування, вибір, пошук файлів, перевірка колізій виводу) завершується до обробки будь-якого вихідного файлу; потім виконання обробляє цілі/файли по порядку і фіксує невдачі. Корисний вивід іде в stdout у порядку цілей/файлів без заголовків (крім рядків цілей --print-inputs); контекст і діагностика йдуть у stderr. Ціль із діагностикою називається один раз, у рядку <manifest> [target <name>]: перед першим її повідомленням; самі повідомлення (error: file:line:col: message) не мають префікса інструмента чи цілі.

./build/debug/bin/clau --parse-check --project examples/project/project.toml
./build/debug/bin/clau --print-ast --project examples/project/project.toml --target tests --target app

Виконувані файли

clau --project FILE [--target T]... (без --emit, без дії перевірки/друку) компонує кожну вибрану ціль, що має ключ output або entry або до якої звертаються -o/--entry з CLI, в один виконуваний файл на ціль:

./build/debug/bin/clau --project tests/fixtures/linking/project/project.toml

Створення проєкту

--new-project <filename> записує один анотований маніфест і нічого більше.

Каталог збирання

Кожна ціль проєкту має каталог збирання, де Clause тримає власні тимчасові файли та свої кеші: build_dir цілі, відносно маніфесту, типово <manifest-dir>/build. --build-dir DIR (відносно каталогу виклику) замінює його для кожної вибраної цілі. Позиційні вхідні файли не отримують жодного, якщо не задано --build-dir.

Кеші збирання

Результати, які варто зберігати між запусками, лежать у <build_dir>/cache; --no-cache їх не читає й не записує. Це відповіді завантажувача parse transforms і список sticky-модулів OTP хоста, тож тепле збирання не запускає erl хоста для модулів, вхідні дані перетворень яких не змінилися, результат компіляції кожного пакета і результати виведення модулів у налаштованих каталогах.

Кеш виведення

Бібліотечні модулі (вихідні файли stdlib, kernel, compiler і syntax_tools з OTP, знайдені через source_search_paths, власна бібліотека Clause) змінюються рідко, тож модулі в налаштованих каталогах зберігають результати виведення типів у кеші збирання, для кожного модуля окремо, а пізніші компіляції використовують їх повторно, замість того щоб виводити знову.

Шляхи та пошук файлів

Індекс каталогів

Пошук за іменем не перевіряє кожен каталог-кандидат. Один індекс на виклик clau, спільний для всіх цілей, зберігає імена записів кожного каталогу, де виконується пошук: каталог перелічується один раз, нерекурсивно, коли пошук уперше його потребує, або записується рекурсивними обходами, що розгортають ** у sources, source_dirs, source_search_paths, include_dirs і transform_paths, тож жоден каталог не перелічується двічі. Він відповідає на промахи пошуку модулів (бібліотека, потім source_search_paths), вихідних файлів перетворень, буквальних sources, знайдених через source_search_paths, і розв'язання включень (каталог файлу, що включає, робочий каталог, каталоги включення по порядку, потім застосунки include_lib); кандидат, який містить індекс, усе одно відкривається або перевіряється, як і раніше, тож пріоритет, ignore_dirs і звіти про помилки не змінюються. Імена включень із частинами каталогів (sub/x.hrl) шукаються в каталозі, який вони називають; імена з кроками .., абсолютні імена, відносні каталоги та переліки, що не вдалися, перевіряються, як і раніше.

Ігноровані вихідні файли

ignore_dirs і ignore_modules виключають вихідні файли з цілі, не видаляючи їх із дерева, наприклад вбудовані тести сторонніх залежностей, застарілий код або модулі, що мають значення лише під OTP. Ігнорований вихідний файл мовчки пропускається: його ніколи не читають, не розбирають, не компілюють і не компонують, тож він може навіть містити синтаксичні помилки.

[targets.options]
source_search_paths = ["deps/**"]
ignore_dirs = ["deps/*/test", "src/legacy"]
ignore_modules = ["telemetry", "*_SUITE"]

Ефективні параметри

НалаштуванняПоєднання маніфесту і CLI
include_dirsПорядок маніфесту, після -I з CLI (останній -I з CLI шукається першим); запис із підстановочними знаками (deps/*/include, apps/**/include) розгортається на місці в наявні каталоги, яким він відповідає, відсортовані за байтами шляху UTF-8 (** також відповідає жодному, символьні посилання на каталоги пропускаються); шаблон без збігів — помилка
source_search_pathsРезервні корені для буквальних вихідних файлів і модулів, які ціль називає, але не перелічує; шаблони розгортаються як include_dirs (без збігів: unmatched source search path pattern)
definesСпочатку маніфест, потім CLI; дублікати між ними є помилками
applicationsMap маніфесту; записи CLI замінюють однойменні
Списки можливостейНалаштування маніфесту, потім упорядковані зміни з CLI; CLI має перевагу
outputДля кожної цілі, лише для виконуваних цілей; -o з CLI перевизначає для однієї вибраної цілі
entryДля кожної цілі; --entry з CLI перевизначає для однієї вибраної цілі
cache_inference_in_dirsНеявні шаблони OTP, потім шаблони маніфесту, потім --cache-inference-in-dirs з CLI (кеш виведення)

Залежність збирання

Приватний для компілятора toml++ 3.4.0 (MIT), лише заголовки, з винятками, невипущений синтаксис вимкнено. SHA-256 архіву 8517f65938a4faae9ccf8ebb36631a38c1cadfb5efa85d9a72e15b9e97d25155.

Кеш збирання використовує амальгамацію SQLite 3.54.0 (суспільне надбання), скомпільовану лише в бібліотеку кешу компілятора (clause_sqlite, без прапорців попереджень проєкту). CMake завантажує https://www.sqlite.org/2026/sqlite-amalgamation-3540000.zip у thirdparty/ на кожному хості та перевіряє його SHA-256 68e913b0fe8ec6b4e5f391c594a28872884e80d6cd042a1e50c957be46b5aa4d; -DCLAUSE_SQLITE_ROOT=<directory with sqlite3.c and sqlite3.h> має пріоритет і вимикає завантаження.

Обмеження

Розмір маніфесту 1 MiB; щонайбільше 1 024 цілі та 100 000 вузлів TOML. Кожне розгортання вихідних файлів допускає 100 000 відвіданих записів, 128 рівнів каталогів і 16 000 000 переходів підстановочних знаків. Вичерпання є явною помилкою; це межі роботи, а не граничні терміни вводу-виводу.