====== Cross-Compilation mit Lyx ======
''lyxc'' ist ein self-contained Cross-Compiler: kein externer Linker, keine separate Toolchain-Konfiguration. Eine einzige Binary erzeugt nativen Code für alle unterstützten Zielplattformen.
→ [[lyx_-_programmiersprache:guides|Guides]] · [[lyx_-_programmiersprache:tools:compiler-parameter|Compiler-Parameter]]
----
===== Alle Zielplattformen =====
^ Target-String ^ Alias ^ Architektur ^ Format ^ ABI ^ Status ^
| ''linux'' | ''x86_64'' | x86_64 | ELF64 | SysV AMD64 | Stabil |
| ''arm64'' | ''linux-arm64'' | ARM64 | ELF64 | AAPCS64 | Stabil |
| ''linux-riscv64'' | – | RV64GC | ELF64 | LP64D | Stabil |
| ''riscv'' | ''riscv64'' | RV64GC | ELF64 | LP64D | Stabil |
| ''arm-cm4'' | ''arm-cm33'' | ARM Cortex-M4/M33 | ELF32 | ARM EABI5 | Stabil |
| ''arm_cm'' | – | ARM Cortex-M (generisch) | ELF32 | ARM EABI5 | Stabil |
| ''win64'' | ''windows-x86_64'' | x86_64 | PE32+ | Windows x64 | Stabil |
| ''windows-arm64'' | – | ARM64 | PE32+ | Windows ARM64 | Stabil |
| ''macosx64'' | ''macos-x86_64'' | x86_64 | Mach-O | SysV AMD64 | Stabil |
| ''macos-arm64'' | – | ARM64 (Apple Silicon) | Mach-O | AAPCS64 | Stabil |
| ''android'' | ''android-arm64'' | ARM64 | ELF64 (.so) | Android Bionic | Stabil |
| ''android-x86_64'' | – | x86_64 | ELF64 (.so) | Android Bionic | Stabil |
| ''esp32'' | ''esp32s3'' | Xtensa LX6 | ELF32 | Vereinfacht SysV | Experimentell |
**Standard:** Kein ''--target'' → Host-Plattform (in der Regel ''linux''/x86_64).
----
===== Typische Workflows =====
==== ARM64 Linux (Raspberry Pi, Embedded-Server) ====
lyxc main.lyx --target=arm64 -o firmware.elf
# Mit Energy-Optimierung für Batteriebetrieb:
lyxc main.lyx --target=arm64 --target-energy=1 -o sensor.elf
# Safety-Build (DO-178C):
lyxc flight.lyx --target=arm64 --lint --static-analysis -o flight.elf
Die erzeugte ELF verwendet ''/lib/ld-linux-aarch64.so.1'' als Dynamic Linker — das muss auf dem Zielsystem vorhanden sein. Für Systeme ohne Standard-Loader:
> **''%%--%%static'' gibt es in lyxc 1.0.16F nicht** — der Aufruf bricht mit ''unbekannter Schalter'' und Exit 2 ab. Der Schalter sollte den Dynamic-Linker-Eintrag entfernen.
>
> **''%%--%%no-libc-init'' wird angenommen**, taucht aber in ''lyxc %%--%%help'' nicht auf: Der Aufruf läuft durch (Exit 0) und erzeugt ein lauffähiges Binary. Ob dabei der vorgesehene Bare-Metal-Stub statt des gewöhnlichen ''_start'' entsteht, ist von außen nicht abzulesen — für die Beispiele unten zum Cortex-M ist er weiterhin die dokumentierte Form.
>
> Beides ist derzeit gegenstandslos: Der Compiler erzeugt ohnehin **statische** ELF-Dateien ohne Dynamic Linker — das meldet auch das LCBS-Audit jedes Builds (''RELRO (kein GOT/PLT-Angriffsziel — statisches ELF)'').
----
==== Windows x64 (Cross von Linux) ====
lyxc main.lyx --target=win64 -o app.exe
lyxc main.lyx --target=windows-arm64 -o app_arm64.exe
Erzeugt eine vollständige PE32+-Datei. Keine Wine- oder MSVC-Installation nötig.
Seit lyxc 1.1.3E sind aus einer solchen Binary auch **Win32-Funktionen** erreichbar: ''extern fn ... link "kernel32.dll"'' landet in der Import-Tabelle, mehrere DLLs nebeneinander sind zulässig, und Umgebungsvariablen (''EnvLookupRaw'', ''std.datetime'', ''std.os'') lesen den Windows-Umgebungsblock ([[https://github.com/SEOLizer/LyX-Compiler/issues/1671|#1671]], [[https://github.com/SEOLizer/LyX-Compiler/issues/1674|#1674]], [[https://github.com/SEOLizer/LyX-Compiler/issues/1676|#1676]], [[https://github.com/SEOLizer/LyX-Compiler/issues/1677|#1677]]). Auch die frühere Größengrenze ist weg: eine Relokationstabelle über 0x1000 machte die Datei vorher unstartbar ([[https://github.com/SEOLizer/LyX-Compiler/issues/1672|#1672]]).
----
==== RISC-V (Embedded-Controller, HiFive, VisionFive) ====
# Generisches RISC-V RV64GC:
lyxc main.lyx --target=riscv -o controller.elf
# Linux-spezifisch (mit Linux ABI-Optimierungen):
lyxc main.lyx --target=linux-riscv64 -o app.elf
**Einschränkung:** Kein Dynamic Linking für RISC-V — immer statisch linken (''--static'') oder ''-l''-Flags vermeiden.
----
==== ARM Cortex-M (Bare-Metal Microcontroller) ====
Für STM32, nRF52, RP2040 und kompatible Cortex-M4/M33-Systeme:
# Cortex-M4 / Cortex-M33:
lyxc main.lyx --target=arm-cm4 --no-libc-init -o firmware.elf
# Generisch Cortex-M (M0/M3):
lyxc main.lyx --target=arm_cm --no-libc-init -o firmware.elf
**Wichtig:** Kein Hardware-FPU-Support — Fließkomma läuft als Software-Emulation. Für DO-178C mit FPU: die betroffenen Funktionen mit ''@flight_crit'' annotieren — ein ''--no-fp-fold'' gibt es nicht.
Das ELF32-Format enthält ''e_flags = EABI5 | Thumb-interwork'' — direkt flashbar mit ''objcopy'' oder ''openocd''.
----
==== ESP32 / ESP32-S3 (Xtensa LX6 — experimentell) ====
lyxc main.lyx --target=esp32 --no-libc-init -o app.elf
lyxc main.lyx --target=esp32s3 --no-libc-init -o app_s3.elf
**Status: läuft, aber ohne Hardware-Nachweis.** Die Defektkette, die hier früher als „Segfault bei komplexen Programmen" stand, ist mit ''lyxc 1.1.9N'' behoben ([[https://github.com/SEOLizer/LyX-Compiler/issues/1782|#1782]]); Division und Modulo, die still 0 lieferten, mit 1.1.10G ([[https://github.com/SEOLizer/LyX-Compiler/issues/1789|#1789]]). Was bleibt:
* **Kein ''f64''-Rechnen** — Addition und Vergleich brechen beim Übersetzen ab (nachgemessen mit 1.1.11B)
* Kein Dynamic Linking
* Die Multiplikation ist **nicht ausführbar geprüft** — in keinem verfügbaren QEMU-Kern gibt es ''Mul32'' ([[https://github.com/SEOLizer/LyX-Compiler/issues/1790|#1790]]). Das gilt sinngemäß für das ganze Ziel: geprüft ist, was der Compiler erzeugt, nicht was der Chip daraus macht.
----
==== Android (.so + JNI) ====
Android-Bibliotheken werden als ''.so'' erzeugt:
lyxc mylib.lyx --target=android --output-type=shared-lib -o libmylib.so
# Android API-Level explizit setzen (Default: 26 = Android 8.0, Minimum: 21):
lyxc mylib.lyx --target=android --android-api=29 --output-type=shared-lib -o libmylib.so
# Android x86_64 (Emulator):
lyxc mylib.lyx --target=android-x86_64 --output-type=shared-lib -o libmylib_x86.so
> **''%%--%%android-api'' hat derzeit keine Wirkung** (#1526). Alle Werte erzeugen dasselbe Programm — auch ein ungültiges wie 99, das ohne Beanstandung angenommen wird. Der Schalter ist also weder wirksam noch prüfend; das API-Level ist beim Einbinden auf Android-Seite sicherzustellen.
**JNI-Funktionen** werden mit ''@jni'' annotiert — der Compiler mangelt den Namen automatisch in das Java-Format ''Java_<class>_<method>'':
import std.io;
@jni(class="com/example/MyApp", method="hello")
pub fn hello(): void {
PrintLn("Hello from Lyx via JNI!");
}
@jni(class="com/example/MyApp", method="add")
pub fn add(a: int64, b: int64): int64 {
return a + b;
}
Das erzeugte ''.so'' enthält ein ''.note.android.ident''-Section mit dem API-Level — erforderlich für den Android-Loader.
----
===== Bare-Metal: kein Betriebssystem =====
Für Microcontroller und Custom-Bootloader ohne OS-Unterstützung:
lyxc main.lyx --target=arm-cm4 --no-libc-init --static -o bare.elf
Was ''--no-libc-init'' bewirkt:
* Kein ''__libc_start_main''-Aufruf
* Kein ''DT_NEEDED libc.so.6'' im ELF
* 12-Byte ''BL main + exit''-Stub statt 56-Byte Standard-''_start''
* ''main()'' wird direkt als Einstiegspunkt verwendet
----
===== Compiler ist vollständig self-contained =====
''lyxc'' benötigt **keinen externen Linker** (kein ''ld'', ''lld'', ''arm-none-eabi-ld''). Der Compiler schreibt das fertige Binary (ELF64/ELF32/PE32+/Mach-O) direkt — Parsing, Codegen und Linking in einem Schritt.
Externe ''C''-Bibliotheken werden trotzdem unterstützt:
# C-Bibliothek linken (lyxc löst Symbole selbst auf):
lyxc main.lyx -lm -lpthread -o app
# Eigene Shared Library einbinden:
lyxc main.lyx -L/opt/mylibs -lmylib -o app
----
===== Bekannte Einschränkungen =====
^ Plattform ^ Einschränkung ^ Workaround ^
| ESP32 / Cortex-M | Kein ''f64''-Rechnen — Addition und Vergleich brechen beim Übersetzen ab | Ganzzahl-Arithmetik, Festkomma |
| ARM Cortex-M | ''alloc''/''new'' gibt es nicht — der Compiler weist beide ab (''alloc/new gibt es auf einem freistehenden Ziel nicht'') | Statische Puffer, feste Feldgrößen |
| ESP32 | Kein Dynamic Linking | Immer statisch kompilieren |
| RISC-V | Kein Dynamic Linking | ''--static'' verwenden |
| ARM Cortex-M | Kein Hardware-FPU | Software-Float; für DO-178C: ''@flight_crit'' an der Funktion |
| ARM Cortex-M | TrustZone nur Stub | Nur M-Mode nutzen |
Die frühere Zeile „ESP32: Segfault bei komplexen Programmen" ist entfallen. Die Ursache war eine Defektkette im xtensa-Backend — Argumente, Param-Spill, Vorwärtsaufrufe, Feld-Offsets, Einstiegspunkt —, behoben mit ''lyxc 1.1.9N'' ([[https://github.com/SEOLizer/LyX-Compiler/issues/1782|#1782]], [[https://github.com/SEOLizer/LyX-Compiler/issues/1765|#1765]]). Dazu kamen Division und Modulo, die vorher **still 0** lieferten ([[https://github.com/SEOLizer/LyX-Compiler/issues/1789|#1789]], 1.1.10G), sowie Zeichenkettenliterale und PC-relative Adressierung ([[https://github.com/SEOLizer/LyX-Compiler/issues/1786|#1786]]). Dieselbe Kette auf ''riscv'' war [[https://github.com/SEOLizer/LyX-Compiler/issues/1740|#1740]] (1.1.9A) — dort waren es acht Defekte auf einmal, weil das Backend bis dahin nie **ausgeführt** geprüft worden war.
===== Was je Ziel übersetzt =====
Gemessen mit **lyxc 1.1.11B**: je ein Minimalprogramm pro Zeile, für jedes Ziel übersetzt. ✓ heißt „der Compiler erzeugt ein Binary", nicht „auf dem Gerät nachgerechnet" — für ''arm-cm4'' und ''esp32'' fehlt uns dafür die Hardware.
^ Was ^ ''linux'' ^ ''arm64'' ^ ''riscv'' ^ ''arm-cm4'' ^ ''esp32'' ^
| ''f64''-Variable anlegen | ✓ | ✓ | ✓ | ✓ | ✓ |
| ''f64''-Addition | ✓ | ✓ | ✓ | **bricht ab** | **bricht ab** |
| ''f64''-Vergleich | ✓ | ✓ | ✓ | **bricht ab** | **bricht ab** |
| Ganzzahl-Division | ✓ | ✓ | ✓ | ✓ | ✓ |
| Multiplikation | ✓ | ✓ | ✓ | ✓ | ✓ |
| Zeichenkettenliteral + ''PrintLn'' | ✓ | ✓ | ✓ | ✓ | ✓ |
| ''Print(variable)'' | ✓ | ✓ | ✓ | ✓ | ✓ |
| globale Variable lesen/schreiben | ✓ | ✓ | ✓ | ✓ | ✓ |
| ''con''-Konstante | ✓ | ✓ | ✓ | ✓ | ✓ |
| ''alloc''/''free'' | ✓ | ✓ | ✓ | **abgewiesen** | ✓ |
Gegenüber dem Stand 1.0.21A hat sich das Bild grundlegend gedreht:
* **''arm64'' und ''riscv'' rechnen ''f64'' vollständig.** Der frühere Ausfall beim Vergleich (arm64, Opcode 42) und bei der Addition (riscv, Opcode 20) ist weg.
* **''con''-Konstanten waren auf //allen// IR-Zielen 0** — die Vorab-Erfassung der Modul-Globalen kannte nur ''NK_VAR_DECL'', nicht ''NK_CON_DECL'' ([[https://github.com/SEOLizer/LyX-Compiler/issues/1751|#1751]], 1.1.8A). Ein reiner Übersetzungstest wäre grün gewesen; der Fehler saß im erzeugten Code. Nachgezogen: ''f64''-Konstanten ([[https://github.com/SEOLizer/LyX-Compiler/issues/1801|#1801]]), ''~0'' im Anfangswert ([[https://github.com/SEOLizer/LyX-Compiler/issues/1799|#1799]]) und negative ''f64'' ([[https://github.com/SEOLizer/LyX-Compiler/issues/1803|#1803]]).
* **''import std.io'' trägt jetzt auf allen IR-Zielen.** Die frühere Aussage „scheitert für alle IR-Ziele, dort fehlen 194 Builtins" ([[https://github.com/SEOLizer/LyX-Compiler/issues/1388|#1388]]) gilt nicht mehr.
* **Virtueller und Interface-Dispatch** laufen auf dem IR-Pfad über einen type-id-Switch statt über eine VMT ([[https://github.com/SEOLizer/LyX-Compiler/issues/1773|#1773]], 1.1.9G) — kein eigenes Layout, keine Interface-Tabellen.
> **Die Backends weisen laut ab, statt still falschen Code zu erzeugen** ([[https://github.com/SEOLizer/LyX-Compiler/issues/1339|#1339]]):
>
>
> error: arm-cm4-Backend kennt Opcode 20 nicht — er wuerde stillschweigend verschwinden (#1339).
> error: arm-cm: alloc/new gibt es auf einem freistehenden Ziel nicht.
>
>
> Das ist die richtige Reihenfolge: ein Abbruch beim Übersetzen ist einer Rechnung vorzuziehen, die auf dem Zielgerät stillschweigend nichts tut.
>
> **Der Wächter hat allerdings eine Lücke, die #1789 offengelegt hat:** auf ''esp32'' standen ''IRO_DIV'' und ''IRO_MOD'' als „behandelt" in der Liste — behandelt wurden sie auch, nur mit einem Rumpf, der still 0 zurückgab. Eine Liste, die Vorhandensein prüft, sagt nichts über Richtigkeit. Dafür braucht es Ausführung.
Letzte Aktualisierung: 2026-08-27 — Einschränkungstabelle und Ziel-Matrix gegen ''lyxc 1.1.11B'' neu erhoben (je ein Minimalprogramm pro Zeile und Ziel übersetzt): #1740, #1751, #1765, #1782, #1786, #1789, #1799, #1801, #1803 behoben, #1388 hinfällig.
Vorherige Aktualisierung: 2026-08-19 — Windows-Abschnitt um DLL-Aufrufe, Umgebungsvariablen und die Relokationsgrenze ergänzt (#1671, #1672, #1674, #1676, #1677), unter Wine mit ''lyxc 1.1.3I'' nachgemessen.
Vorherige Aktualisierung: 2026-08-15 — Gleitkomma-Matrix gegen 1.0.20A gemessen (#1339)