Wer mit dem make-basierten Weg, Programmpakete in Unix-System zu installieren, vertraut ist, soll hier dazu angeregt werden, einen Schritt weiter zu gehen und RedHat's Package Manager (RPM) zu verwenden.
RPM ist grundlegender Bestandteil von RedHat Linux, SuSE Linux und anderen Linux-Distributionen. RPM ist nicht der einzige verfügbare Paket-Manager, aber wer eine RPM-basierte Linux-Distribution besitzt, sollte lernen, ihn zu benutzen, insbesondere wenn er/sie Programmpakete ansonsten geradewegs von make bauen und installieren lässt. Einen Paket-Manager zu benutzen, erleichtert das De-Installieren und Aktualisieren von Programmpaketen, und ein Paket-Manager bietet darüberhinaus weitere nützliche Möglichkeiten, beispielsweise zur Ermittlung der Paketzugehörigkeit jeder installierten Datei und zur Erkennung von Änderungen an installierten Paketen.
Das hier ist kein einschlägiges RPM-Tutorium; wer RPM installiert hat, verfügt auch über einführende Dokumentation, z.B. das RPM-HOWTO und die Handbuchseite rpm(1). Auch ein Blick in Ed Baileys Buch Maximum RPM lohnt sich, es ist bei RedHat erhältlich.
Einige erklärende Worte seien dennoch voran gestellt. Normalerweise baut und testet man ein Programmpaket so, wie in dessen Installationsanweisungen beschrieben ist, findet möglicherweise einige Fehler und bringt vereinzelt Änderungen an. Dann simuliert man eine Installation, üblicherweise durch das Umdefinieren von Variablen wie prefix oder DESTDIR in der Kommandozeile von make install, so dass beispielsweise Dateien, die für den /usr-Baum bestimmt sind, nach, sagen wir, /var/tmp/foo-root/usr gelangen. In diesem Beispiel ist /var/tmp/foo-root die von RPM so genannte Buildroot für das Paket foo. Daraufhin inspiziert man den Dateibaum unter der Buildroot, um heraus zu finden, welche Dateien installiert werden. Schließlich legt man all diese Informationen, einschließlich der verwendeten Patch-, Bau- und Installationskommandos und der ermittelten Dateiliste, zusammen mit einigen Eckdaten über das Paket in einer so genannten Spec-Datei ab.
Anhand dieser Spec-Datei kann RPM nun die gesamte Folge vom Auspacken der Paketquellen und Anbringen der Patches über den Bauvorgang bis zur (simulierten) Installation nachvollziehen. RPM sammelt die zu installierenden Dateien ein und bildet daraus ein oder mehrere Binär-Pakete. Weil dabei keine Systemverzeichnisse berührt werden, sind dazu keine zusätzlichen Berechtigungen erforderlich. Die eigentliche Installation der Binärpakete kann mit einem anderen RPM-Kommando erfolgen, welches dann Root-Privilegien voraussetzt. RPM speichert Daten über alle installierten Pakete und ihre Dateien in einer Datenbank und benutzt diese Informationen bei Verwaltungsaufgaben wie Untersuchung auf nachträgliche Änderungen, Paket-Aktualisierung oder De-Installation.
RPM kann außerdem ein so genanntes Quell-RPM-Paket erzeugen, welches alle Dateien enthält, aus denen das (die) Binär-RPM-Paket(e) gemacht worden sind, also das ursprüngliche Quellarchiv, Patch-Dateien und die Spec-Datei. Somit ist alles, was man für eine Wiederholung des Bauvorgangs benötigt, kompakt zusammengefasst.
Aus dem Gesagten dürfte deutlich geworden sein, dass alles, was man braucht, um irgendein foo.tar.gz von RPM bauen zu lassen, eine Spec-Datei und zuweilen Patch-Dateien sind. Einige entgegenkommende Entwickler fügen ihren herausgegebenen Quellarchiven selber Spec-Dateien hinzu, und RPM kann solche Quellarchive direkt verwenden.
Die folgenden Hinweise gehen davon aus, dass ein System mit installiertem RPM zur Verfügung steht, was bei RPM-basierten Linux-Distributionen natürlich der Fall ist.
Wer mit RPM noch nichts gebaut hat, sollte sicherstellen, dass eine brauchbare Einstellung der optflags z.B. in der Konfigurationsdatei /etc/rpmrc gegeben ist. Man kann das Ergebnis mit folgendem Kommando überprüfen:
rpm --eval '%{optflags}'
Manche Leute mögen hohe und höchste Optimierungspegel, aber ich glaube, dass GCCs -O2 genug ist und einige Fehler des Optimierers am Auftreten hindert. Für einen Pentium-II benutze ich typischerweise die Optionen -mcpu=i686 -O2 -fstrict-aliasing -Wall -Wno-unused.
Als ergänzende Maßnahme sollte man in Erwägung ziehen, eine Datei /usr/share/config.site für GNUs configure anzulegen. Das ist auch ohne RPM nützlich. Zu Details sei auf die autoconf-Dokumentation verwiesen.
Man sollte wissen, wo RPM Quellarchive und Patch-Dateien zu finden
erwartet, wo die Spec-Dateien, wo RPM den Bauvorgang durchführt, wo
die resultierenden Pakete landen usw. In der Regel geschieht das in
Unterverzeichnissen von %{_topdir}; man sollte RPM also
fragen:
rpm --eval '%{_topdir}'
Normalerweise sind die betreffenden Unterverzeichnisse allgemein beschreibbar, so dass reguläre Benutzer RPM-Pakete bauen können. Wer es vorzieht, in seinem Heimatverzeichnis zu bauen, sollte eine Datei ~/.rpmmacros mit etwa folgendem Inhalt anlegen:
# Use the home directory for building.
# Needed dirs (or symlinks): BUILD RPMS/i386 SOURCES SPECS SRPMS
%home /home/chris
%_topdir %{home}
%_tmppath %{_builddir}
%buildroot %{_tmppath}/%{name}-root
Angenommen, das Paket foo soll aus Quellen von foo-1.0.tar.gz mittels RPM gebaut werden. Es sei eine Spec-Datei und unter Umständen auch einige Patch-Dateien für foo-1.0 vorhanden.
Das Quellarchiv und die Patch-Dateien sind in dasjenige Verzeichnis zu verschieben, wo RPM die Quellen vorzufinden erwartet, z.B. in /usr/src/packages/SOURCES/. In der Regel wird man die Spec-Datei im dazugehörigen SPECS-Verzeichnis halten.
Nun ist das Kommando rpm -ba foo.spec auszuführen, wobei foo.spec der Pfadname der Spec-Datei sein soll. (Gegebenenfalls sind Verzeichniskomponenten einzufügen.) Wenn alles gut geht, baut (-b) RPM nun alle (-a) erzeugbaren RPM-Pakete, d.h., sowohl das Quellpaket als auch ein oder mehrere Binärpakete. Das Quellpaket landet dabei z.B. in /usr/src/packages/SRPMS/, Binärpakete etwa in /usr/src/packages/RPMS/i386/. Die Buildroot für die Pseudo-Installation ist typischerweise ein Unterverzeichnis von /var/tmp/.
Um die dabei auftretenden Bildschirmausgaben in einer Protokolldatei zu speichern, sollte obiges Kommando verfeinert werden wie folgt:
rpm -ba foo.spec 2>&1 | tee foo-1.0.log
Die Protokolldatei kann im Fehlerfall nützlich sein und sollte selbstverständlich auf Warnungen oder sonstige Anzeichen seltsamer Vorgänge untersucht werden.
Das oder die erhaltenen Binärpakete können, sobald man über root-Rechte verfügt, mit folgendem exemplarischen Kommando (wirklich) installiert werden:
rpm -Uvh /usr/src/packages/RPMS/i386/foo-1.0-1.i386.rpm # or whatever
Damit ist das Paket foo ordentlich ins System integriert. (Anmerkung: -U bedeutet Upgrade Package, das -vh dient lediglich zur Ausgabe eines Fortschrittsbalkens.)
Sofern man mit der Installation zufrieden ist, kann man nun den beim Bauen entstandenen Dateibaum in /usr/src/packages/BUILD/ entfernen. Das kann entweder direkt geschehen oder mit dem Kommando
rpm --clean foo.spec
(wobei anzumerken ist, dass die --clean-Option
nicht mit dem %clean-Abschnitt in der
Spec-Datei zu verwechseln ist, welcher die Pseudo-Installation
rückgängig macht. Wenn Binär-RPM-Pakete erfolgreich gebaut werden,
kommen die %clean-Kommandos automatisch zur Ausführung,
aber der Dateibaum, in welchem gebaut worden ist, bleibt erhalten,
wenn nicht die Option --clean gegeben wird.)
Auf ähnliche Weise kann man nun das Quellarchiv und die Patch-Dateien aus /usr/src/packages/SOURCES/ löschen, da man stattdessen ein Quell-RPM-Paket hat. (Hat man?) RPM erledigt das von sich aus, wenn man das folgende Kommando gibt:
rpm --rmsource foo.spec
Zu beachten ist, dass die Spec-Datei damit nicht gelöscht wird, obwohl sie ebenfalls im Quell-RPM zu finden ist. Die Spec-Datei kann manuell oder mit der Option --rmspec gelöscht werden.
Ebenfalls bemerkenswert ist, dass die Optionen --clean und --rmsource ebenso gut dem Baukommando rpm -b hinzugefügt werden können. D.h., man kann RPM-Pakete bauen und anschließend aufräumen lassen, indem man ein einziges Kommando gibt:
rpm -ba --clean --rmsource foo.spec 2>&1 | tee foo-1.0.log
Sollten die Quellen, die Patch-Dateien und/oder die Spec-Datei jemals wieder benötigt werden, kann man das Quell-RPM-Paket auspacken, indem man RPM auffordert, es zu installieren:
rpm -i /usr/src/packages/SRPMS/foo-1.0-1.src.rpm
Im Gegensatz zur Installation eines Binär-RPMs bedarf die Installation eines Quell-RPMs keiner besonderen Privilegien, solange die SOURCES- und SPECS-Verzeichnisse beschreibbar sind.
In dem speziellen Fall, dass man nur das Quell-RPM-Paket auspacken, von RPM neu bauen lassen und danach aufräumen lassen möchte, genügt folgendes Kommando:
rpm --rebuild /usr/src/packages/SRPMS/foo-1.0-1.src.rpm 2>&1 | tee foo-1.0.log
Vor der Verwendung der Spec-Datei sollte diese durchgesehen
werden. Zuweilen kommentiere ich einige anwendbare Teile aus, z.B.
Patches für experimentelle Erweiterungen oder zeitaufwendige
make check-Kommandos, deren Ausführung normalerweise
ratsam ist. Auch Require-Direktiven sollten überprüft
werden, da es durchaus sein kann, dass man einige der geforderten
Pakete zwar installiert hat, aber unter anderem Namen. Und natürlich
können die Kommentare in der Spec-Datei nützliche Gebrauchshinweise
enthalten.
In jedem Falle zu beachten ist, dass die meisten Patches spezifisch für eine ganz bestimmte Version des betreffenden Programmpaketes sind. Spätere Versionen könnten bereits repariert sein, in gleicher oder völlig anderer Weise, oder könnten immer noch fehlerhaft sein, aber dann könnten die Patches unvollständig oder unangemessen oder aus anderen Gründen nicht anwendbar sein.
Wenn eine Spec-Datei für eine neuere Paketversion vorbereitet wird, sollten alle vorherigen Patches deaktiviert werden. Man könnte versuchen, heraus zu finden, ob die alten Patches noch passen und, durch eingehende Inspektion des Quellkodes, ob sie noch angewendet werden sollten und welche zusätzlichen Änderungen dazu erforderlich sein könnten. Das beste Ergebnis wäre eine angepasste Patch-Datei, die auf die neue Paketversion maßgeschneidert ist.
RPM fügt jeder Versionsnummer eine Ausgabenummer hinzu. Die Versionsnummer sollte die offizielle Versionsnummer des verwendeten Quellarchivs wiedergeben, während eigene Modifikationen und Weiterentwicklungen dieser Version mit der Ausgabenummer gezählt werden können. Wenn das Programmpaket geändert wird, ohne auf eine neue offizielle Version zuzugreifen, sollte nur die Ausgabenummer erhöht werden. Wenn eine neue offizielle Version gebaut wird, ist die Versionsnummer in der Spec-Datei anzupassen; die Ausgabenummer kann dann auf 0 oder 1 zurückgesetzt werden.
Sobald man einige RPM-Pakete erfolgreich gebaut hat, möchte man sie evtl. zur allgemeinen Verfügung stellen. Binäre RPMs sind installationsfertig und demgemäß recht bequem, sie tragen aber eine Menge Abhängigkeiten vom Bausystem mit sich. Da sind zunächst die Spezialisierung auf eine Prozessorfamilie oder sogar einen bestimmten Prozessortyp, sodann die Festlegung auf bestimmte Versionen dynamischer Programmbibliotheken und einige andere Dinge, welche Binär-RPMs wenig portabel machen. RPM stellt die meisten dieser Abhängigkeiten fest und verweigert (normalerweise) die Installation von RPMs mit nicht erfüllten Abhängigkeiten. Solche RPMs sind dann eher nutzlos. Sie zu besitzen, hilft einem Benutzer nicht einmal dann, wenn er sich entschließt, das Paket nachzubauen, weil die Spec-Datei woanders ist, nämlich im Quell-RPM. Die gleichen Einschränkungen ergeben sich bei Aktualisierungen von Programmpaketen jedes Mal aufs Neue.
Die Spec-Datei kann in der Regel mit sehr wenigen Änderungen dazu verwendet werden, spätere Versionen eines Programmpaketes zu bauen. Deswegen stelle ich lediglich Spec-Dateien und Patch-Dateien bereit. Die anderen Quellen können von den offiziellen Stellen heruntergeladen werden, und wenn man dort ist, kann man gleich nach der neuesten Version Ausschau halten.
Eigene Patches sollten den offiziellen Paketautoren mitgeteilt werden, damit man spätere Versionen nicht erneut patchen muss.
Wer eine auf meinen Webseiten gefundene Spec-Datei verwendet, möge erwägen, mir nichttriviale Änderungen mitzuteilen.