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