====== 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)