====== Vega — Portabel bauen ====== Ein Quelltext, drei Ziele: X11 unter Linux, Win32 unter Windows, Ring-3 unter Lyx OS. Der Unterschied steht **nicht** im Programm, sondern im Include-Pfad des Übersetzungsaufrufs. → [[lyx_-_programmiersprache:vega:guides|Vega-Guides]] · [[lyx_-_programmiersprache:vega:backends|Backends]] · [[lyx_-_programmiersprache:vega:bauen|Bauen und Testen]] · [[lyx_-_programmiersprache:guides:crosscompiling|Cross-Compilation]] ---- ===== Der Trick: eine Unit, dreimal vorhanden ===== ''Vega.BackendAuto'' liegt je einmal unter ''platform/linux'', ''platform/win64'' und ''platform/lyxos''. Alle drei exportieren dieselbe Funktion: pub fn NewPlatformBackend(): IVegaBackend Welche gebunden wird, entscheidet die **letzte** ''-I''-Angabe — deshalb steht der Plattformpfad hinter dem Projektpfad. lyxc app.lyx -I . -I platform/linux -o app # X11 lyxc app.lyx -I . -I platform/win64 --target=win64 --format=pe -o app.exe # Win32 lyxc app.lyx -I . -I platform/lyxos -o app.elf # Lyx OS > **Für Lyx OS wird //derzeit// ohne ''%%--target=lyxos%%'' gebaut** — als Übergang, nicht als Dauerzustand. > > Das native Zielformat von Lyx OS ist ''LYX!'', der Maschinencode-Container des LX-34-Loaders; ''%%--target=lyxos%%'' erzeugt ihn (Magic ''4C 59 58 21'', nachgemessen mit ''lyxc 1.1.4B''), und ''PrintLn'' arbeitet dort inzwischen — allerdings nur mit einem Zeichenketten-Literal ([[https://github.com/SEOLizer/LyX-Compiler/issues/1716|#1716]]). ELF wird von Lyx OS nur **weiterhin mitgeladen**. > > Was Vega an diesem Ziel bislang hindert: ''alloc'' und ''free'' fehlen ([[https://github.com/SEOLizer/LyX-Compiler/issues/1718|#1718]] — deshalb die eigene ''platform/lyxos/Vega/Mem.lyx'' über ''mmap''), und die stdlib-Importe brechen an fehlenden Builtin-Namen ([[https://github.com/SEOLizer/LyX-Compiler/issues/1717|#1717]]: ''std.fs'' schon bei ''FileExists'', ''std.io'' bei ''StrNew''); im Backend selbst fehlen die Builtin-IDs 3 und 6–15 ([[https://github.com/SEOLizer/LyX-Compiler/issues/1715|#1715]]). Solange das so ist, ist der ELF-Weg der einzige, der wirklich läuft. Sobald die Lücken zu sind, ist ''%%--target=lyxos%%'' der richtige Weg. ---- ===== Warum keine Fallunterscheidung im Code ===== ''TARGET_OS'' gibt es (1 = Linux, 3 = Windows), und es ändert sich mit ''--target''. Für die Backendwahl reicht es trotzdem nicht: Beide Zweige müssten übersetzt **und** gebunden werden, und ''extern''-Deklarationen sind harte Abhängigkeiten — auch in einem Zweig, der nie läuft. Eine Linux-Binary mit eingebundenem Win32-Backend verlangt beim Start ''kernel32.dll'' und startet gar nicht erst. Deshalb die Trennung über den Pfad. Es ist dasselbe Verfahren, mit dem Lazarus seine Widgetsets auswählt. ---- ===== Beispiel ===== Dieses Programm ist unverändert für alle drei Ziele übersetzbar: unit Main; import std.io; import Vega.Types; import Vega.Events; import Vega.Canvas; import Vega.Theme; import Vega.Control; import Vega.Font; import Vega.Strings; import Vega.Lists; import Vega.Style; import Vega.StdCtrls; import Vega.Backend; // Diese Unit gibt es dreimal — unter platform/linux, platform/win64 und // platform/lyxos. Welche gilt, entscheidet der Include-Pfad, nicht der Code. import Vega.BackendAuto; import Vega.Forms; var g_app: TApplication; var g_stand: TLabel; var g_zaehler: int64; fn OnZaehl(sender: TControl): void { g_zaehler := g_zaehler + 1; g_stand.SetCaption(StrConcat("Geklickt: ", IntToStr(g_zaehler))); } fn OnBeenden(sender: TControl): void { g_app.Terminate(); } fn main(): int64 { g_app := new TApplication(NewPlatformBackend()); if (!g_app.Ready) { PrintLn("Kein Fenstersystem erreichbar."); return 1; } var f: TForm := new TForm(320, 160, "Portabel"); g_zaehler := 0; g_stand := new TLabel("Geklickt: 0"); g_stand.SetBounds(16, 16, 280, 18); g_stand.SetParent(f); var b1: TButton := new TButton("Zaehlen"); b1.SetBounds(16, 56, 130, 28); b1.OnClick := OnZaehl; b1.SetParent(f); var b2: TButton := new TButton("Beenden"); b2.SetBounds(166, 56, 130, 28); b2.OnClick := OnBeenden; b2.SetParent(f); if (!g_app.ShowForm(f)) { return 2; } g_app.Run(); g_app.Shutdown(); return 0; } Nachgemessen mit ''lyxc 1.1.3I'' — dieselbe Datei, drei Aufrufe: ^ Ziel ^ Aufruf ^ Ergebnis ^ | Linux/X11 | ''-I . -I platform/linux'' | ELF 64-bit, 787 KB | | Windows | ''-I . -I platform/win64 %%--target=win64 --format=pe%%'' | PE32+ x86-64, 803 KB | | Lyx OS | ''-I . -I platform/lyxos'' | ELF 64-bit statisch, 764 KB | Die PE-Datei wurde zusätzlich unter Wine gestartet und zeigt ihr Fenster. ---- ===== Was portabel ist und was nicht ===== ^ Portabel ^ Nicht portabel ^ | Alles aus ''Vega.*'' — Controls, Layout, Themes, LFM | Direkte ''extern''-Aufrufe in Systembibliotheken | | Zeichnen, Schriften, Ereignisse | Pfade mit ''/'' oder ''\\'' fest im Code | | ''std''-Units ohne Systembezug | Annahmen über Zeilenenden oder Dateirechte | Die HAL ist bewusst klein — 21 Methoden. Alles darüber ist geteilter Code und läuft überall gleich; genau deshalb ist sie ein Interface. ---- ===== Bauen mit Skript ===== Im Repository nimmt ''build.sh'' die Unterscheidung über den Dateinamen ab: ein Beispiel ''name_win'' wird als PE gebaut, ''name_lyxos'' für Lyx OS, alles andere für X11. Für ein eigenes Projekt genügt dasselbe Muster — drei Aufrufe, ein Quelltext. ---- ===== Fallstricke ===== * **Plattformpfad vor dem Projektpfad.** Die letzte ''-I''-Angabe gewinnt; steht ''platform/linux'' zuerst, greift sie nicht. * **''--target=win64'' ohne ''platform/win64''.** Dann wird das X11-Backend in eine PE-Datei gebunden — sie startet, findet aber kein Fenstersystem. * **''--target=lyxos'' benutzt, solange die Builtins fehlen.** Der Bau bricht bei der ersten ''alloc''- oder ''std.fs''-Stelle ab; siehe Kasten. Es ist das künftige, noch nicht das gangbare Ziel. * **Backend direkt importiert.** ''import Vega.Backend.X11'' bindet fest an X11; portable Programme nehmen ''Vega.BackendAuto''. Letzte Aktualisierung: 2026-08-20 — drei Ziele mit ''lyxc 1.1.3I'' aus derselben Datei gebaut und mit ''file'' geprüft; der Lyx-OS-Abschnitt am 2026-08-20 gegen ''lyxc 1.1.4B'' nachgemessen (''LYX!''-Container, fehlende Builtins ''alloc'' und ''readlink'').