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.
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 --no-fp-fold --stack-check --lint -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:
lyxc main.lyx --target=arm64 --static --no-libc-init -o firmware.elf
–static entfernt den Dynamic-Linker-Eintrag. –no-libc-init erzeugt einen 12-Byte Bare-Metal-Stub statt des normalen 56-Byte _start (kein libc_start_main).
—-
==== Windows x64 (Cross von Linux) ====
–static
Erzeugt eine vollständige PE32+-Datei. Keine Wine- oder MSVC-Installation nötig.
—-
==== RISC-V (Embedded-Controller, HiFive, VisionFive) ====
lyxc main.lyx --target=win64 -o app.exe
lyxc main.lyx --target=windows-arm64 -o app_arm64.exe
Einschränkung: Kein Dynamic Linking für RISC-V — immer statisch linken (# 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
) oder -l-Flags vermeiden.
—-
==== ARM Cortex-M (Bare-Metal Microcontroller) ====
Für STM32, nRF52, RP2040 und kompatible Cortex-M4/M33-Systeme:
–no-fp-fold
Wichtig: Kein Hardware-FPU-Support — Fließkomma läuft als Software-Emulation. Für DO-178C mit FPU: # 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
setzen.
Das ELF32-Format enthält e_flags = EABI5 | Thumb-interwork — direkt flashbar mit objcopy oder openocd.
—-
==== ESP32 / ESP32-S3 (Xtensa LX6 — experimentell) ====
.so
Status: Experimentell. Bekannte Einschränkungen:
* Segfault bei komplexen Programmen möglich
* Kein Dynamic Linking
* Eingeschränkte Stdlib-Unterstützung — nur Builtins verwenden
—-
==== Android (.so + JNI) ====
Android-Bibliotheken werden als lyxc main.lyx --target=esp32 --no-libc-init -o app.elf
lyxc main.lyx --target=esp32s3 --no-libc-init -o app_s3.elf
erzeugt:
@jni
JNI-Funktionen werden mit 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
annotiert — der Compiler mangelt den Namen automatisch in das Java-Format Java_<class>_<method>:
.so
Das erzeugte 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;
}
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:
–no-libc-init
Was lyxc main.lyx --target=arm-cm4 --no-libc-init --static -o bare.elf
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:
–static
—-
===== Bekannte Einschränkungen =====
^ Plattform ^ Einschränkung ^ Workaround ^
| ESP32 | Segfault bei komplexen Programmen | Einfachere Programme, keine tiefe Rekursion |
| ESP32 | Kein Dynamic Linking | Immer statisch kompilieren |
| RISC-V | Kein Dynamic Linking | # 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
verwenden |
| ARM Cortex-M | Kein Hardware-FPU | Software-Float; für DO-178C: –no-fp-fold'' |
| ARM Cortex-M | TrustZone nur Stub | Nur M-Mode nutzen |
| Alle | Einige IR-Operationen Stubs in Nicht-x86-Backends | x86_64 Linux als primäres Build-Target nutzen |
Letzte Aktualisierung: 2026-06-08
