Clause
← Gesamte Dokumentation

Übersetzt aus dem englischen Original · 1e3a39c8-dirty · 2026-10-26 · Auf Englisch lesen

Ausführbare Dateien

Vertrag für Programme, die mit clau -o oder einem Projekt-Build erstellt werden. Positionelle Eingaben oder genau ein ausgewähltes Projektziel werden zum -o-Pfad gelinkt; ein Projekt-Build linkt jedes ausgewählte ausführbare Ziel zu seinem output im Manifest (Linken, Projekte).

Auswahl des Einstiegspunkts

Der Einstiegspunkt ist eine exportierte Funktion der Stelligkeit 1, die die Argumentliste erhält. Eine ausgewählte FUNCTION ohne FUNCTION/1 darf stattdessen ein exportiertes FUNCTION/0 sein: Sie läuft ohne die Programmargumente (Runtime-Optionen werden trotzdem herausgenommen). Ein Suffix /0 oder /1 wählt nur diese Stelligkeit, sodass --entry benchmarks:run/0 auch dann run/0 ausführt, wenn run/1 ebenfalls exportiert ist. Der Standard (keine Auswahl) ist immer main/1.

QuelleSchreibweiseGeltungsbereich
CLI--entry MODULE[:FUNCTION[/ARITY]]Positioneller Batch oder das einzige ausgewählte Projektziel
Manifestentry = "MODULE[:FUNCTION[/ARITY]]" in einer [[targets]]-TabelleDieses Ziel
StandardDas einzige escript, sonst das einzige Modul, das main/1 exportiertNur wenn eine ausführbare Datei angefordert wird (-o oder ein Projektziel mit output)
FehlerDiagnose (Exit 1)
Modul nicht im Batch<origin>: entry module M is not among the compiled modules (Herkunft: --entry oder Manifest file:line:col [target t] (entry))
Weder F/1 noch F/0<file>:<line>:<col>: entry function M:F/1 is not defined an der Moduldeklaration
Explizites F/A fehlt... entry function M:F/A is not defined; found F/N an einer gleichnamigen Definition, sonst an der Moduldeklaration
Nur andere Stelligkeiten... is not defined; found F/N, but the entry takes the argument list (FUNCTION/1) or nothing (FUNCTION/0) an dieser Definition
F/1 (sonst F/0) nicht exportiert<file>:<line>:<col>: entry function M:F/A is not exported an der Definition
Keine Auswahl, kein Export von main/1no entry point: no module exports main/1; choose the entry with --entry MODULE[:FUNCTION[/ARITY]] (an exported FUNCTION/1, or FUNCTION/0 run without the program arguments; FUNCTION defaults to main, ARITY to 1, else 0)
Keine Auswahl, mehrereambiguous entry point: main/1 is exported by a, b; choose the entry with ... (gleicher Hinweis)

Für Projektziele nennt der Hinweis auch den Manifest-Schlüssel: ... --entry MODULE[:FUNCTION[/ARITY]] or with entry = "MODULE[:FUNCTION[/ARITY]]" in this target's [[targets]] table of the project manifest ..., zum Beispiel:

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

Argumente

Entry(Argv) erhält eine echte Liste von Strings (Listen von Unicode-Codepoints), ohne den Programmnamen und die führenden Runtime-Optionen, sonst unverändert und in Reihenfolge, wie bei escript.

Runtime-Optionen

Die Runtime liest ihre Optionen aus der Umgebungsvariable CLAUSE_FLAGS (Wörter getrennt an Leerzeichen und Tabs, kein Quoting) und dann aus den führenden Befehlszeilenargumenten, sodass die Befehlszeile gewinnt. Beide werden gleich ausgewertet; ein Wert steht im nächsten Argument oder nach =.

OptionWirkung
--max-atoms NGröße der Atomtabelle, 1 bis 2^26 (67.108.864); Standard 2^20 (1.048.576), wie +t von OTP
--max-heap BYTESObergrenze für Heap-Block, Fragmente und Off-Heap-Binaries jedes Prozesses, mindestens der minimale Heap (233 Wörter); standardmäßig unbegrenzt
--max-stack BYTESObergrenze für den Frame-Stack jedes Prozesses; standardmäßig unbegrenzt
--min-heap-size WORDSStandard-min_heap_size jedes Prozesses, mindestens 1, aufgerundet auf eine Heap-Größe, wie +hms von OTP; höchstens --max-heap; Standard 233 (Größenbemessung)
--max-memory BYTESObergrenze für den Speicher aller Prozesse zusammen (Heaps, Off-Heap-Binaries, Stacks); standardmäßig unbegrenzt
--schedulers NScheduler-Worker, die Prozesse ausführen, 1 bis 1.024; Standard einer pro CPU von --scheduler-cpus, sonst einer pro logischem Prozessor, auf dem das Programm laufen darf (seine Affinitätsmaske), wie die Online-Scheduler von OTP (Worker)
--scheduler-cpus SETBindet Worker N reihum an die N-te CPU von SET, wie +sbt/+sct von OTP: performance (die schnellste Kernklasse: P-Kerne einer Hybrid-CPU, sonst jede CPU), all oder eine Liste wie 0-15 oder 2,4,6; jede aufgeführte CPU muss in der Affinitätsmaske liegen. Standardmäßig ungebunden (CPU-Bindung)
--profile FILESchreibt beim Programmende einen Bericht über Eintritte und Eigenzeit pro Funktion und pro Prozess nach FILE (Profiling); standardmäßig aus
--args-file FILEOptionsdatei wie vm.args von OTP: reserviert, meldet runtime option --args-file is not implemented
--Beendet die Runtime-Optionen; alle folgenden Argumente gehen an Entry

Auf der Befehlszeile endet die Auswertung beim ersten Argument, das keine Runtime-Option ist, sodass prog data --max-atoms 9 alle drei Argumente an das Programm übergibt. In CLAUSE_FLAGS muss jedes Wort eine Runtime-Option sein. Ein ungültiger Wert, ein Wort in der Variable, das keine Option ist, oder --args-file stoppt das Programm, bevor irgendein Modul registriert ist: clau: runtime failure: <reason>, Exit 70. Prozessanzahlen sind nicht begrenzt, und Speicher ist standardmäßig unbegrenzt. Byte-Werte sind dezimal ohne Suffixe und werden auf ganze Wörter abgerundet; ein Programm, das eine Obergrenze erreicht, scheitert mit resource_limit, Exit 70 (Speichergrenze der Runtime).

Exit-Status

ErgebnisStatus
Einstiegspunkt kehrt zurück (beliebiger Wert)0
erlang:halt()0
erlang:halt(N), nichtnegative GanzzahlN (POSIX-Hosts behalten die unteren 8 Bits)
erlang:halt(Slogan) mit einem StringSlogan auf stderr, dann 1 (kein Crash-Dump)
erlang:halt(abort)Nativer Abbruch (kein Leeren der Puffer)
Jede Ausnahme, die den Einstiegspunkt verlässt, einschließlich throw und exit(normal)Bericht auf stderr, 1
Einstiegsprozess durch ein Exit-Signal beendet (Prozesse)Gemeldet als nicht abgefangenes exit, 1; Grund normal: 0
Fehler beim Start der Runtime oder in der Infrastruktur (ABI-Abweichung, Registrierung, Speicher vor dem Einstieg)Meldung auf stderr, 70
Speicher des Hosts erschöpft (Wachstum von Heap, Off-Heap-Binary oder Stack verweigert; standardmäßig keine Speichergrenze, Speichererschöpfung)clau: runtime failure: entry call failed: out_of_memory, 70

Ungültige Argumente von halt/1 lösen im Aufrufer badarg aus. Endet der Einstiegspunkt, beendet sich das Programm: Andere Prozesse werden gestoppt, ohne weiterzulaufen, wie bei halt/1 von OTP nach der Rückkehr von escript. Ein Halt in einem beliebigen Prozess beendet das Programm mit dessen Status, und ein Runtime-Fehler in einem beliebigen Prozess beendet es mit 70; eine Ausnahme in einem gestarteten Prozess beendet nur diesen Prozess (Prozesse).

halt/0,1, error/1,2,3, exit/1 und throw/1 sind mit oder ohne Präfix erlang: aufrufbar; eine lokale Definition oder -compile({no_auto_import, ...}) hält den unqualifizierten Namen lokal, wie in OTP. halt/2 ist nicht verfügbar. halt(N) behält die unteren 31 Bits jeder nichtnegativen Ganzzahl, wie OTP. Ein Slogan ist eine echte Liste von höchstens 1.023 Unicode-Codepoints. Ein Halt wickelt den Einstiegspunkt wie ein Fehler über den geprüften Fehlerkanal ab, sodass er das Programm erst nach dem erzeugten Aufräumen stoppt.

Ausgabeströme

Startobjekt

Kompilieren mit einem expliziten Einstiegspunkt (--entry oder entry im Manifest) fügt nach den Modulen des Batches ein Startmodul hinzu. Mit --emit wird es als clausev1_start.{obj,o,ll,bc} neben den Modulartefakten veröffentlicht (der Name kann nicht mit einem Modulartefakt kollidieren). Es enthält einen konstanten abi::v1::StartupDescriptor (startup.hpp): ABI-Revision, Term-Breite, jeden Moduldeskriptor in Quelltextreihenfolge, die Schreibweisen von Einstiegsmodul und -funktion sowie ein escript-Flag. Sein int main(int, char **) ruft CLAUSE_main_v1 der Runtime auf, das:

  1. Startdeskriptor und jeden Moduldeskriptor auf ABI-Revision und Breite prüft, bevor irgendetwas registriert wird; eine Abweichung endet mit 70.
  2. Die Runtime startet und alle Module registriert; jeder Fehler stoppt vor dem Einstiegspunkt und verwirft die Runtime (Exit 70), sodass kein Erlang-Code gegen einen unvollständigen Batch läuft.
  3. Den Einstiegsprozess erzeugt, argv aufbaut und den Aufruf von M:F/1 als Hauptprozess einreiht, ihn dann zusammen mit jedem Prozess, den er startet, auf den Scheduler-Workern (Prozesse) ausführt, bis er endet.
  4. Das Ergebnis auf den obigen Exit-Status abbildet, Berichte nach dem Leeren von stdout ausgibt, dann jeden Prozess freigibt und die Runtime auf jedem Pfad herunterfährt (außer halt(abort)).

clau -o linkt diese Objekte selbst (Linken). Manuelles Linken (das Rezept für das native Harness ohne Harness-Quelltext):

& $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

Jedes Clang-kompatible Linken der Objekte mit Clause::generated_program funktioniert genauso (siehe tests/compiler/linking/startup.cmake).

Linken

clau [-O0|-O2|-Os] -o PATH a.erl b.erl ... (oder --project FILE [--target T] -o PATH für ein ausgewähltes Ziel) kompiliert den Batch im Speicher, fügt das Startobjekt für den Einstiegspunkt hinzu und linkt eine ausführbare Datei:

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

-Os legt zusätzlich jede erzeugte und jede Runtime-Funktion und jedes Datenobjekt in einen eigenen Abschnitt und linkt mit --gc-sections (ELF), -dead_strip (Mach-O) oder /OPT:REF /OPT:ICF (MSVC), sodass Code, den kein Einstiegspfad erreicht, entfernt wird.

--lto kompiliert die Module und das Startmodul zu LLVM-Bitcode statt zu Objekten und linkt mit -flto -fuse-ld=lld, sodass LLD den erzeugten Code des Programms als eine Einheit gegen das native Runtime-Archiv optimiert. Modul- und Startdeskriptoren, exportierte Einstiegspunkte und main bleiben referenziert und überleben; Programme verhalten sich wie ohne die Option. Nur LLD liest den Bitcode dieses Compilers, daher wird --lto für Windows-MSVC- und ELF-Ziele akzeptiert; andere scheitern vor dem Linken mit --lto is not supported for target <triple>: it needs LLD. --lto braucht eine ausführbare Ausgabe (-o oder einen linkenden Projekt-Build). Das installierte Clang/LLD muss dasselbe LLVM-Release wie clau sein (23.1).

Lebendigkeit von Exporten

Eine ausführbare Datei lässt die Exporte weg, die sie nicht erreichen kann, sodass das Dead-Stripping von -Os und --lto Bibliothekscode entfernen, den das Programm nie aufruft. Direkt nach der Auflösung der Aufrufe, vor der Typinferenz, beginnt eine Analyse des ganzen Batches bei der Einstiegsfunktion und markiert als lebendig alles, was eine lebendige Funktion direkt aufruft (auch über -import und Auto-Importe von OTP), jedes fun F/A und literale fun M:F/A sowie die literalen Ziele von apply/3, spawn/3, spawn_link/3, spawn_monitor/3, spawn_opt/4,5, spawn_request/3,5, hibernate/3 und make_fun/3 (jede Stelligkeit von M:F, wenn die Argumentliste nicht literal ist), und file:write/2, sobald io:format/3, io:fwrite/3, io:put_chars/2 oder io:nl/1 lebendig ist (ihre Builtins schreiben darüber auf ein Prozessgerät). Sie bleibt konservativ:

Eine Funktion, die nichts Lebendiges erreicht, erhält überhaupt keinen Code. Ein weggelassener Export behält seinen Namen in der Exporttabelle des Moduls ohne Code, sodass function_exported/3 und module_info(exports) antworten, als wäre er exportiert, während ein dynamischer Aufruf, der ihn erreicht, undef auslöst (Unterschiede). Das kann nur geschehen, wenn ein Modulname von außerhalb der Analyse stammt: aus einem Stacktrace, einem Ausnahmeterm oder Daten von außerhalb des Programms. --verbose protokolliert das Ergebnis pro Modul (phase=liveness detail="dropped-exports=3" oder detail="kept-all-exports reason='m' is used as a value in main:main/1").

Eine Funktion, die nichts Lebendiges erreicht, wird auch nie typinferiert oder gegen ihre -spec geprüft: Die Inferenz deckt nur lebendigen Code ab, was für Programme schneller ist, die wenig von großen Bibliotheksmodulen nutzen, und die Fakten lebendiger Funktionen nur einengen kann, da unerreichbare Aufrufer ihre Argumente nicht mehr vereinigen. Eine Spezifikation, der nur unerreichbarer Code widerspricht, wird daher für --emit-Artefakte gemeldet, aber nicht für die ausführbare Datei.

--keep-exports (oder die Projektoption keep_exports = true) hält jeden Export aufrufbar. Die Analyse gilt für ausführbare Dateien (-o oder ein linkender Projekt-Build) und für IR- und Assembly-Inspektionen mit einem Einstiegspunkt (--entry oder das Manifest-entry des Ziels), die dann den Code der ausführbaren Datei zeigen; --emit-Artefakte, die für andere Programme gedacht sind, behalten jeden Export.

-g behält Erlang-Zeilentabellen für Debugger: in der ausführbaren Datei (ELF) oder in einer daneben veröffentlichten <name>.pdb (MSVC-Ziele) (Debugging).

Fehler (Exit 1)Diagnose
Kein Clangcannot find clang++ or clang on PATH; install LLVM/Clang or pass --linker / linker not found: X
Keine Runtimeruntime library not found: P; build the clause_runtime target or pass --runtime-library
Kein Archivruntime library is not a static library: P: ...
Falsches Zielruntime library P contains x86_64 coff objects, but the executable targets T; ...
Link-Fehlerlinking O failed: <clang> exited with status N:, gefolgt von der Ausgabe des Linkers (erste 64 KiB)
Ungültiges Zieloutput directory does not exist: D, artifact destination is not a regular file: O, artifact destination aliases an input: O

Escripts

Eine Quelldatei, deren erste Zeile mit #! beginnt, wird als escript kompiliert, in jedem Modus und mit jedem Dateinamen (positionelle Eingaben oder .erl-Dateien eines Projekts). Die Regeln folgen escript aus OTP 29 für Quelltext-Skripte:

Vergleich mit OTP

Goldens für Programm-Fixtures führen den Einstiegspunkt unter OTP mit denselben Regeln aus (Orakel); dasselbe Orakel erzeugt die Golden-Fälle für ausführbare Dateien, die der End-to-End-Runner unter jeder Policy linkt und ausführt. Unterschiede zu escript für gewöhnliche Module: Nicht abgefangene Ausnahmen enden mit 1 statt 127, und main/1 muss exportiert sein. Escript-Quelltexte behalten die Regeln von OTP (siehe oben).