LPM — Pakete anlegen und in die Registry einreichen

LPM ist der Lyx Package Manager. Er löst Abhängigkeiten auf, baut .lxpkg-Archive und kommuniziert mit der zentralen Registry unter lpm.seolizer.de.

Ein Lyx-Projekt beschreibt sich selbst in einer einzigen Datei: lyx.toml. Darin steht der Paketname, die Version, die Abhängigkeiten — und optional der Einstiegspunkt für den Compiler. LPM liest diese Datei und weiß damit alles was es braucht: welche Pakete geladen werden müssen, wie das Archiv heißt und wohin es hochgeladen wird.

Die Registry speichert jedes Paket versioniert und unveränderlich. Wer ein Paket unter [email protected] einreicht, kann diese Version nicht nachträglich ändern — das schützt alle, die diese Version als Abhängigkeit deklariert haben. Neue Versionen werden immer als eigener Eintrag veröffentlicht.

Was LPM kann:

Befehl Was passiert
lpm init lyx.toml mit Grundstruktur anlegen
lpm install Abhängigkeiten aus lyx.toml auflösen, herunterladen und verifizieren (SHA256)
lpm publish Paket packen, signieren und in die Registry hochladen
lpm resolve Versionsauflösung testen — wird von lyxc als Hook aufgerufen
lpm info / search Registry nach Paketen und Versionen abfragen

LPM arbeitet direkt mit lyxc zusammen: nach lpm install gibt lpm resolve dem Compiler die -I-Pfade zu den heruntergeladenen Paketen — der eigene Code muss nichts weiter tun als import andreas.stringutils.trim; zu schreiben.

Tools-Übersicht · Compiler-Parameter · Erste Schritte


1. Voraussetzungen

Config einmalig anlegen (~/.lpm/config.yml):

registry: https://lpm.seolizer.de
api_key: <dein-token>

Den Token vergibt der Server-Admin:

php admin.php add-token <dein-name>


2. Neues Paket anlegen

mkdir mein.paket && cd mein.paket
lpm init --name mein.paket

lpm init erzeugt eine lyx.toml mit Pflichtfeldern. Fehlende Felder ergänzen:

[package]
name        = "mein.paket"
version     = "0.1.0"
author      = "Andreas Röne"
license     = "MIT"
description = "Kurze Beschreibung des Pakets"

[build]
entry = "main.lyx"

[dependencies]
std.string    = "^1.0.0"
anderes.paket = "^2.1.0"


3. Paket-Struktur

mein.paket/
├── lyx.toml          ← Pflicht
├── main.lyx          ← Einstiegspunkt (gemäß entry in lyx.toml)
├── core/
│   └── util.lyx
└── README.md         ← optional

Die unit-Deklaration in jeder Datei muss zum Paketnamen passen:

unit mein.paket;

pub fn main(argc: int64, argv: int64): int64 {
    ...
}


3b. Library-Paket (kein Einstiegspunkt)

Nicht jedes Paket hat eine main-Funktion. Bei einer reinen Bibliothek lässt du den [build]-Abschnitt einfach weg — LPM publiziert das Archiv trotzdem:

[package]
name        = "andreas.stringutils"
version     = "1.0.0"
author      = "Andreas Röne"
license     = "MIT"
description = "Erweiterte String-Hilfsfunktionen für Lyx"

[dependencies]
std.string = "^1.0.0"

Kein entry, kein main. Der Server prüft nicht ob ein Einstiegspunkt vorhanden ist.

Unit-Benennung: Der Paketname aus lyx.toml ist der Namespace-Präfix. Jede Quelldatei deklariert ihre eigene Sub-Unit darunter:

andreas.stringutils/
├── lyx.toml
├── trim.lyx        → unit andreas.stringutils.trim;
├── split.lyx       → unit andreas.stringutils.split;
└── format.lyx      → unit andreas.stringutils.format;

unit andreas.stringutils.trim;

import std.string;
import std.alloc;

pub fn StrTrimLeft(s: int64): int64 { ... }
pub fn StrTrimRight(s: int64): int64 { ... }
pub fn StrTrim(s: int64): int64 { ... }

Nur pub-Funktionen sind nach außen sichtbar.

Nutzer der Bibliothek:

[dependencies]
andreas.stringutils = "^1.0.0"

lpm install

unit mein.projekt;

import andreas.stringutils.trim;
import andreas.stringutils.split;

pub fn main(argc: int64, argv: int64): int64 {
    var s: int64 := StrTrim("  hallo  "c);
    ...
}

lyxc findet die installierten Units über den Cache-Pfad, den lpm als -I-Flag weitergibt — das übernimmt lpm resolve (der lyxc-Hook) automatisch.

Faustregeln:

Typ [build] entry main-Funktion
Executable ja ja ja (pub fn main)
Library nein nein
Hybrid ja ja ja — plus zusätzliche exportierte pub-Funktionen

Ein Hybrid macht Sinn wenn das Paket sowohl eine CLI liefert als auch eine API für andere Pakete — wie z.B. lpm selbst: es hat pub fn main, aber lpm.core.* ist für andere Pakete importierbar.


4. Version hochzählen

Vor jedem Publish die Version in lyx.toml erhöhen — SemVer:

Änderung Beispiel Wann
Patch 0.1.0 → 0.1.1 Bugfix, keine API-Änderung
Minor 0.1.0 → 0.2.0 Neue Funktion, rückwärtskompatibel
Major 0.1.0 → 1.0.0 Breaking Change

Bereits veröffentlichte Versionen können nicht überschrieben werden — immer neue Versionsnummer.


5. Publish

cd mein.paket/
lpm publish

LPM führt dabei aus:

  1. lyx.toml lesen
  2. Alle .lyx-Dateien in ein .lxpkg-Archiv packen
  3. SHA256 berechnen
  4. Hochladen: POST /v1/publish mit Bearer-Token

Erfolgsmeldung:

lpm: [email protected] veröffentlicht (sha256: abc123...)


6. Paket aktualisieren

Version in lyx.toml erhöhen, dann erneut publishen:

# lyx.toml: version = "0.2.0"
lpm publish


7. Paket als Abhängigkeit nutzen

In lyx.toml eines anderen Projekts:

[dependencies]
mein.paket = "^0.2.0"

lpm install

LPM löst die Version auf, lädt das .lxpkg herunter und verifiziert den SHA256.


8. Abhängigkeiten aktualisieren (lpm update)

lpm update aktualisiert installierte Pakete auf die neueste Version, die mit der Versionsangabe in lyx.toml kompatibel ist. Die Constraint-Zeilen in lyx.toml bleiben dabei unverändert — nur der tatsächlich installierte Stand wird angehoben.

Alle Abhängigkeiten auf einmal aktualisieren:

lpm update

LPM prüft für jede Abhängigkeit, ob in der Registry eine neuere Version existiert, die noch in den deklarierten Bereich fällt. std.string = „^1.0.0“ erlaubt z.B. jede 1.x.y-Version, nicht aber 2.0.0.

Einzelnes Paket aktualisieren:

lpm update andreas.stringutils

Nützlich wenn nur ein bestimmtes Paket eine kritische Bugfix-Version erhalten hat und der Rest stabil bleiben soll.

Was '^' bedeutet:

Constraint Erlaubt Nicht erlaubt
^1.0.0 1.0.1, 1.2.0, 1.9.9 2.0.0
^0.2.0 0.2.1, 0.2.9 0.3.0, 1.0.0
^0.0.3 0.0.3 0.0.4, 0.1.0

Bei 0.x.y-Versionen schützt '^' auch vor Minor-Bumps — solange die Major-Version 0 ist, gilt jede Minor-Erhöhung als potenzieller Breaking Change.

Breaking Change: Major-Version anheben

Wenn ein Paket eine neue Major-Version veröffentlicht (1.x.x → 2.0.0), greift lpm update bewusst nicht — die ^-Constraint verhindert es. Die Abhängigkeit in lyx.toml muss manuell angepasst werden:

[dependencies]
andreas.stringutils = "^2.0.0"   # war: ^1.0.0

lpm install

Das ist Absicht: ein Major-Bump signalisiert Breaking Changes, die eine bewusste Entscheidung erfordern.


9. Nützliche Befehle

Befehl Wirkung
lpm info mein.paket Paket-Infos und alle veröffentlichten Versionen anzeigen
lpm search <suchbegriff> Registry nach Paketen durchsuchen
lpm list Lokal installierte Pakete auflisten
lpm cache clean Lokalen Paket-Cache leeren
lpm resolve mein.paket Versionsauflösung testen (lyxc-Hook)

Letzte Aktualisierung: 2026-06-12