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.

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

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. —- ==== 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:
–no-fp-fold setzen. 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: 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
.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
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 | Segfault bei komplexen Programmen | Einfachere Programme, keine tiefe Rekursion | | 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: –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