====== 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
> **Der Bau für Lyx OS läuft //noch// ohne ''%%--target=lyxos%%'' — die Gründe dafür sind aber weg.**
>
> Das native Zielformat von Lyx OS ist ''LYX!'', der Maschinencode-Container des LX-34-Loaders; ''%%--target=lyxos%%'' erzeugt ihn (Magic ''4C 59 58 21''). ELF wird von Lyx OS nur **weiterhin mitgeladen**.
>
> Was Vega an diesem Ziel bislang gehindert hat, ist mit ''lyxc 1.1.4D'' erledigt und mit **1.1.11B nachgemessen**: ''alloc''/''free'' übersetzen ([[https://github.com/SEOLizer/LyX-Compiler/issues/1718|#1718]] — die eigene ''platform/lyxos/Vega/Mem.lyx'' über ''mmap'' ist damit kein Zwang mehr), die stdlib-Importe tragen wieder ([[https://github.com/SEOLizer/LyX-Compiler/issues/1717|#1717]]: ''std.fs'' mit ''FileExists'', ''std.io'' mit ''StrNew''), die Builtin-IDs 3 und 6–15 sind im Backend belegt ([[https://github.com/SEOLizer/LyX-Compiler/issues/1715|#1715]]), und ''Print''/''PrintLn'' nehmen Variable, Zahl, Ausdruck und Funktionsaufruf ([[https://github.com/SEOLizer/LyX-Compiler/issues/1716|#1716]]). Ein Programm mit allen dreien baut zum ''LYX!''-Container durch.
>
> Offen ist damit nur noch die Umstellung des Vega-Baus selbst — ''%%--target=lyxos%%'' ist der Weg, der ELF-Weg der Übergang.
----
===== 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-27 gegen ''lyxc 1.1.11B'' neu nachgemessen — ''alloc''/''free'', ''std.io'', ''std.fs'' und ''Print(variable)'' bauen dort jetzt zum ''LYX!''-Container durch (#1715, #1716, #1717, #1718 behoben).
Codebeispiele geprüft: gegen **lyxc 1.2.5C** übersetzt (Prüflauf 2026-09-08 über die gesamte Doku: 574 Vollprogramme, 0 echte Fehler; zusätzlich 5159 Aufrufe gegen die ''pub fn''-Signaturen in ''aurum/std'' gehalten, 0 Abweichungen).