SDB:Paketbau-Aktualisierungsabhängigkeiten
Inhaltsverzeichnis
Distributionsaktualisierungen durchführen
Es gibt zwei Aktualisierungsmodi, die verschiedene Herangehensweisen benötigen:
- Fehlerbehebungen (Patches)
- Distributionsaktualisierungen (bspw. openSUSE 10.2 auf 10.3)
Im ersten Modus werden installierte Pakete gepatcht, um Fehler zu beheben oder um fehlende Funktionen nachzuliefern. Hierbei bleibt die Versionsnummer des Pakets in der Regel bestehen, nur die Veröffentlichungsnummer (release number) des Pakets wird geändert. (Wenn das System bspw. openSUSE 10.2 ist, dann bleibt es auch bei openSUSE 10.2)
Auch die Bauumgebung (Compiler, Bibliotheken, usw.) erfährt nur minimale Änderungen.
Eine Distributionsaktualisierung hebt das komplette System auf eine neue Ebene, die Betriebssystemversion wird erhöht.
(Wenn das System bspw. openSUSE 10.2, wird es auf openSUSE 10.3 angehoben.)
Die Paketänderungen, die bei einer Distributionsaktualisierung erlaubt sind, sind wesentlich weit gehender und enthalten
- fallen gelassene Pakete
- neue Pakete
- umbenannte Pakete
- zusammengeführte Pakete
- aufgeteilte Pakete
Solche Änderungen sind schwer (oder sogar unmöglich) durch RPM-Abhängigkeiten ausdrückbar. Deshalb ist hierfür eine ausdrucksstärkere Form von Paketabhängigkeiten nötig, damit eine Systemaktualisierung durchgeführt werden kann.
Diese Wiki-Seite zeigt, wie sich Abhängigkeiten für Distributionsaktualisierungen ausdrücken lassen.
Wenn Sie Abhängigkeiten für eine reibungslose Systemaktualisierung hinzufügen, vergessen Sie nicht, die openSUSE-Version anzugeben, bei denen diese benötigt werden. Dies erlaubt es, die dafür nötigen Zeilen als obsolet für künftige Versionen zu erkennen (It will allow to recognize these lines as obsolete in future versions (höchstwahrscheinlich ist es bei openSUSE Version + 1 und bei SLE Version + 2).
Mittel um Abhängigkeiten auszudrücken
Jedes Paket kann Abhängigkeiten zu anderen Pakete definieren indem symbolische Namen für Provides (Bietet), Requires (Benötigt) und Conflicts (Konflikt) angegeben werden.
Diese symbolischen Namen sind in der Regel die Namen von Paketen, können aber auch 'abstrakte' Namen sein, die nicht mit einem Paket in Verbindung stehen.
Diese symbolischen Namen können benutzt werden, um Fähigkeiten anzugeben, die nicht nur einem einzigen Paket zugeordnet werden können. So wird bspw. die Fähigkeit MTA (Mail Transport Agent) von mehreren Paketen angeboten. sendmail und postfix sind dabei die prominentesten.
Es ist wichtig, nicht zu vergessen, dass alle symbolischen Namen (egal ob Paket oder abstrakter Name) im selben Namensraum liegen. Wenn ein abstrakter Name gewählt wird (bspw. für eine Fähigkeit) muss dieser nicht mit einem anderen Paketnamen in Konflikt treten.
Um Aktualisierungsabhängigkeiten zu definieren um ein (älteres) Paket mit einem anderen (neueren) Paket zu ersetzen, wird die Markierung Obsoletes (Überflüssig) verwendet.
Fakten zu RPM-Abhängigkeiten
- Jedes Paket bietet auf jeden Fall seinen Namen an.
Es ist nicht notwendig, den Paketnamen extra bei Provides anzugeben, aber andere Pakete können den Paketnamen benötigen (oder mit ihm in Konflikt treten). - Ein Paket kann mit einem von ihm bereitgestellten symbolischen Tag nicht in Konflikt treten.
Da der Paketname implizit von einem Paket angeboten kann ein Paket nicht mit sich selbst in Konflikt treten. - Obsolete funktioniert nur mit echten Paketnamen.
Eine symbolische Markierung kann nicht für Obsolete verwendet werden. - Symbolische Namen wie sie in Requires, Provides und Conflicts verwendet werden, unterscheiden sich bei Groß- und Kleinschreibung.
Basisabhängigkeiten
Installieren eines neuen Pakets
pac.spec | |
---|---|
Name: | pac |
Version: | 1.0 |
Requires: | |
Provides: | |
Obsoletes: | |
Conflicts: |
Aktualisieren eines Pakets
pac.spec | |
---|---|
Name: | pac |
Version: | 1.1 |
Requires: | |
Provides: | |
Obsoletes: | |
Conflicts: |
Der passende Name und die höhere Version machen dies zu einer Aktualisierung für pac-1.0
Umbenennen eines Pakets
package.spec | |
---|---|
Name: | package |
Version: | 1.1 |
Requires: | |
Provides: | pac = %{version} |
Obsoletes: | pac < %{version} |
Conflicts: |
Klar gesagt ist die Angabe des alten Paketnamens im Feld Provides: nur notwendig, wenn ein anderes Paket den alten Paketnamen benötigt. Bitte fügen Sie die Versionsnummer zum Feld mit dem alten Paketnamen hinzu, so dass eine spätere Rückumbenennung möglich ist. (Zum Beispiel: Provides: pac = 1.0). In 90% der Fälle können Sie einfach %{version} nutzen, wie auch im obigen Beispiel.
Dennoch veranlasst der Eintrag bei Provides: die Auswahl des neuen Pakets während der Aktualisierung. Dieses Feld sagt, Ich übernehme jetzt für das alte Paket. Das Obsoletes: sichert vor allem eine atomische Ersetzung, so dass keine Abhängigkeiten unaufgelöst bleiben. Das Feld Version: ist hier irrelevant; nichtsdestotrotz sollten Sie die Versionsnummer des alten Pakets zum Feld Obsoletes: hinzufügen (in diesem Beispiel: Obsoletes: pac <= 1.0), um "den Weg zurück" zum alten Paketnamen mit einer höheren Versionsnummer zu ermöglichen. Wie Sie im Beispiel sehen, können Sie auch hier %{version} nutzen. Nutzen Sie in diesem Fall aber nur "<", da Sie andernfalls innerhalb der gleichen Version nicht mehr zum alten Paketnamen zurückkehren können.
Falls Sie ein Unterpaket obsolet machen möchten, dessen Versionsnummer sich von der des Hauptpakets unterscheidet, können Sie %{version} nicht in Provides/Obsoletes benutzen. Sie können natürlich die gleiche Versionszeichenkette wie in Version des Unterpakets benutzen.
Bitte fügen Sie auch einen einfachen Kommentar zur spec-Datei hinzu, bspw. "# pac was last used in openSUSE 10.2". Ohne ihn ist es schwierig zu entscheiden, wann es möglich ist, diese Zeilen zu entfernen und sie werden für immer dort bleiben.
Ein Paket durch ein anderes mit der gleichen Funktion ersetzen
package.spec | |
---|---|
Name: | package |
Version: | 1.1 |
Requires: | |
Provides: | |
Obsoletes: | pac < %{version} |
Conflicts: |
Anders als beim Umbenennen eines Pakets wird pac durch package ersetzt, obwohl es keine Dateien von pac anbietet. Dadurch bietet package natürlich auch nicht pac an.
Dies funktioniert nur, wenn nur ein Paket pac überflüssig macht. Wenn es mehrere Pakete gibt, wird der Solver die Aktualisierung nicht durchführen.
Aufteilen und Zusammenführen
Abspalten eines Unterpakets
pac.spec | pac-devel.spec | |||
---|---|---|---|---|
Name: | pac | Name: | pac-devel | |
Version: | 1.1 | Version: | 1.1 | |
Requires: | Requires: | |||
Provides: | Provides: | pac:/file/from/pac | ||
Obsoletes: | Obsoletes: | |||
Conflicts: | Conflicts: |
Aufspalten von einem Paket in zwei
firstpac.spec | secondpac.spec | |||
---|---|---|---|---|
Name: | firstpac | Name: | secondpac | |
Version: | 1.1 | Version: | 1.1 | |
Requires: | Requires: | |||
Provides: | pac = 8.15 | Provides: | pac:/file/from/pac | |
Obsoletes: | pac <= 8.15 | Obsoletes: | ||
Conflicts: | Conflicts: |
Dieses Beispiel zeigt separate .spec-Dateien für pac und pac-devel. (Denken Sie daran, dass RPM es erlaubt, ein Unterpaket von einem 'Hauptpaket' in einer einzelnen .spec-Datei zu definieren.
Die Auflösung der Abhängigkeiten (Installieren beider neuer Pakete) wird von YaST mit dem split-alias durchgeführt, welcher im Feld Provides: von pac-devel angegeben ist.
Es ist am Paketbetreuer über die Abhängigkeiten zwischen pac und pac-devel zu entscheiden. Zum Beispiel dann, wenn jemand ein Bibliothekspaket in ein Haupt-, ein -devel- und ein -doc-Paket einteilen will. Haupt- und -doc-Paket sind unabhängig voneinander, aber das -devel-Paket verlangt nach dem Hauptpaket.
Während einer Aktualisierung ist die oben erwähnte split-alias-Markierung wichtig. YaST aktualisiert nur bereits installierte Pakete, in diesem Fall nur das Hauptpaket. Ohne den split-alias würden Dateien welche zur Entwicklung benötigt werden entfernt, da diese zwar Teil des alten Pakets waren, nun aber nicht mehr zum neuen Hauptpaket gehören.
Das angegebene Provides: für pac löst nun diese Aktualisierungsabhängigkeit aus, indem es YaST mitteilt, auch pac-devel zu installieren, auch wenn dieses vorher nicht installiert war.
!! split-alias-Markierungen werden nur von YaST verwendet, RPM kennt sie nicht. !!
Falls ein Paket in mehr als zwei Pakete aufgeteilt wird, muss der split-alias gemeinsam exklusiv sein. Dies ist der einzige Weg für YaST solche Aktualisierungsabhängigkeiten korrekt zu verarbeiten.
Wichtige Erweiterungen für die Zukunft
Das Aufteilen eines Bibliothekspakets in ein Haupt- und ein -devel-Paket ist immer eine gute Idee. Es ist aber nicht in jedem Fall sinnvoll, da das -devel-Paket manchmal viel zu klein würde oder nichts enthalten würde. Der Trick ist in diesem Fall einfach das Hinzufügen eines Provides: pac-devel = %{version} im Hauptpaket: andere Pakete können dieses virtuelle -devel-Paket dann verlangen.
Bitte fügen Sie auch einen einfachen Kommentar zur spec-Datei hinzu, bspw. "#-devel splitted in openSUSE 10.2". Ohne ihn ist es schwierig zu entscheiden, wann es möglich ist, diese Zeilen zu entfernen und sie werden für immer dort bleiben.
Verschmelzen eines Pakets
package.spec | |
---|---|
Name: | package |
Version: | 1.1 |
Requires: | |
Provides: | pac = 8.15 |
Obsoletes: | pac <= 8.15 |
Conflicts: |
Dies ist vergleichbar mit der Umbenennung eines Pakets. Das neue Paket muss auch die Markierungen Provides und Obsoletes des alten Pakets einbeziehen. Dies wird für eine passende Aktualisierung für Distributionen vor X benötigt.
Verschmelzen von zwei Paketen in ein neues
package.spec | |
---|---|
Name: | package |
Version: | 1.1 |
Requires: | |
Provides: | pac1 = 8.15 pac2 = 2.3 |
Obsoletes: | pac1 <= 8.15 pac2 <= 2.3 |
Conflicts: |
Alternativen handhaben
Nicht in Konflikt stehend
firstpac.spec | secondpac.spec | thirdpac.spec | |||||
---|---|---|---|---|---|---|---|
Name: | firstpac | Name: | secondpac | Name: | thirdpac | ||
Version: | 1.0 | Version: | 1.0 | Version: | 1.0 | ||
Requires: | Requires: | Requires: | |||||
Provides: | Pac = 1.0 | Provides: | Pac = 1.0 | Provides: | Pac 1.0 | ||
Obsoletes: | Obsoletes: | Obsoletes: | |||||
Conflicts: | Conflicts: | Conflicts: |
Alle drei Pakete stellen die Fähigkeit Pac bereit und können parallel zueinander installiert werden.
(Der groß geschriebene Anfangsbuchstabe in Pac wurde gewählt, um diese Markierung von einem Paket zu unterscheiden. Solche Fähigkeiten/capabilities müssen innerhalb der openSUSE-Entwicklergemeinde ausgehandelt werden. Fragen Sie auf der Mailing-Liste opensuse-packaging bevor Sie ihre eigenen Markierungen/Tags einführen!).
Beispiel: xdm und kdm stellen die Fähigkeit 'Display-Manager' bereit
Teilweise in Konflikt stehend
firstpac.spec | secondpac.spec | thirdpac.spec | |||||
---|---|---|---|---|---|---|---|
Name: | firstpac | Name: | secondpac | Name: | thirdpac | ||
Version: | 1.0 | Version: | 1.0 | Version: | 1.0 | ||
Requires: | Requires: | Requires: | |||||
Provides: | Pac = 1.0 | Provides: | Pac = 1.0 | Provides: | Pac = 1.0 | ||
Obsoletes: | Obsoletes: | Obsoletes: | |||||
Conflicts: | secondpac | Conflicts: | firstpac | Conflicts: |
Das Feld Conflicts drückt aus, dass entweder firstpac oder secondpac installiert sein kann, aber nicht beide.
Gegenseitig ausschließend
firstpac.spec | secondpac.spec | thirdpac.spec | |||||
---|---|---|---|---|---|---|---|
Name: | firstpac | Name: | secondpac | Name: | thirdpac | ||
Version: | 1.0 | Version: | 1.0 | Version: | 1.0 | ||
Requires: | Requires: | Requires: | |||||
Provides: | Pac = 1.0 | Provides: | Pac = 1.0 | Provides: | Pac = 1.0 | ||
Obsoletes: | Obsoletes: | Obsoletes: | |||||
Conflicts: | secondpac thirdpac | Conflicts: | firstpac thirdpac | Conflicts: | firstpac secondpac |
Nur eins von firstpac, secondpac oder thirdpac kann installiert sein.