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

Перекладено з англійського оригіналу · 06042fa · 2026-10-09 · Читати англійською

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

Контракт для програм, зібраних через clau -o або збіркою проєкту. Позиційні вхідні файли або рівно одна обрана ціль проєкту компонуються в шлях -o; збірка проєкту компонує кожну обрану ціль-виконуваний файл у її output з маніфесту (компонування, проєкти).

Вибір точки входу

Точка входу — це експортована функція арності 1, що отримує список аргументів.

ДжерелоЗаписОбласть дії
CLI--entry MODULE[:FUNCTION]Позиційний пакет або єдина обрана ціль проєкту
Маніфестentry = "MODULE[:FUNCTION]" у таблиці [[targets]]Ця ціль
ТиповоЄдиний escript, інакше єдиний модуль, що експортує main/1Лише коли запитано виконуваний файл (-o або ціль проєкту з output)
ЗбійДіагностика (код виходу 1)
Модуля немає в пакеті<origin>: entry module M is not among the compiled modules (походження: --entry або маніфест file:line:col [target t] (entry))
Немає F/1<file>:<line>:<col>: entry function M:F/1 is not defined на оголошенні модуля
Лише інші арності... is not defined; found F/N, but the entry receives one argument (the argument list) на цьому визначенні
F/1 не експортовано<file>:<line>:<col>: entry function M:F/1 is not exported на визначенні
Нічого не обрано, немає експорту main/1no entry point: no module exports main/1; choose the entry with --entry MODULE[:FUNCTION] (an exported FUNCTION/1; FUNCTION defaults to main)
Нічого не обрано, кількаambiguous entry point: main/1 is exported by a, b; choose the entry with ... (та сама підказка)

Для цілей проєкту підказка також називає ключ маніфесту: ... --entry MODULE[:FUNCTION] or with entry = "MODULE[:FUNCTION]" in this target's [[targets]] table of the project manifest ..., наприклад:

[[targets]]
name = "app"
sources = ["src/*.erl"]
entry = "app:start"   # calls app:start/1; plain "app" calls app:main/1

Аргументи

Entry(Argv) отримує правильний список рядків (списків кодових точок Unicode) без імені програми й початкових опцій runtime, в іншому незмінних і в тому самому порядку, як escript.

Опції runtime

Runtime читає свої опції зі змінної середовища CLAUSE_FLAGS (слова розділено пробілами й табуляціями, без лапок), а потім із початкових аргументів командного рядка, тож командний рядок має перевагу. Обидва розбираються однаково; значення йде в наступному аргументі або після =.

ОпціяЕфект
--max-atoms NРозмір таблиці атомів, від 1 до 2^26 (67 108 864); типово 2^20 (1 048 576), як +t в OTP
--max-heap BYTESОбмеження на блок купи кожного процесу, фрагменти й binary поза купою, щонайменше мінімальна купа (233 слова); типово без обмеження
--max-stack BYTESОбмеження на стек фреймів кожного процесу; типово без обмеження
--max-memory BYTESОбмеження на пам'ять усіх процесів разом (купи, binary поза купою, стеки); типово без обмеження
--schedulers NРобочі потоки планувальника, що виконують процеси, від 1 до 1 024; типово один на логічний процесор, як +S в OTP (робочі потоки)
--args-file FILEФайл опцій на кшталт vm.args в OTP: зарезервовано, повідомляє runtime option --args-file is not implemented
--Завершує опції runtime; усі наступні аргументи йдуть до Entry

У командному рядку розбір зупиняється на першому аргументі, що не є опцією runtime, тож prog data --max-atoms 9 передає програмі всі три аргументи. У CLAUSE_FLAGS кожне слово має бути опцією runtime. Недійсне значення, слово в змінній, що не є опцією, або --args-file зупиняють програму до реєстрації будь-якого модуля: clau: runtime failure: <reason>, код виходу 70. Кількість процесів не обмежена, а пам'ять типово не має обмеження. Значення в байтах десяткові без суфіксів і округлюються донизу до цілих слів; програма, що досягає обмеження, завершується збоєм resource_limit, код виходу 70 (обмеження пам'яті runtime).

Статус виходу

РезультатСтатус
Точка входу повертає значення (будь-яке)0
erlang:halt()0
erlang:halt(N), невід'ємне ціле числоN (хости POSIX зберігають молодші 8 бітів)
erlang:halt(Slogan) з рядкомГасло в stderr, потім 1 (без аварійного дампу)
erlang:halt(abort)Нативний abort (без скидання буферів)
Будь-який виняток, що виходить за межі точки входу, включно з throw і exit(normal)Звіт у stderr, 1
Процес точки входу завершено сигналом виходу (процеси)Повідомляється як неперехоплений exit, 1; причина normal: 0
Збій запуску runtime чи інфраструктури (невідповідність ABI, реєстрація, пам'ять до входу)Повідомлення в stderr, 70
Пам'ять хоста вичерпано (відмовлено в зростанні купи, binary поза купою чи стека; типово без обмеження пам'яті, вичерпання пам'яті)clau: runtime failure: entry call failed: out_of_memory, 70

Недійсні аргументи halt/1 породжують badarg у того, хто викликає. Коли точка входу завершується, програма виходить: інші процеси зупиняються без подальшого виконання, як із halt/1 в OTP після повернення з escript. Halt у будь-якому процесі завершує програму з його статусом, а збій runtime у будь-якому процесі завершує її з 70; виняток у запущеному процесі завершує лише цей процес (процеси).

halt/0,1, error/1,2,3, exit/1 і throw/1 можна викликати з префіксом erlang: або без нього; локальне визначення чи -compile({no_auto_import, ...}) залишає некваліфіковане ім'я локальним, як в OTP. halt/2 недоступна. halt(N) зберігає молодші 31 біт будь-якого невід'ємного цілого числа, як OTP. Гасло (slogan) — це правильний список щонайбільше з 1 023 кодових точок Unicode. Halt розмотує точку входу через перевірений канал помилок, як помилку, тож зупиняє програму лише після згенерованого прибирання.

Потоки виводу

Об'єкт запуску

Компіляція з явною точкою входу (--entry або entry маніфесту) додає модуль запуску після модулів пакета. З --emit він публікується як clausev1_start.{obj,o,ll,bc} поряд з артефактами модулів (ім'я не може збігтися з артефактом модуля). Він містить сталий abi::v1::StartupDescriptor (startup.hpp): ревізію ABI, ширину терма, кожен дескриптор модуля в порядку джерел, записи модуля/функції точки входу та прапорець escript. Його int main(int, char **) викликає CLAUSE_main_v1 з runtime, яка:

  1. Перевіряє дескриптор запуску й кожен дескриптор модуля на ревізію ABI та ширину до реєстрації будь-чого; невідповідність дає код виходу 70.
  2. Запускає runtime і реєструє всі модулі; будь-який збій зупиняє все до точки входу й відкидає runtime (код виходу 70), тож жоден код Erlang не виконується з неповним пакетом.
  3. Створює процес точки входу, будує argv і ставить виклик M:F/1 у чергу як головний процес, потім виконує його й кожен процес, який він запускає, на кооперативному виконавці (процеси), доки той не завершиться.
  4. Відображає результат на статус виходу вище, друкуючи звіти після скидання stdout, потім звільняє кожен процес і завершує роботу runtime на кожному шляху (окрім halt(abort)).

clau -o компонує ці об'єкти сам (компонування). Ручне компонування (рецепт нативної обв'язки без вихідного файлу обв'язки):

& $tool --emit obj --entry app --artifact-dir build/app app.erl helper.erl
clang-cl /MT build/app/*.obj build/debug/lib/clause_runtime.lib /Fe:app.exe

Будь-яке Clang-сумісне компонування об'єктів із Clause::generated_program працює так само (див. tests/compiler/linking/startup.cmake).

Компонування

clau [-O0|-O2|-Os] -o PATH a.erl b.erl ... (або --project FILE [--target T] -o PATH для однієї обраної цілі) компілює пакет у пам'яті, додає об'єкт запуску для точки входу і компонує виконуваний файл:

clau -O2 -o build/demo examples/compile/answer.erl examples/compile/client.erl
./build/demo          # build/demo.exe on Windows

-Os додатково розміщує кожну згенеровану функцію й функцію runtime та кожен об'єкт даних в окремій секції й компонує з --gc-sections (ELF), -dead_strip (Mach-O) або /OPT:REF /OPT:ICF (MSVC), тож код, якого не досягає жоден шлях від точки входу, видаляється.

Збій (код виходу 1)Діагностика
Немає Clangcannot find clang++ or clang on PATH; install LLVM/Clang or pass --linker / linker not found: X
Немає runtimeruntime library not found: P; build the clause_runtime target or pass --runtime-library
Не архівruntime library is not a static library: P: ...
Неправильна цільruntime library P contains x86_64 coff objects, but the executable targets T; ...
Помилка компонуванняlinking O failed: <clang> exited with status N:, а за ним вивід компонувальника (перші 64 КіБ)
Неправильне призначенняoutput directory does not exist: D, artifact destination is not a regular file: O, artifact destination aliases an input: O

Escript

Вихідний файл, перший рядок якого починається з #!, компілюється як escript у будь-якому режимі й з будь-яким ім'ям файлу (позиційні вхідні файли чи файли .erl проєкту). Правила відповідають escript з OTP 29 для скриптів у вихідних кодах:

Порівняння з OTP

Еталони для фікстур програм виконують точку входу під OTP за тими самими правилами (оракул); той самий оракул генерує еталонні випадки виконуваних файлів, які наскрізний запускач компонує й виконує за кожної політики. Відмінності від escript для звичайних модулів: неперехоплені винятки дають код виходу 1 замість 127, і main/1 має бути експортована. Вихідні коди escript зберігають правила OTP (див. вище).