Inhaltsverzeichnis

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.

→ Vega-Guides · Backends · Bauen und Testen · 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 (#1718 — die eigene platform/lyxos/Vega/Mem.lyx über mmap ist damit kein Zwang mehr), die stdlib-Importe tragen wieder (#1717: std.fs mit FileExists, std.io mit StrNew), die Builtin-IDs 3 und 6–15 sind im Backend belegt (#1715), und Print/PrintLn nehmen Variable, Zahl, Ausdruck und Funktionsaufruf (#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

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