Lyx Compiler – CLI Referenz
Der Lyx-Compiler (lyxc) ist ein moderner Cross-Compiler für Linux, Windows, macOS und Embedded-Systeme. Er kombiniert Compiler, Linker und statisches Analyse-Werkzeug in einem einzigen Binary.
Aufruf-Syntax
lyxc [Optionen] <Eingabedatei(en)>
# Einfaches Beispiel
lyxc main.lyx -o main
# Mehrere Quelldateien
lyxc main.lyx utils.lyx protocol.lyx -o app
# Cross-Compilation mit vollständigem Safety-Build
lyxc main.lyx --target=arm64 --target-energy=1 --static-analysis --lint -o firmware.elf
Flags können in beliebiger Reihenfolge angegeben werden. Kurzformen (‑o) und Langformen (--output) sind gleichwertig, wo beide existieren.
Stand der Schalter
Alle Schalter aus lyxc –help wurden gegen 1.1.14A einzeln nachgemessen — nicht nur am Rückgabewert, sondern am erzeugten Programm (Byte-Vergleich, file auf das Format, Lauf des Erzeugnisses).
<WRAP info>
Mit 1.1.12D sind die Assembler-Schalter umgesetzt. --emit-asm, --asm-listing und --dump-asm wurden bis dahin abgewiesen (#1370) — sie arbeiten jetzt. Auch --profile und --debug-symbols wirken inzwischen. Übrig bleibt ein einziger echter Mangel: die Optimierstufen sind untereinander nicht unterscheidbar. Wer eine ältere Fassung benutzt, findet den alten Stand in der Versionsgeschichte der Seite.
</WRAP>
| Gruppe | Anzahl | Bedeutung |
|---|---|---|
| arbeiten wie beschrieben | 44 | --target vollständig, --arch, --format, -I, --std-path, --shared, --target-energy, --emit=lbf, Linter, --debug, --debug-symbols, --runtime-checks, --verify-tmr, --mcdc-report, --seccomp-trap, --android-api, --dump-relocs, --map-file, --emit-asm, --asm-listing, --profile, die IR-Diagnose, --version/--build-info/--config |
| ausdrücklich abgewiesen | 1 | --trace — Exit 2 mit klarer Meldung; die Trace-Builtins arbeiten ohne Schalter |
| noch offen | 1 | siehe Kasten |
Was weiterhin nicht hält, was die Hilfe verspricht (gemessen mit 1.1.14B):
*-O0,-O1,-O2,-O3,-Osafeund--no-optliefern an demselben Programm byte-gleiche Erzeugnisse (4243 Byte in allen sechs Läufen). Die Stufen sind untereinander nicht unterscheidbar (#1371).
--mcdcbaut weiterhin keine Instrumentierung ein — das ist seit 1.1.12D aber kein Mangel mehr, sondern die Ansage: die Hilfe nennt den Schalter „MC/DC-Strukturanalyse (Uebersetzungszeit, keine Laufzeitmessung)„.--debug-symbolswirkt (Programm 4243 → 5095 Byte).
Was sich mit 1.1.12D bis 1.1.14A geändert hat:
| Schalter | vorher | jetzt (1.1.14A gemessen) |
|---|---|---|
--emit-asm | Exit 2, abgewiesen (#1370) | schreibt ein Assembler-Listing nach <ausgabe>.asm (im Prüflauf 87 KB), Programm unverändert |
--asm-listing | Exit 2, abgewiesen (#1370) | Auflistung mit Adressen, Bytes und Quellzeilen nach <ausgabe>.asm (seit 1.1.14B, #1862; bis 1.1.14A ging sie nach stdout); nicht gedeutete Bytes meldet sie ausdrücklich am Ende |
--dump-asm | Exit 2, abgewiesen (#1370) | umgesetzt (#1370 geschlossen) |
--profile | Exit 2, abgewiesen (#1370) | wirkt: Erzeugnis wächst von 4243 auf 4345 Byte |
--debug-symbols | „ohne Wirkung“ | bettet Debug-Info ein (4243 → 5095 Byte) |
--dump-relocs, --map-file | in den Detailtabellen als „nicht umgesetzt„ geführt | arbeiten: Relokationstabelle nach stdout, <ausgabe>.map (507 Byte) |
| Projektdatei | gab es nicht | lyxc projekt.lpf — siehe Projektdatei *.lpf |
Was sich mit 1.0.20F geändert hat:
| Schalter | vorher | jetzt |
|---|---|---|
--dump-ir, --ir-source-map, --provenance | erzeugten ein Programm mit Exit 42 | erzeugen ein lauffähiges Programm, identisch zum Bau ohne den Schalter (#1523) |
--config | Exit 1, 61 Zeilen mit angehängter Hilfe | Exit 0, 4 Zeilen (#1527) |
--format=pe | lieferte ELF | liefert PE32+ (#1526) |
--arch=xtensa | lieferte still x86-64 | wird abgewiesen (#1526) |
--seccomp-trap | ohne Wirkung | SECCOMP_RET_TRAP statt KILL_PROCESS (#1526) |
--android-api | nahm jeden Wert an | weist Werte außerhalb des Bereichs ab (#1526) |
--trace | ohne Wirkung | wird abgewiesen (#1370) |
--mcdc-report | zählte a && b als eine Bedingung | zählt richtig: n Bedingungen → n+1 Testfälle (#1524) |
Zwei Schalter werden angenommen, fehlen aber in lyxc –help: --dump-ir und --meta-safe.
1. Eingabe & Ausgabe
| Flag | Kurzform | Beschreibung |
|---|---|---|
--output=<datei> | -o | Ausgabedatei. Standard: a.out (Linux/macOS) / a.exe (Windows) |
--include=<pfad> | -I | Suchpfad für Units und Module. Mehrfach verwendbar: -I src -I lib |
--std-path=<pfad>'' | – | Überschreibt den Pfad zur Standardbibliothek. Ohne Angabe sucht ''lyxc'' in dieser Reihenfolge: relativ zur Quelldatei → ''-I''/''LYX_PATH'' → ''--std-path/LYX_STD_PATH → Installationspfad /usr/include/lyx/units (seit 1.0.17I, #1368 — eine Umgebungsvariable ist nach der Paketinstallation nicht mehr nötig) | ||
--format=<fmt> | – | Ausgabeformat: elf, pe, macho — seit 1.0.20F wirken alle drei (#1526) |
--output-type=<typ> | – | executable (Standard) oder shared-lib |
--shared | – | Kurzform für --output-type=shared-lib |
--compile-unit | – | Kompiliert eine .lyx-Datei zu einer vorkompilierten .lyu-Unit |
--map-file | – | Symbol- und Sektionskarte als <ausgabe>.map (seit 1.0.20A, #1370) |
Es gibt keine Linker-Flags.--lib-path/-L,--link/-lund--staticexistieren nicht —lyxcerzeugt statische ELF-Dateien und bindet C-Bibliotheken überextern fn … link „libfoo.so“im Quelltext ein (→ FFI).--no-libc-initwird dagegen angenommen, obwohl es inlyxc --helpnicht auftaucht.
Beispiele
# Normaler Build (Linux)
lyxc main.lyx -o myapp
# Shared Library erstellen
lyxc mylib.lyx --shared -o libmylib.so
# Unit vorkompilieren
lyxc --compile-unit src/utils.lyx
# → erzeugt: src/utils.lyu
2. Target & Architektur
lyxc ist vollständig self-contained: kein externer Linker (kein ld, lld o. ä.) nötig. Der Compiler schreibt ELF64/ELF32/PE32+/Mach-O direkt in einem Schritt.
→ Ausführlicher Guide: Cross-Compilation
--target=<TARGET>
| Target-String | Alias | Architektur | Format | Status |
|---|---|---|---|---|
linux | x86_64 | x86_64 | ELF64 | Stabil |
arm64 | linux-arm64 | ARM64 Linux | ELF64 | Stabil * |
linux-riscv64 | riscv, riscv64 | RV64GC Linux | ELF64 | Stabil * |
arm-cm4 | arm-cm33 | ARM Cortex-M4/M33 | ELF32 | Stabil |
arm_cm | – | ARM Cortex-M (generisch) | ELF32 | Stabil |
win64 | windows-x86_64 | Windows x64 | PE32+ | Stabil |
windows-arm64 | – | Windows ARM64 | PE32+ | Stabil |
macosx64 | macos-x86_64 | macOS x86_64 | Mach-O | Stabil |
macos-arm64 | – | macOS ARM64 (Apple Silicon) | Mach-O | Stabil |
android | android-arm64 | Android ARM64 (.so) | ELF64 | Stabil |
android-x86_64 | – | Android x86_64 (Emulator) | ELF64 | Stabil |
esp32 | esp32s3 | Xtensa LX6 (ESP32) | ELF32 | Experimentell |
* StrConcat fehlt auf arm64 und riscv (#2028, nachgemessen mit lyxc 1.2.5C):
error: arm64: Builtin-ID 7 wird im Linux-Zweig nicht behandelt
error: riscv: Builtin-ID 7 wird nicht behandelt
Damit lässt sich für diese beiden Ziele praktisch kein Programm bauen, das einen berechneten Wert mit Text verbindet. Die übrigen String-Builtins sind in Ordnung — geprüft mit IntToStr, StrLen, FloatToStr und StrSub. Der Rest der IR-Ziele wurde mit #2018, #2019 und #2022 gerade nachgezogen: zuvor waren 33 bzw. 41 stdlib-Units für arm64 unbaubar.
lyxc main.lyx --target=arm64 -o firmware.elf
lyxc main.lyx --target=win64 -o app.exe
lyxc main.lyx --target=linux-riscv64 -o controller.elf
lyxc mylib.lyx --target=android --output-type=shared-lib -o libmylib.so
Alle Ziele wurden mit file auf das erzeugte Format geprüft und liefern das jeweils richtige: PE32+ für win64, Mach-O für die macOS-Ziele, ARM aarch64, RISC-V. esp32 bricht mit einer klaren Meldung ab (Zeichenkettenliterale sind fuer xtensa nicht umgesetzt) — das ist der ehrliche Umgang mit einer Lücke.
--arch=<ARCH>
Erzwingt eine spezifische CPU-Architektur, unabhängig vom Target:
lyxc main.lyx --target=linux --arch=arm64 -o cross.elf
Verfügbare Werte: x86_64, arm64, xtensa, riscv64, arm_cm
Seit 1.0.20F wird–arch=xtensaabgewiesen, statt still ein x86-64-Programm zu erzeugen (#1526). Für Xtensa führt der Weg über–target=esp32, das die eigentliche Lücke benennt (Zeichenkettenliterale sind fuer xtensa nicht umgesetzt).
x86_64,arm64undriscv64arbeiten korrekt und liefern jeweils das passende ELF.
--format=<fmt>
Seit 1.0.20F wirken alle drei Werte (#1526): –format=pe liefert ein PE32+, –format=macho ein Mach-O. Vorher kam in allen Fällen ELF heraus.
--format=elf → ELF 64-bit LSB executable, x86-64
--format=pe → PE32+ executable (console) x86-64, for MS Windows
Bequemer bleibt der Weg über –target, weil dieser zugleich die Architektur und die Aufrufkonvention festlegt.
Seit 1.1.3E ist das PE-Ziel auch für fremde Bibliotheken benutzbar: extern fn … link „x.dll“ erscheint in der Import-Tabelle, Argumente gehen nach Microsoft-x64-Konvention, und eine Relokationstabelle über einer Seite (0x1000) sprengt SizeOfImage nicht mehr — vorher lehnte Windows solche Dateien als „Fehlerhaftes EXE-Format“ ab, das Programm startete gar nicht (#1672, #1671, #1674, #1676). Einzelheiten in FFI — Windows-DLLs.
3. Optimierung & Energy-Awareness
Energy-Awareness-Annotationen und Compiler-Optimierungen:
--target-energy=<1–5>
Steuert das Energy-Aware-Backend. Beeinflusst Loop Unrolling, SIMD-Nutzung, Inlining-Aggressivität und Instruktions-Scheduling.
| Level | Name | Loop Unrolling | SIMD | Inlining | Einsatz |
|---|---|---|---|---|---|
| 1 | Minimal | 2× | Nein | Konservativ | IoT, Batterieknoten |
| 2 | Low | 4× | Nein | Moderat | Mobile Embedded |
| 3 | Standard | 4× | Optional | Ausgewogen | Server, Desktops |
| 4 | High | 8× | Ja | Aggressiv | Hochleistungs-Server |
| 5 | Extreme | 8× + SIMD | Ja (AVX2/NEON) | Maximal | DSP, HPC, ML-Inferenz |
Der Schalter wirkt tatsächlich, und zwar deutlich — dasselbe Programm über alle fünf Stufen:
Stufe 1: 33 107 Byte
Stufe 2: 49 491 Byte
Stufe 3: 94 547 Byte = Standard, entspricht dem Aufruf ohne Schalter
Stufe 4: 94 547 Byte identisch mit Stufe 3
Stufe 5: 237 907 Byte
Damit ist –target-energy der einzige Schalter dieses Abschnitts, der etwas bewirkt — er übernimmt die Rolle, die anderswo -O hätte.
Stufe 4 ist byte-identisch mit Stufe 3. Die Tabelle oben verspricht für Stufe 4 doppeltes Unrolling, SIMD und aggressiveres Inlining; erzeugt wird dasselbe Programm wie bei Stufe 3. Wirksam unterschieden sind nur 1, 2, 3/4 und 5.
Ein Wert außerhalb von 1–5 bricht ab (Exit 2).
lyxc node.lyx --target=arm64 --target-energy=1 -o sensor.elf # Batterie-optimiert
lyxc dsp.lyx --target=linux --target-energy=5 -o dsp.out # Max-Performance
--no-opt und -O<0-3> — beide ohne Wirkung
–no-opt und -O0 schalten seit 1.0.20A die Vereinfachungen ab, die der Codegen beim Emittieren vornimmt — Konstantenfaltung und tote Zweige (#1371). Das Erzeugnis unterscheidet sich messbar:
Standard d61a5580b507 4216 B
-O0 917cb3e9c87e 4222 B
--no-opt 917cb3e9c87e 4222 B
-O3 d61a5580b507 4216 B
-O0und--no-optunterscheiden sich inzwischen vom Rest (#1647, nachgemessen mit lyxc 1.2.2B): sie erzeugen ein anderes Erzeugnis als der Aufruf ohne Schalter.-O1,-O2und-O3liefern weiterhin untereinander dasselbe — und dasselbe wie der Standardaufruf.
Gemessen an einem Schleifenprogramm (115304 Byte in allen Fällen, Prüfsummen):
^ Aufruf ^ Erzeugnis ^
| ohne Schalter (=-O2) |93820736…|
|-O1·-O2·-O3|93820736…— identisch zum Standard |
|-O0·--no-opt|d7109877…— abweichend |
Ein abgestufter IR-Optimierer ist das nicht: es gibt eine Optimierung, die sich mit-O0abschalten lässt — plus-Osafeals eigene, vorsichtigere Fassung.--helpnennt-O2als Standard.
-Osafegibt es inzwischen (#1525, nachgemessen mit lyxc 1.2.2D): der Schalter wird angenommen, steht in--helpund erzeugt ein drittes, von-O0und-O1…-O3verschiedenes Erzeugnis — „nur nachweislich sichere Umformungen„. Frühere Fassungen meldeten hier fünf Fehlermeldungen, weil der Parser den Namen zeichenweise zerlegte.
Die Fehlerbehandlung von -O arbeitet korrekt: -O, -O9 und -Ox brechen mit lyxc: -O erwartet eine Stufe 0..3 und Exit 2 ab.
-O0 übersetzt dasselbe Programm wie die höheren Stufen. Bis lyxc 1.1.3B wies es gültige Enum-Konstanten aus importierten Units ab (der Wert von AL_NONE muss zur Uebersetzungszeit feststehen), weil die Konstantenfaltung für Enums nur im Optimierer stattfand statt in der Semantikprüfung (#1647). Damit fiel gerade die Stufe aus, die man beim Eingrenzen von Codegen-Fehlern zuerst greift.
Für stärkeren Einfluss auf die Codeerzeugung bleibt –target-energy.
--no-fp-foldund--inline-thresholdgibt es nicht. Wer Fließkomma-Umordnung unterbinden will, annotiert die betroffene Funktion mit@flight_crit(→ Attribute); die Inline-Grenze ist nicht einstellbar.
4. Safety & Verifikation (DO-178C)
Diese Flags sind für die Zertifizierung sicherheitskritischer Software gedacht. Gemessen mit 1.1.14A.
| Flag | Beschreibung |
|---|---|
--static-analysis | Statische Analyse: Data-Flow, Live-Variablen, Stack |
--call-graph | Statischer Aufrufgraph — Grundlage für WCET-Abschätzung und Rekursionserkennung |
--runtime-checks | Laufzeitprüfungen: Bereichsgrenzen, Null-Zeiger, Division durch null |
--mcdc | MC/DC-Strukturanalyse zur Übersetzungszeit; baut ausdrücklich keine Laufzeitmessung ein, das Erzeugnis bleibt byte-gleich |
--mcdc-report | Coverage-Bericht nach der Übersetzung; zählt seit 1.0.20F richtig (#1524) |
--verify-tmr | Bilanz der @redundant-Zugriffe; Fehler, wenn ein Zugriff am Voter vorbeigeht |
--asm-listing | Auflistung mit Adressen, Bytes und Quellzeilen (DO-178C 6.1) nach <ausgabe>.asm — seit 1.1.12D umgesetzt, seit 1.1.14B in der Datei statt auf stdout (#1862) |
--map-file | Symbol- und Sektionskarte als <ausgabe>.map — arbeitet |
--provenance | Provenance-Tracking IR → AST → Quelle; Erzeugnis unverändert (#1523) |
--meta-safe | .meta_safe-Section mit CRC32 je 4096-Byte-Page; wirkt, steht aber nicht in --help |
MC/DC: der Bericht misst nicht, was er nennt
--mcdc-reportzählt jede Entscheidung als genau eine Bedingung (#1524). Vier Funktionen mit 1, 2, 3 und 4 Bedingungen ergeben denselben Bericht:
> [MC/DC] Eins: 1 decisions, 1 conditions → min 2 test cases > [MC/DC] Zwei: 1 decisions, 1 conditions → min 2 test cases // a > 0 && b > 0 > [MC/DC] Drei: 1 decisions, 1 conditions → min 2 test cases // drei Bedingungen > [MC/DC] Vier: 1 decisions, 1 conditions → min 2 test cases // vier Bedingungen >
^ Bedingungen ^ gemeldet ^ korrekt (n+1) ^
| 1 | 2 | 2 |
| 2 | 2 | 3 |
| 3 | 2 | 4 |
| 4 | 2 | 5 |
Genau die Aufschlüsselung zusammengesetzter Bedingungen ist das, was MC/DC von einfacher Zweigüberdeckung unterscheidet. Der Bericht misst derzeit Zweigüberdeckung.
--mcdcbaut zudem keine Instrumentierung ein — das Programm ist mit und ohne den Schalter byte-identisch. Es gibt also nichts, was zur Laufzeit Überdeckung aufzeichnen könnte.
Brauchbar ist der Bericht als Strukturübersicht: er nennt Anzahl und Ort der Entscheidungspunkte je Funktion. Für einen Überdeckungsnachweis nach DO-178C Level A reicht das nicht — die Mindestzahl der Testfälle muss von Hand ermittelt werden.
Die Stack-Prüfung braucht kein Flag
@stack_limit wird bei jeder Übersetzung ausgewertet — ein früher hier dokumentiertes --stack-check gibt es nicht und ist auch nicht nötig:
$ lyxc rekursiv.lyx -o /dev/null
error: F: @stack_limit ist mit Rekursion nicht nachweisbar — die Aufruftiefe ist unbeschraenkt
Der Nachweis für @stack_limit selbst — Rahmengröße gegen die Schranke, Aufrufgraph bei Rekursion — wird seit lyxc 1.0.14K geführt, @wcet seit 1.0.14L, @flight_crit seit 1.0.14M; @redundant wirkt seit 1.0.15A auch an globalen Variablen und wird mit --verify-tmr geprüft. Ohne Nachweis bleiben @integrity, @dal und @critical — sie sind Vermerk, nicht Beweis.
Der MC/DC-Dreischritt aus früheren Fassungen läuft so nicht.--mcdc-instrument,--coverage-reportund--run-testsexistieren nicht. Vorhanden sind--mcdc(instrumentieren) und--mcdc-report(Bericht nach der Übersetzung, ohne.cov-Datei).
Ebenfalls nicht vorhanden:--wcet,--integrity-check,--symbol-sizes,--lint-strict.
--provenance
lyxc flight.lyx --provenance --target=arm64 -o flight.elf
Erfasst werden Quelldatei-Hash, Compiler-Version, Flags, Ziel und die importierten Units.
Bis 1.0.20E erzeugte dieser Aufruf ein nicht lauffähiges Programm (Exit 42). Seit 1.0.20F ist das Erzeugnis mit dem Bau ohne den Schalter identisch (#1523) — Diagnose und Auslieferungsstand entstehen also im selben Lauf, ein getrennter Aufruf ist nicht mehr nötig.
Für den Nachweis gehört die Compiler-Version aus lyxc –build-info ins Prüfprotokoll — bei dieser Doku 1.0.19E.
5. Analyse & Debugging
| Flag | Beschreibung |
|---|---|
--dump-ir | IR ausgeben; Erzeugnis unverändert (#1523). Fehlt in --help |
--ir-source-map | IR-Source-Mapping; Erzeugnis unverändert (#1523) |
--emit-asm | Assembler-Listing nach <ausgabe>.asm — seit 1.1.12D umgesetzt |
--emit=lbf | IR als .lbf-Bytecode (nur --target=lyxos) |
--ast-dump | AST nach dem Parsen anzeigen |
--symtab-dump | Symboltabelle ausgeben |
--trace-passes | Jeden Compiler-Pass mit Dauer protokollieren |
--trace-imports | Modul-Auflösung debuggen: welche Pfade je import durchsucht werden |
--type-reasoning | Herleitung des Typprüfers anzeigen |
--constraint-log | Constraint-Log ausgeben |
--dump-relocs | Relokationstabelle nach stdout (=== RELOCATION TABLE ===); arbeitet |
--debug | Debug-Informationen einbetten |
--profile | Laufzeitmessung je Funktion (nur x86-64) — seit 1.1.12D umgesetzt; das Erzeugnis wächst messbar |
--trace | wird abgewiesen (#1370); die Trace-Builtins arbeiten ohnehin immer |
--dump-relocs und --map-file
Beide sind seit 1.0.20A umgesetzt (#1370) und ersetzen einen Teil dessen, was –emit-asm leisten sollte.
lyxc main.lyx --dump-relocs -o main
=== RELOCATION TABLE ===
OFFSET ART ZIEL
0x0000000000000033 STR +32
0x000000000000003A STR +40
0x000000000000003F CALL main
–map-file legt die Karte neben dem Erzeugnis ab — bei -o main.bin also main.bin.map:
Lyx-Abbildkarte fuer h.bin
Sektionen
NAME ADRESSE LAENGE
.text 0x00000000004000b0 3920
.data 0x0000000000401000 122
Anders als die drei Schalter im nächsten Abschnitt verändern beide das erzeugte Programm nicht.
--trace
Der Schalter wird seit 1.0.20F abgewiesen (Exit 2, #1370) — vorher wurde er angenommen und tat nichts. Die Trace-Builtins trace, trace_int und trace_str arbeiten unabhängig davon; wer die Ausgaben loswerden will, entfernt die Aufrufe aus dem Quelltext.
5b. KI-Integration (nicht verdrahtet)
Für KI-Agenten, IDEs und Build-Tooling sind zwei Flags vorgesehen, die JSON (Daten & Serialisierung) auf stdout schreiben: --ast-json (Parser-AST) und --error-json (strukturierte Sema-Fehler).
Beide Flags sind auch in 1.0.19E nicht erreichbar und brechen den Aufruf mitunbekannter Schalterund Exit 2 ab. Die Bausteine liegen im Repository (src/backend/ast_json.lyx,src/error_collector.lyx), sind aber insrc/lyxc.lyxan keine Kommandozeile angeschlossen — auch nicht aufdevelop(1.0.16A).
Das dokumentierte JSON-Schema bleibt gültig: KI-Integration — Datenformat und interne API.
6. Linter & Verifikation
Der integrierte Linter läuft als Teil des Compile-Prozesses oder eigenständig.
| Flag | Beschreibung |
|---|---|
--lint | Aktiviert alle Standard-Warnungen |
--lint-only | Nur Lint, keine Binärdatei erzeugen (schneller Feedback) |
--no-lint | Linter-Warnungen abschalten |
-wa / -we | Alle Warnungen / Warnungen als Fehler |
--verify-tmr | Prüft ob alle @redundant-Variablen korrekt dreifach vorliegen |
--static-analysis | Erweiterte statische Analyse (Null-Pointer, uninit. Vars, dead code) |
Lint-Kategorien
| Warnung | Auslöser |
|---|---|
unused-var | Variable deklariert, nie gelesen |
unused-import | import ohne Verwendung im Modul |
risky-cast | as-Konvertierung mit möglichem Datenverlust (f64→int32, int64→uint8) |
unbounded-loop | while ohne limit in @dal(A/B)-Modul |
null-deref | Pointer-Dereferenz ohne vorherigen null-Check |
unreachable-code | Code nach return oder break |
missing-case | match über Enum ohne vollständige Abdeckung |
unsafe-in-dal | unsafe-Block in @dal(A/B)-Modul |
$ lyxc main.lyx --lint-only
main.lyx:12: Warnung [unused-var] 'temp' wird nie gelesen
main.lyx:28: Warnung [risky-cast] int64 → uint8 (mögliche Truncation)
main.lyx:41: Warnung [unbounded-loop] while ohne 'limit' in @dal(B)-Modul
main.lyx:55: Fehler [unsafe-in-dal] unsafe-Block in @dal(A)-Modul nicht erlaubt
3 Warnungen, 1 Fehler
7. Vollständige Flag-Referenz
Stand lyxc 1.0.19E, abgeglichen mit lyxc –help und je Schalter nachgerufen — mit Vergleich des Erzeugnisses, nicht nur des Rückgabewerts. Andere als die hier genannten Schalter werden seit 1.0.15D abgewiesen (Exit 2).
Eingabe und Ausgabe
| Flag | Beschreibung |
|---|---|
-o <datei> | Ausgabedatei (Standard: a.out) |
-I <pfad> | Include-Pfad für Module. Mehrfachangabe wirkt seit lyxc 1.1.6C (#1736, nachgemessen mit 1.1.11B): alle angegebenen Pfade werden durchsucht, und ein nicht existierender Pfad in der Liste macht den Bau nicht mehr kaputt |
--std-path=PATH | Pfad zur Standardbibliothek überschreiben |
--format=<fmt> | Ausgabeformat: elf, pe, macho |
--output-type=<typ> | executable (Standard) oder shared-lib |
--shared | Kurzform für --output-type=shared-lib |
Ziel und Architektur
| Flag | Beschreibung |
|---|---|
--target=TARGET | win64, linux, arm64, macosx64, macos-arm64, esp32, riscv, android-arm64, android-x86_64, lyxos, lyxos-kernel — alle geprüft, alle liefern das richtige Format |
--arch=ARCH | x86_64, arm64, riscv wirken; xtensa erzeugt still x86-64 (#1526) |
--format=fmt | nur elf wirkt; pe und macho werden angenommen und liefern trotzdem ELF (#1526) |
--android-api=N | Android-API-Level; Werte außerhalb des Bereichs werden seit 1.0.20F abgewiesen (#1526) |
--output-type=<typ>'' / ''--shared | executable oder shared-lib; beide arbeiten korrekt |
Optimierung
| Flag | Beschreibung |
|---|---|
--target-energy=<1-5> | Energy-Level des Backends; Vorgabe 3. Ungültige Werte werden abgewiesen. Der einzige wirksame Schalter dieser Gruppe — Stufe 4 ist allerdings identisch mit 3 |
-O0 | schaltet Konstantenfaltung und tote Zweige ab (seit 1.0.20A, #1371) |
-O1 … -O3 | untereinander wirkungslos — alle drei entsprechen dem Aufruf ohne Schalter |
--no-opt | gleichbedeutend mit -O0 |
Linter
| Flag | Beschreibung |
|---|---|
--lint | Linter-Warnungen einschalten |
--lint-only | Nur linten, nicht übersetzen |
--no-lint | Linter-Warnungen abschalten |
-wa / -we | Warnungen alle / als Fehler; ohne a bzw. e bricht der Aufruf ab |
Safety und Verifikation (DO-178C)
| Flag | Beschreibung |
|---|---|
--static-analysis | Statische Analyse (Data-Flow, Live-Vars, Stack) |
--call-graph | Statischer Aufrufgraph (WCET, Rekursionserkennung) |
--runtime-checks | Laufzeitprüfungen: Bereichs-, Null- und Division-durch-null-Prüfung |
--mcdc | baut keine Instrumentierung ein (#1524) — Programm byte-identisch |
--mcdc-report | Strukturbericht; zählt zusammengesetzte Bedingungen als eine (#1524) |
--verify-tmr | Bilanz der @redundant-Zugriffe; Fehler, wenn einer am Voter vorbeigeht — arbeitet korrekt |
--asm-listing | Auflistung mit Adressen, Bytes und Quellzeilen (DO-178C 6.1) nach <ausgabe>.asm — umgesetzt seit 1.1.12D, in der Datei statt auf stdout seit 1.1.14B (#1862) |
--map-file | Symbol- und Sektionskarte als <ausgabe>.map (seit 1.0.20A, #1370) |
--provenance | Provenance-Tracking IR → AST → Quelle; Erzeugnis unverändert (#1523) |
--meta-safe | .meta_safe-Section mit CRC32 je 4096-Byte-Page; wirkt, fehlt aber in --help |
Analyse und Fehlersuche
| Flag | Beschreibung |
|---|---|
--dump-ir | IR ausgeben; Erzeugnis unverändert (#1523); fehlt in --help |
--ir-source-map | IR-Source-Mapping; Erzeugnis unverändert (#1523) |
--emit-asm | Assembler-Listung nach <ausgabe>.asm, ohne Quellzeilen — umgesetzt seit 1.1.12D |
--emit=lbf | IR als .lbf-Bytecode (nur --target=lyxos); korrekt gekoppelt |
--dump-relocs | Relokationstabelle nach stdout: Offset, Art, Ziel (seit 1.0.20A, #1370) |
--ast-dump | AST nach dem Parsen |
--symtab-dump | Symboltabelle |
--trace-imports | Import-Auflösung |
--trace-passes | Transformationen mitschreiben |
--static-analysis / --call-graph | erzeugen Zusatzausgabe, verändern das Programm nicht |
--type-reasoning | Herleitung des Typprüfers |
--constraint-log | Constraint-Log |
--debug | Debug-Informationen einbetten — vergrößert das Programm nachweislich |
--runtime-checks | Laufzeitprüfungen — vergrößert das Programm nachweislich |
--profile | Funktionsaufruf-Instrumentierung — umgesetzt seit 1.1.12D; das Erzeugnis waechst messbar |
--trace | wird abgewiesen (#1370); die Trace-Builtins arbeiten ohnehin immer |
Unit-Kompilierung
| Flag | Beschreibung |
|---|---|
--compile-unit | Unit zu .lyu vorkompilieren |
--debug-symbols | Debug-Info in die .lyu einbetten — wirkt seit #1555: mit 1.1.2E nachgemessen 705 B ohne, 724 B mit |
--unit-info <datei> | Informationen über eine .lyu anzeigen |
--include <hdr.h> | C-Header einlesen und extern-Deklarationen ausgeben |
Werkzeug-Qualifizierung (TOR)
| Flag | Beschreibung | Verhalten |
|---|---|---|
--version | Versionsnummer (TOR-001) | 2 Zeilen, Exit 0 |
--build-info | Build-Identifikation (TOR-002) | 5 Zeilen, Exit 0 |
--config | Aktive Konfiguration (TOR-003) | 4 Zeilen, Exit 0 (seit 1.0.20F, #1527) |
--help | Hilfe |
Seit 1.0.20F arbeitet –config wie die beiden anderen TOR-Schalter: Exit 0, vier Zeilen, keine angehängte Hilfe (#1527). Vorher endete der Aufruf mit Exit 1 und gab 61 Zeilen aus — in einem Skript galt er damit als fehlgeschlagen.
Diese früher hier dokumentierten Flags gibt es nicht — sie brechen den Aufruf seit 1.0.15D mitlyxc: unbekannter Schalterund Exit 2 ab:
--stack-check,--wcet,--no-fp-fold,--inline-threshold,--lint-strict,--mcdc-instrument,--coverage-report,--integrity-check,--symbol-sizes,--emit-ir,--emit-map,--debug-level,--define/-D,--lib-path/-L,--link/-l,--static,--run-tests,--ast-json,--ast-json-pretty,--error-json.
Ersatz, soweit vorhanden:--stack-checkbraucht es nicht — die@stack_limit-Prüfung läuft immer und meldet etwa@stack_limit ist mit Rekursion nicht nachweisbarauch ohne Flag. Statt--emit-irgibt es--dump-ir, statt--wcetdas--call-graph, statt--stack-checkdas--static-analysis, statt--lint-strictdas--lint, statt--mcdc-instrumentdas--mcdc. Für--emit-mapsteht--map-filebereit — es arbeitet seit 1.0.20A (#1370).
--no-libc-initsteht nicht in dieser Liste — es wird angenommen, obwohllyxc --helpes nicht nennt.
8. Beispiel-Aufrufe
Typische Aufrufmuster:
A) Schneller Entwicklungs-Build
lyxc main.lyx -o main
./main
B) Debug-Build mit Stack-Trace
lyxc main.lyx --debug --no-opt -o main_dbg
./main_dbg
# Bei Absturz: vollständiger Stack-Trace mit Zeilennummern
C) Lint-Check für CI/CD
lyxc main.lyx --lint-only -we
# -we behandelt Warnungen als Fehler; Exit != 0 laesst die Pipeline scheitern
D) Cross-Compilation: ARM64 (Raspberry Pi / Server)
lyxc main.lyx \
--target=arm64 \
--target-energy=3 \
-o app.elf
# Auf dem Zielgerät ausführen:
scp app.elf pi@raspberrypi:~/
ssh pi@raspberrypi ./app.elf
E) IoT-Build: ESP32 (Batterie-optimiert)
lyxc sensor.lyx \
--target=esp32 \
--target-energy=1 \
--static-analysis \
-o sensor.elf
F) Luftfahrt-Zertifizierung (DAL A)
Seit 1.0.20F genügt ein Aufruf: –provenance verändert das Erzeugnis nicht mehr (#1523), –map-file arbeitet seit 1.0.20A. –asm-listing legt seit 1.1.14B die Auflistung mit Quellzeilen als <ausgabe>.asm ab (#1862) — ein Griff zu objdump -d ist dafür nicht mehr nötig.
lyxc flight_control.lyx \
--target=arm64 \
--call-graph \
--static-analysis \
--verify-tmr \
--runtime-checks \
--lint \
--mcdc-report \
--provenance \
--map-file \
-o evidence/fcc.elf > evidence/analyse.log 2>&1
Analysen, Traceability-Protokoll, Speicherkarte (evidence/fcc.elf.map) und Auslieferungsstand entstehen damit im selben Lauf — die frühere Lücke, dass geprüfte Artefakte und ausgeliefertes Programm aus verschiedenen Übersetzungen stammten, entfällt.
G) Energieprofil vergleichen
# Level 1: Batterie-optimiert
lyxc dsp.lyx --target-energy=1 -o dsp_low.elf
# Level 5: Maximum-Performance
lyxc dsp.lyx --target-energy=5 -o dsp_high.elf
# Größenvergleich
ls -l dsp_low.elf dsp_high.elf
Gemessen an einem kleinen Testprogramm über alle fünf Stufen:
Stufe 1: 33 107 Byte
Stufe 2: 49 491 Byte
Stufe 3: 94 547 Byte (Vorgabe)
Stufe 4: 94 547 Byte identisch mit Stufe 3
Stufe 5: 237 907 Byte
Der Faktor zwischen Stufe 1 und Stufe 5 beträgt hier gut sieben. Die absoluten Zahlen hängen vom Programm ab, das Verhältnis gibt aber die Größenordnung wieder.
H) Compiler-Performance analysieren
lyxc main.lyx --trace-passes -o main 2>&1 | grep "^\[pass\].*done"
# [pass] sema: done (1ms / 1337µs) <- Dauer je Pass, langsamste zuerst sortierbar
I) Provenance-Log für Audit
lyxc main.lyx --provenance --target=arm64 -o /dev/null > audit/provenance.log
Ausgegeben wird eine Zuordnung von IR-Instruktionen über AST-Knoten zur Quellzeile:
=== PROVENANCE ===
IR[0] irLoadLocal -> AST[6] IF -> src:main.lyx:1
IR[1] irConstInt -> AST[6] IF -> src:main.lyx:1
IR[2] irCmpLe -> AST[6] IF -> src:main.lyx:1
<WRAP alert> Drei Dinge weichen von früheren Fassungen dieser Seite ab:
- Es entsteht keine
.prov-Datei. Die Ausgabe geht ausschließlich nach stdout und muss umgeleitet werden. - Erfasst wird nicht Quelldatei-Hash, Compiler-Version, Flags und Ziel, sondern allein die IR→AST→Quelle-Zuordnung. Version und Ziel holt man sich aus
--build-info. - Die Zeilennummern stimmen weitgehend nicht (#1523): bei einem 22-zeiligen Programm mit drei Funktionen verwiesen 77 von 85 Einträgen auf Zeile 1 — die Importzeile. Für einen Traceability-Nachweis nach DO-178C 6.4.4.2b reicht das nicht.
Seit 1.0.20F ist das dabei erzeugte Programm regulär lauffähig; -o /dev/null steht hier nur, weil allein das Protokoll gebraucht wird.
</WRAP>
9. Kein --define / -D
lyxc kennt kein --define / -D-Flag für Präprozessor-Symbole, weil Lyx keinen Präprozessor hat. Die Alternativen:
| C-Äquivalent | Lyx-Weg |
|---|---|
-DDEBUG=1 | con DEBUG: bool := true; in einer Konfigurationsdatei oder Unit |
-DMAX_SIZE=1024 | con MAX_SIZE: int64 := 1024; |
-DPLATFORM_ARM | –target=arm64 + plattformspezifische Include-Pfade (–include) |
#pragma once / Header Guards | Nicht nötig — jede .lyx-Datei ist eine Unit mit eindeutigem Namen |
→ Ausführlich: Bedingungen – Kein Präprozessor in Lyx (Abschnitt 7)
Weiterführende Seiten:
Letzte Aktualisierung: 2026-09-05 (#1647, nachgemessen mit lyxc 1.2.2B) — -O-Kasten präzisiert: -O0/--no-opt erzeugen inzwischen ein anderes Erzeugnis, -O1…-O3 bleiben untereinander gleich.
Vorherige letzte Aktualisierung: 2026-08-31 — die drei Assembler-Schalter gegen 1.1.15B nachgemessen (#1862 geschlossen): –dump-asm schreibt nach stdout, –emit-asm die Datei ohne Quellzeilen, –asm-listing die Datei mit Quellzeilen. Zuvor am 2026-08-30 alle Schalter gegen 1.1.14A gemessen. Neu: Projektdatei *.lpf (eigene Seite). –emit-asm/–asm-listing/–dump-asm sind umgesetzt (#1370 geschlossen), ebenso –profile und –debug-symbols; –dump-relocs und –map-file arbeiten. Offen bleibt allein, dass die Optimierstufen untereinander byte-gleich sind (#1371).
Vorherige Aktualisierung: 2026-08-16 — alle Schalter gegen 1.0.20F neu gemessen (Byte-Vergleich, file, Lauf des Erzeugnisses). Von dreizehn zuvor defekten Schaltern sind elf in Ordnung: –dump-ir/–ir-source-map/–provenance liefern wieder ein lauffähiges Programm (#1523), –mcdc-report zählt Bedingungen richtig (#1524), –format und –arch wirken (#1526), –config endet mit Exit 0 (#1527). Offen: –mcdc instrumentiert nicht, –debug-symbols ohne Wirkung, -O1..-O3 untereinander gleich (#1371).
