RPM-Pakete selbst bauen

Aus LinuxUser 07/2003

RPM-Pakete selbst bauen

Private Paketzentrale

Die meiste Software für Linux liegt im Quellcode vor und muss kompiliert werden. Dies geht schnell von der Hand, doch spätestens wenn man eine Anwendung wieder loswerden will, fangen die Probleme an.

Was sammelt sich nicht im Laufe der Zeit an selbstkompilierter Software auf dem eigenen System an? Hat man bei Binärdateien zumindest eine grobe Vorstellung, wo sie herumliegen, ist man spätestens im Unterverzeichnis /usr/local/lib heillos verloren. Händische Löschaktionen und das Rätselraten nach dem Ursprung einer Datei lassen sich vermeiden, wenn das Paketmanagement der Distribution auch selbstkompilierte Software verwaltet.

Das am weitesten verbreitete Programm dafür ist rpm, der Red Hat Package Manager. Er schreibt nicht nur alle Informationen über die installierten Pakete in seine Datenbank, sondern kümmert sich darüber hinaus auch um die Abhängigkeiten, so dass eine rückstandslose Entfernung möglich wird. Das ist ein unschätzbarer Vorteil, denn selbst wenn Sie eine Bibliothek installiert haben, damit Programm A läuft, können Sie diese nicht bedenkenlos zusammen mit Programm A entfernen. Möglicherweise wurde nachträglich noch weitere Software eingespielt, die ebenfalls auf die fragliche Bibliothek angewiesen ist. RPM wacht darüber und warnt Sie in einem solchen Fall.

Handarbeit bevorzugt

Damit RPM auch selbstkompilierte Software verwaltet, muss aus dem Quellcode erst einmal ein Paket werden. Mit checkinstall [1,2] existiert ein Programm, das die Installation überwacht und beim Aufruf von make install aus den kopierten Dateien ein RPM-Paket baut.

Wie alle automatisierten Lösungen hat auch diese den Nachteil, dass sie nicht alle Möglichkeiten des RPM-Befehls bietet. Sie kann eine Software nicht in mehrere Einzelpakete aufteilen, und bei manchen Programmen verweigert checkinstall ganz die Mitarbeit.

Das gravierendste Manko: Sie erstellt die Dateiliste für das Paket erst während der Installation, man hat also keinerlei Kontrolle darüber, ob nicht Dateien überschrieben werden. Das soll jedoch in einer der nächsten Versionen durch Unterstützung der RPM-BUILDROOT-Option ausgemerzt werden. Damit lassen sich Pakete in einer Art Sandbox bauen, etwa im Verzeichnis /tmp. Das Programm betrachtet /tmp während der Installation als Wurzelverzeichnis, so dass keine System-Dateien überschrieben werden.

Wer keine halben Sachen mag, verlässt sich daher nicht auf Zusatz-Tools, sondern baut seine Pakete selbst. Wie das geht, darüber schweigt sich die RPM-Dokumentation leider weitgehend aus und “Maximum RPM” [3], die Referenz für Paketbauer und alle die es werden wollen, eignet sich wegen des Umfangs von mehreren hundert Seiten nicht für einen schnellen Einstieg.

Um Sie nicht mit trockener Theorie zu Tode zu langweilen, beschreiben wir, wie man ein Paket des Programms xpuyopuyo[4] baut. Das ist ein netzwerkfähiges, Tetris-ähnliches Spiel mit netter Grafik, lustigem Sound und hohem Suchtfaktor(Abbildung 1), sollte also genug Anreiz bieten, die Mühe des Paketbauens auf sich zu nehmen.

Abbildung 1: Das Programm Xpuyopuyo dient als Beispiel zum Erstellen eines RPM-Pakets.

Abbildung 1: Das Programm Xpuyopuyo dient als Beispiel zum Erstellen eines RPM-Pakets.

Vorbereitungen

Wer denkt, er könne sofort loslegen, irrt. Die meisten Distributoren installieren nur die Programme, die nötig sind, um RPMs zu installieren, nicht aber jene, die man zur Erstellung benötigt. In diesem Fall muss zunächst das Paket rpm-build eingespielt werden. Die Packtheke, also das Arbeitsverzeichnis des Paketbauers, befindet sich unterhalb des Verzeichnisses /usr/src, und auch hier geht jeder Distributor eigene Wege. Unter SuSE nennt es sich packages, bei Mandrake RPM, und der amerikanische Marktführer hat den entsprechenden Ordner ganz egozentrisch redhat genannt.

In den dort liegenden fünf Unterverzeichnissen SOURCES, SPECS, BUILD, RPMS und SRPMS geht der Paketbau vonstatten. RPMS und SRPMS nehmen später die erzeugten Binär- und Source-Pakete auf und im Verzeichnis BUILD wird die Software kompiliert. Da Sie beim Erstellen von RPMs die entsprechenden Befehle nicht selbst eingeben, sondern RPM sie aus einer Steuerdatei, dem so genannten Specfile, liest, gibt es in diesem Ordner für Sie nichts zu tun.

Der Paketbauer bewegt sich in SOURCES und SPECS. Unter SOURCES muss sich das tar.gz-Archiv mit der zu verpackenden Software befinden. Liegt Ihr Quellcode in einer anderen Form vor, müssen Sie ihn vorher in ein tar.gz-Archiv umwandeln.

Werden Sie zunächst durch den Befehl su und nachfolgende Eingabe des root– Passwortes zum Administrator. Sie brauchen während des gesamten Build-Prozesses Superuser-Rechte. Man kann auch normalen Benutzern das Paketebauen erlauben, was jedoch kompliziert einzurichten ist. Laden Sie die Datei http://chaos2.org/xpuyopuyo/xpuyopuyo-0.9.7.tar.gz herunter und kopieren Sie sie nach SOURCES. Wechseln Sie danach in das Verzeichnis SPECS. Dort erwartet RPM die Steuerdatei. Wie Sie diese nennen ist egal, es hat sich jedoch eingebürgert, einen Namen nach dem Schema Programmname.spec zu wählen. Öffnen Sie dann als root einen Editor und beginnen Sie mit der Erstellung der Textdatei xpuyopuyo.spec.

Die Präambel

Ein Specfile besteht aus drei Teilen. Im ersten Abschnitt, der Präambel, stehen allgemeine Informationen, aus denen z. B. später der Name des Pakets gebildet wird. Für xpuyopuyo könnte die Präambel aussehen wie in Listing 1.

Listing 1

Präambel des Specfiles für das Xpuyopuyo-Paket

#Specfile fuer xpuyopuyo
Summary: netzwerkfaehiges Tetris-artiges Spiel
Name: xpuyopuyo
Version: 0.9.7
Release: apocalypse
Copyright: GPL
Group: Games/Arcade
Source: xpuyopuyo-0.9.7.tar.gz
URL: http://chaos2.org/
Distribution: Mandrake 9.0
Packager: Andrea Mueller <amueller@linux-user.de>

Ihr Aufbau ist denkbar einfach und bei jedem Paket gleich, so dass man hier mit Vorlagen arbeiten kann. Einem RPM-spezifischen Tag folgt ein Doppelpunkt und dahinter der zugehörige Wert. Aus den Werten hinter Name, Version und Release setzt sich später der Paketname zusammen. Das Version-Tag darf nur Zahlen und Punkte enthalten, ansonsten bricht RPM die Paketerstellung ab.

Im Release-Tag steht bei den Distributoren normalerweise, um die wievielte Paket-Version es sich handelt. Oft bauen Distributoren mehrere Pakete zu ein und derselben Programmversion, etwa weil es Patches dafür gibt oder weil der Distributor nachträglich andere Verbesserungen einbaut. Dieses Feld sollte auch zum Einfügen einer distributionsspezifischen Kennung genutzt werden, was jedoch nur Mandrake konsequent umsetzt. Bei Paketen dieses Distributors finden Sie immer die Buchstabenfolge mdk im Namen. Sie selbst können dorthin schreiben, was Sie mögen: Für das Beispiel muss der Rechnername herhalten. Achten Sie jedoch darauf, dass Sie bestimmte Zeichen wie z. B. das Minus nicht verwenden dürfen. Im Feld Summary ist Platz für die Kurzbeschreibung, das Source-Tag nimmt den Namen des Quellcode-Archivs auf, und das Feld URL enthält Service-Informationen für den Benutzer Ihres Pakets. Er weiß sofort, woher die Software im RPM stammt. Die Distribution-Zeile ist optional, Sie können sie also weglassen. Hinter dem Schlagwort Packager sollte jedoch Ihr Name oder Spitzname und eine gültige E-Mail-Adresse stehen, zumindest dann, wenn Sie das selbstgebaute Paket auch an andere weitergeben. Ein Fehler bei der Paketherstellung ist schnell gemacht, und dann freut sich der Benutzer, wenn er einen Ansprechpartner hat.

Einen kurzen Blick sollte man dem Punkt Group gönnen. Hier legen Sie fest, unter welcher Rubrik grafische Paketverwaltungsprogramme wie z. B. kpackage die Software später einordnen. Theoretisch kann man sich eigene Gruppen ausdenken, will man jedoch Pakete weitergeben, hält man sich besser an die gängigen Konventionen. Die möglichen Gruppennamen stehen in der Datei GROUPS der RPM-Dokumentation unterhalb von /usr/share/doc.

Der Bauplan

Im Hauptabschnitt des Specfiles stehen die Anweisungen zum Entpacken, Konfigurieren und Installieren der Software. Das Vorgehen kann sich von Anwendung zu Anwendung unterscheiden, besteht jedoch meistens aus dem altbekannten Dreisatz

configure
make
make install

Das ist so in etwa auch bei xpuyopuyo der Fall. Hängen Sie also die Zeilen aus Listing 2 an Ihre Spec-Datei an.

Listing 2

Hauptteil des Specfiles für Xpuyopuyo

%description
Netzwerkfähiges tetris-artiges Spiel mit coolem Sound.
%prep
%setup
./configure --prefix=/usr/local --with-gnome=no
%build
make
%install
make install-strip
cp doc/xpuyopuyo.txt /usr/local/share/xpuyopuyo

Einem Prozentzeichen folgen hier RPM-spezifische Schlagworte. Der Punkt %description nimmt den Text auf, der sich Ihnen später präsentiert, wenn Sie mit dem Befehl rpm -qi xpuyopuyo Informationen zum Paket abfragen. Er darf sich über mehrere Zeilen erstrecken und alle Zeichen enthalten. Der Abschnitt %prep beendet die Beschreibung und leitet die Vorbereitung des Build-Prozesses ein. In dieser Phase wird alles erledigt, was nötig ist, um das Quellpaket in einen kompilierfähigen Zustand zu versetzen.

Der Punkt %setup macht Sie mit einer Arbeitserleichterung bekannt, die RPM dem Paketbauer bietet: dem Einsatz von Makros. So wie Sie in einem Office-Programm Makros aufzeichnen können, um immer wiederkehrende Aufgaben zu erledigen, kennt auch RPM solche praktischen Helfer. Das wohl am meisten genutzte ist das Setup-Makro, was gleich mehrere Aufgaben abarbeitet. Es entpackt das im Verzeichnis SOURCES liegende Archiv nach BUILD und wechselt danach mit dem cd-Befehl dorthin. Handelt es sich nicht um den ersten Versuch, das Paket zu bauen, löscht das Setup-Makro vor dem Entpacken der Quellen die Rückstände, die von einem vorherigen Compiler-Lauf in BUILD zurückgeblieben sind.

In der nächsten Zeile der %prep-Sektion beginnt der eigentliche Bau. Den Befehl ./configure würden Sie von Hand aufrufen, wenn Sie das Programm zum Kompilieren vorbereiten wollten. Dessen --prefix-Parameter dient in diesem Fall nur als Beispiel, da das Skript dieses Verzeichnis standardmäßig als Ziel für das Programm auswählt. Sie schreiben hier die configure-Optionen hin, mit denen Sie das Verhalten des Konfigurationsskripts in der Shell modifizieren würden. Sie sollten das Paket wie andere selbstkompilierte Software nach /usr/local installieren. Dadurch haben Sie immer noch eine gewisse Trennung zwischen selbstkompilierter Software und Distributionspaketen. Auch ein Update ist damit kein Problem, sofern Ihr Distributor seine Pakete ordentlich pflegt. Die xpuyopuyo-typische configure-Option --with-gnome=no bewirkt, dass keine Icons für den GNOME-Desktop erstellt und in die Verzeichnisse unterhalb von /usr/share kopiert werden.

In der nun folgenden Sektion %build kompiliert RPM die Software. Bei xpuyopuyo erledigt das wie bei den meisten anderen Paketen der Befehl make. Der nächste Punkt ist dann logischerweise %install, wo das Kommando make install- aufgerufen wird, um die kompilierte Software nach /usr/local zu installieren.

Damit ist der Hauptteil des Specfiles komplett, obwohl es noch weitere Sektionen gibt, die man dort einfügen könnte, so z. B. das %patch-Makro, das die Anwendung von Patches (“Flicken”) automatisiert, die Fehler bereinigen oder der Software zusätzliche Funktionalität verleihen. Mit der %package-Anweisung teilt man Software in mehrere Pakete auf, etwa in programm.rpm, programm-doc.rpm und programm-devel.rpm. Falls Sie einmal ein Paket bauen, das eine Bibliothek enthält, sollten Sie Ihrem Specfile auf jeden Fall die beiden Zeilen

%post
ldconfig

hinzufügen. Das ruft nach der Installation des Pakets den Befehl ldconfig auf. Er registriert die neu eingespielte Bibliothek, so dass Sie auch von anderen Programmen gefunden wird.

Grundsätzlich können Sie in den Unterabschnitten des Hauptteils einer Spec-Datei jeden Befehl aufrufen. In den Abschnitten, die jedoch später bei der Installation des Pakets ausgeführt werden (ein Beispiel dafür ist die %post-Sektion), sollten Sie nur solche Kommandos verwenden, von denen Sie sicher wissen, dass Sie auf jedem Linux-System vorhanden sind.

Der mühsame Teil

Alles ist eingerichtet, doch RPM weiß immer noch nicht, welche Dateien denn nun zum Paket gehören sollen. Sie wissen es bis jetzt genausowenig, denn Sie haben xpuyopuyo ja noch gar nicht installiert. Einen Königsweg, um an die Dateiliste zu kommen, gibt es nicht. Manch einer installiert die Software vorab und lässt sich vom Programm installwatch eine Liste der kopierten Dateien erstellen. Nichts anderes macht checkinstall, und die Methode ist nicht 100-prozentig zuverlässig. Ganz hartgesottene Naturen klauben die Dateiliste aus dem Makefile zusammen. Alternativ installiert man die Software zunächst als normaler Benutzer in ein Unterverzeichnis seines Home. Die Dateiliste bekommt man dann entweder durch ein selbstgeschriebenes Skript oder stellt sie aus der Ausgabe von ls -R selbst zusammen. Natürlich müssen dann im Specfile die Pfade angepasst werden: Statt /home/nutzername/test/bin/date steht im Specfile /usr/local/bin/datei.

Obwohl ziemlich aufwendig ist letztgenannter Weg empfehlenswert. Dadurch, dass Sie das Paket zunächst als normaler Benutzer bauen stellen Sie sicher, dass der “make install“-Aufruf tatsächlich nur Dateien in die Unterverzeichnisse des angegebenen --prefix installiert, und Sie wissen, dass das Makefile keinen fatalen “rm -rf“-Aufruf enthält. Außerdem stellen Sie so sicher, dass beim Build-Prozess alle benötigten Entwicklerpakete vorhanden sind (xpuyopuyo verlangt die Development-Pakete von gtk, xpm, XFree, glib und mikmod).

Manchmal sind auch die Programmierer selbst so nett, ihrer Software ein passendes Specfile mit kompletter Dateiliste beizulegen. Für das Beispiel haben wir in bester Fernsehkoch-Manier schon einmal etwas vorbereitet: Den letzten Teil des Specfiles finden Sie in Listing 3.

Listing 3

Dateiliste für das Xpuyopuyo-Specfile

%files
/usr/local/man/man6/xpuyopuyo.6
/usr/local/bin/xpuyopuyo
/usr/local/share/xpuyopuyo
%doc /usr/local/share/xpuyopuyo/xpuyopuyo.txt

Interessant sind die beiden letzten Zeilen. Ins Verzeichnis /usr/local/share/xpuyopuyo werden bei der Installation mehrere Unterverzeichnisse mit Bildern und Sounds kopiert. Steht im %files-Abschnitt ein Verzeichnis, wird dieses samt Inhalt eingepackt und Bestandteil des Pakets – achten Sie also darauf, dass Ihnen auf keinen Fall die Zeile /usr/local in diesen Abschnitt rutscht. Das vorangestellte %doc in der letzten Zeile markiert die danach genannte Datei als Dokumentation. Diese Datei bekommen Sie angezeigt, wenn Sie bei der Abfrage des Pakets den Befehl rpm -qd xpuyopuyo benutzen. Es gibt noch eine weitere Anwendungsmöglichkeit für das %doc-Tag: Oft bringen Programme Dokumentation mit, die make install nicht kopiert. Steht in der Datei-Sektion des Specfiles eine Zeile der Art

%doc README FAQ CREDITS

kopiert RPM diese drei Dateien aus dem Quellcode-Verzeichnis in ein Unterverzeichnis des defaultdocdir und packt sie mit ins Paket. Das defaultdocdir ist auf jedem System ein anderes, unter Mandrake und Red Hat /usr/share/doc, bei SuSE /usr/share/doc/packages. Der Vorgabewert kann über die Datei .rpmrc im Home-Verzeichnis von root geändert werden.

Wildcards erleichtern das Leben im %files-Abschnitt des Specfiles. Kopiert ein Programm sehr viele Lokalisierungsdateien nach /usr/local/share/locale, erschlägt man alle diese Dateien mit der Zeile:

/usr/local/share/locale/@L: */LC_MESSAGES/programmname.mo

RPM meckert zwar, wenn einige der Sprachverzeichnisse keine Datei dieses Namens enthalten, arbeitet jedoch artig weiter.

Pakete schnüren

Nun ist endlich alles bereit, um das Paket zu bauen. Rufen Sie im Verzeichnis SPECS den Befehl rpm -ba xpuyopuyo.spec auf, unter Red Hat müssen Sie rpmbuild -ba xpuyopuyo.spec eingeben. Der Parameter -b sagt RPM, dass er die Steuerinformationen für den Build-Prozess aus einer Datei lesen soll. In diesem Fall wünschen wir uns einen kompletten Build-Durchlauf, RPM soll also alle Abschnitte des Specfiles abarbeiten und sowohl ein Binär- als auch ein Source-Paket erzeugen. Das signalisiert der Parameter a. Wer auf das Source-RPM verzichten kann, wählt stattdessen b, gibt also rpm -bb xpuyopuyo.spec ein. Der Aufruf rpm -bc xpuyopuyo.spec testet, ob ein Paket überhaupt kompiliert. Dabei wird das Specfile nur bis zum Punkt %build ausgeführt, also keine Dateien kopiert.

Welchen Aufruf Sie auch eingeben, rpm ist in jedem Fall sehr gesprächig. Sie sehen, was der Paketmanager tut und bekommen außerdem auch die Ausgabe der einzelnen Befehlsaufrufe präsentiert:

+ cd xpuyopuyo-0.9.5
+ ./configure --prefix=/usr/local
creating cache ./config.cache

Die mit einem Plus-Zeichen beginnenden Zeilen zeigen die Aktionen von RPM, hier den Wechsel ins Quellcode-Verzeichnis und den Aufruf des ./configure-Befehls. Danach folgen die Ausgaben des aufgerufenen Skripts. Hat alles geklappt, sollten die letzten Zeilen aussehen wie in Abbildung 2.

Abbildung 2: RPM hat ein Binär- und ein Source-Paket erzeugt.

Abbildung 2: RPM hat ein Binär- und ein Source-Paket erzeugt.

Vor der Erfolgsmeldung sieht man, dass RPM in gewissem Rahmen selbst ermittelt, welche Abhängigkeiten ein Paket hat. Dafür wird für jede eingepackte Binärdatei der Befehl ldd aufgerufen, der ermittelt, gegen welche Bibliotheken ein Programm gelinkt ist. Dem neu entstandenen xpuyopuyo-Paket wird also die Installation verweigert, wenn die mikmod-Bibliothek nicht installiert ist. Abhängigkeiten, die ldd nicht erkennt, muss man ins optionale Tag Requires: in der Präambel zu schreiben. Das Mail-Programm Mutt beispielsweise benötigt einen lokalen Mailserver, enthält also das Tag Requires: mailserver. Das Gegenstück dazu ist das Tag Provides:. Ein Distributor, der seine Pakete gut pflegt, wird Provides: mailserver in die Präambel von sendmail und postfix schreiben.

Das fertige Binärpaket liegt nun im Unterverzeichnis i686 des Ordners RPM. Auf welchen Prozessor-Typ optimiert wird, ist distributionsabhängig, kann aber jederzeit durch die rpm-Kommandozeilenoption --target Prozessortyp überschrieben werden.

Der Aufruf make install-strip im Specfile kopiert die xpuyopuyo-Dateien zwar, nimmt das neu erstellte Paket jedoch nicht in die Paketdatenbank auf. Um das Tetris-Spiel dort hinzuzufügen, installiert man das Paket über den Aufruf rpm -i ../RPMS/i686/xpuyopuyo-0.9.5-apocalypse.i686.rpm. Falls Sie sich nicht mehr im Verzeichnis SPECS befinden, geben Sie den absoluten Pfad ein. Mit dem Befehl rpm -qil xpuyopuyo | less können Sie danach alle Informationen zu Ihrem selbstgebauten Paket abfragen.

Sicher hat jeder schon einmal ein Paket installiert, bei dem dann manches nicht so funktionierte wie erwartet. Oft liegt das nur an einer fehlenden Datei. Um den Benutzern Ihrer Pakete solchen Ärger zu ersparen, testen Sie jedes selbstgebaute RPM erst auf einem anderen Rechner als dem Build-System, bevor Sie es weitergeben.

Glossar

make install

Dieser Aufruf führt den install-Abschnitt des Makefiles aus. Dabei werden die Dateien, die zu einer Anwendung gehören in die Zielverzeichnisse auf dem System kopiert.

strip

Dieser Befehl entfernt Symbole aus Binärdateien und verkleinert sie dadurch. Diese Symbole helfen Programmierern dabei, Probleme zu debuggen. Um sie sich zu lassen verwendet man den Befehl nm. Man sieht in der Ausgabe z. B., welche Funktionen eine Bibliothek bereitstellt. Entfernt man die Symbole aus Binärdateien, verringert das deren Größe erheblich, weshalb fast alle Distributoren nur gestrippte Programme und Bibliotheken ausliefern.

LinuxUser 07/2003 KAUFEN
EINZELNE AUSGABE
ABONNEMENTS
TABLET & SMARTPHONE APPS
E-Mail Benachrichtigung
Benachrichtige mich zu:

Hinweis: Dieser Artikel ist älter als ein Jahr, enthaltene Informationen sind möglicherweise veraltet.

0 Kommentare
Älteste
Neuste Beste Bewertung
Inline Feedbacks
Alle Kommentare anzeigen
Nach oben