Ein eigenes RPM-Paket zusammenzustellen ist recht einfach, insbesondere wenn man die Software, die man zu einem Paket zusammenpacken möchte, dazu bringen kann, ohne Eingriff eines Nutzers automatisch zu kompilieren. Wir setzen voraus, daß Sie wissen, wie man ein Programm aus den Quellen kompiliert. Wenn nicht, sollten Sie vielleicht zuerst Literatur zu diesem Thema lesen, und später mit dieser Einführung fortfahren.
Der grundlegende Ablauf beim Erstellen eines RPM-Paketes ist wie folgt:
Standardmäßig erzeugt der RPM sowohl Quell- als auch Binärcode.
Kommen wir zuerst zu den Spec-Dateien. Sie sind erforderlich, um ein Paket zu erstellen. Sie enthalten eine Beschreibung der Software, Hinweise zum deren Übersetzung, sowie eine Dateiliste aller Binaries, die installiert werden.
Es wird empfohlen, die Spec-Datei entsprechend der Standardkonvention zu benennen. Diese lautet »Paketname-Strich-Versionsnummer-Strich-Releasenummer- Punkt-spec«.
Hier ein Beispiel für eine Spec-Datei (eject-2.0.2-1.spec):
Summary: A program that ejects removable media using software control.
Name: eject
Version: 2.0.2
Release: 3
Copyright: GPL
Group: System Environment/Base
Source: http://metalab.unc.edu/pub/Linux/utils/disk-management/eject-
2.0.2.tar.gz
Patch: eject-2.0.2-buildroot.patch
BuildRoot: /var/tmp/%{name}-buildroot
%description
The eject program allows the user to eject removable media
(typically CD-ROMs, floppy disks or Iomega Jaz or Zip disks)
using software control. Eject can also control some multi-
disk CD changers and even some devices' auto-eject features.
Install eject if you'd like to eject removable media using
software control.
%prep
%setup -q
%patch -p1 -b .buildroot
%build
make RPM_OPT_FLAGS="$RPM_OPT_FLAGS"
%install
rm -rf $RPM_BUILD_ROOT
mkdir -p $RPM_BUILD_ROOT/usr/bin
mkdir -p $RPM_BUILD_ROOT/usr/man/man1
install -s -m 755 eject $RPM_BUILD_ROOT/usr/bin/eject
install -m 644 eject.1 $RPM_BUILD_ROOT/usr/man/man1/eject.1
%clean
rm -rf $RPM_BUILD_ROOT
%files
%defattr(-,root,root)
%doc README TODO COPYING ChangeLog
/usr/bin/eject
/usr/man/man1/eject.1
%changelog
* Sun Mar 21 1999 Cristian Gafton <gafton@redhat.com>
- auto rebuild in the new build environment (release 3)
* Wed Feb 24 1999 Preston Brown <pbrown@redhat.com>
- Injected new description and group.
[ Einige changelog Einträge gekürzt. -Editor. ]
Die erläuternden Texte wie %description
oder Summary
sollten
sinnvollerweise in Englisch verfaßt werden, es sei denn, es handelt sich um ein
Paket, das nur für deutschsprachige Anwender gedacht ist.
Der Header hat einige Standardfelder, die angegeben werden müssen. Es gibt hier auch ein paar kleine "Problemzonen", die man kennen sollte. Die Felder haben folgenden Inhalt:
Source0: blah-0.tar.gz
Source1: blah-1.tar.gz
Source2: fooblah.tar.gz
Diese Dateien würden im SOURCES
Verzeichnis gespeichert werden. Die
Verzeichnisstruktur wird später im Abschnitt »Die Struktur der
Quellenverzeichnisse« diskutiert.
Patch0: blah-0.patch
Patch1: blah-1.patch
Patch2: fooblah.patch
Diese Dateien werden ebenfalls im SOURCES
Verzeichnis gespeichert.
gnorpm
, mit, wo es in der Pakethierarchie
einzuordnen ist. Die aktuelle Beschreibung findet sich in
/usr/doc/rpm*/GROUPS
. Der Groups-Baum sieht zur Zeit etwa so aus:
Amusements/Games
Amusements/Graphics
Applications/Archiving
Applications/Communications
Applications/Databases
Applications/Editors
Applications/Emulators
Applications/Engineering
Applications/File
Applications/Internet
Applications/Multimedia
Applications/Productivity
Applications/Publishing
Applications/System
Applications/Text
Development/Debuggers
Development/Languages
Development/Libraries
Development/System
Development/Tools
Documentation
System Environment/Base
System Environment/Daemons
System Environment/Kernel
System Environment/Libraries
System Environment/Shells
User Interface/Desktops
User Interface/X
User Interface/X Hardware Support
Dies ist der zweite Abschnitt der Spec-Datei. Hiermit werden die Quellen fürs
Übersetzen angepaßt. Man sollte hier alle Dinge veranlassen, die nötig sind, um
die Quellen zu patchen und für ein make
vorzubereiten.
Anmerkung: Jeder dieser Abschnitte ist eigentlich nur ein Platz, an dem Shellskripte ausgeführt werden. Man könnte einfach ein Shellskript schreiben, das nach dem %prep Tag eingetragen wird und die Quellen entpackt und patcht. Wir haben jedoch Makros geschrieben, die das ein wenig vereinfachen sollen.
Das erste dieser Makros ist das %setup Makro. Im einfachsten
Fall (keine Parameter auf der Kommandozeile) entpackt es nur die Quellen und
macht ein cd
ins Quellverzeichnis. Es versteht die folgenden Optionen:
-n name
setzt den Namen des Übersetzungsverzeichnisses auf den
angegebenen Namen name. Der Defaultwert ist $NAME-
$VERSION. Andere Möglichkeiten sind $NAME,
${NAME}${VERSION} oder was immer das Haupttararchiv
enthält. (Man beachte, daß die hier genannten »$« Variablen
keine echten Variablen, die in der Spec-Datei zur Verfügung stehen,
sind, sondern nur als Platzhalter anstelle von Beispielnamen stehen. Man muß die
echten Namen und Versionen der Pakete einsetzen, keine Variablen.)
-c
erstellt das angegebene Verzeichnis und wechselt dorthin
vor dem Entpacken.
-b #
entpackt Source# vor dem Wechseln in das
Verzeichnis (nicht in Verbindung mit -c
verwenden). Diese Option ist
nur sinnvoll für mehrere Quelldateien.
-a #
entpackt Source# nach dem Wechseln in das
Verzeichnis.
-T
Diese Option verhindert die Default-Aktion des Entpackens der
Quellen und erfordert ein -b 0
oder -a 0
um die
Hauptquelldatei zu entpacken. Sie wird benötigt, wenn es noch weitere Quellen
gibt.
-D
Den Inhalt des Verzeichnisses nicht vor dem Entpacken
löschen. Dies ist nur sinnvoll, wenn man mehr als ein Setup-Makro hat. Die
Option sollte nur in Setup-Makros nach dem ersten Makro
benutzt werden, nie im ersten.
Das nächste bereitgestellte Makro ist das %patch Makro. Dieses Makro erleichtert das Anwenden von Patches auf die Quellen. Es kennt die folgenden Optionen:
#
verwendet Patch# als Patchdatei.
-p #
gibt die Anzahl der Verzeichnisse an, die für das
patch(1) Kommando vom Pfad entfernt werden.
-P
Die Default-Aktion ist das Anwenden von Patch
bzw.
Patch0
. Dieses Flag unterbindet dies und erfordert ein 0
zum
entpacken der Hauptquelldatei. Diese Option ist nützlich für die Anwendung eines
zweiten (oder noch weiteren) %patch
Makros, wenn für dieses eine
andere Anzahl als für das erste Makro erforderlich ist.
%patch#
ist an Stelle des eigentlichen Kommandos
%patch # -P
auch möglich
-b erweiterung
Macht eine Backup-Kopie der Originale als
dateiname.erweiterung
vor dem patchen.
Das sollten alle Makros sein, die man benötigt. Wenn man diese richtig verstanden hat, kann man auch beliebige andere Typen von Setup's nach Art der Shell-Skripte erstellen. Alles was bis zum %build Makro, näher erläutert im nächsten Abschnitt, eingefügt wird, wird von der Shell abgearbeitet. Siehe das Beispiel oben für Aktionen, die hier ausgeführt werden können.
Für diesen Abschnitt gibt es eigentlich keine eigenen Makros. Hier werden alle
Kommandos eingetragen, die notwendig sind, um ein Programm zu übersetzen,
nachdem die Quellen entpackt und gepatcht wurden und man ins entsprechende
Verzeichnis gewechselt hat. Dies ist im wesentlichen nur eine weitere Folge von
Anweisungen, die der Shell zur Ausführung übergeben werden, d.h. alle gültigen
sh
-Kommandos können hier benutzt werden, inklusive Kommentare.
Man beachte, daß das aktuelle Verzeichnis nach jedem dieser Abschnitte wieder auf das Toplevel-Verzeichnis der Quellen gesetzt wird. Man kann, wenn notwendig, in ein Unterverzeichnis wechseln.
Die Variable RPM_OPT_FLAGS
wird entsprechend den Werten in
/usr/lib/rpm/rpmrc
gesetzt. Stellen Sie sicher, das dort Ihrem System
entsprechende Werte stehen (in den meisten Fällen dürfte das der Fall sein). Da
die Verwendung der Variablen in der Spec-Datei optional ist, kann dies
alternativ auch unterbleiben.
Auch für diesen Abschnitt gibt es eigentlich keine Makros. Es werden hier alle
Kommandos aufgelistet, die notwendig sind, um das fertige Programm zu
installieren. Falls das Paket ein make install
hat, kann man es hier
einsetzen. Wenn nicht, kann das Makefile entsprechend gepatcht werden, oder die
Installation manuell mit Shellkommandos bewerkstelligt werden. Das aktuelle
Verzeichnis ist hier wieder das Toplevel-Verzeichnis der Quellen.
Die Variable RPM_BUILD_ROOT
enthält den Pfad, der im Abschnitt
Buildroot: im Header festgelegt wurde. Die Verwendung von Build-Roots
ist optional, wird aber empfohlen, da dies verhindert, daß sich Softwarepakete
im System breit machen, die nicht in der RPM-Datenbank verzeichnet sind (das
Erstellen von RPM-Paketen hat keinen Einfluß auf die Datenbank - dazu muß man
das soeben erstellte binär-RPM installieren).
Es ist sinnvoll, sicherzustellen, daß das Build-Root leer ist, bevor man ein
Paket zum zweiten mal auf einem System zusammenpackt. Zu diesem Zweck steht das
%clean Makro zur Verfügung. Hier fügt man einfach die
entsprechenden Kommandos für das Entfernen des alten Inhaltes ein. Vorsichtige
Leute testen vorher, ob RPM_BUILD_ROOT
nicht auf /
oder der
Systemintegrität ähnlich abträgliches gesetzt ist.
Hier können Skripte angegeben werden, die vor und nach der Installation und der
Deinstallation von fertig übersetzten Paketen abgearbeitet werden. Eines der
Haupteinsatzgebiete dafür ist das Ausführen von speziellen Programmen, wie z.B.
ldconfig
nach dem Installieren oder Entfernen von Paketen mit Shared
Libraries. Die Makros für die jeweiligen Skripte sind:
%pre
ist das Makro zum Ausführen von Pre-Install Skripten.
%post
ist das Makro zum Ausführen von Post-Install
Skripten.
%preun
ist das Makro zum Ausführen von Pre-Deinstall
Skripten.
%postun
ist das Makro zum Ausführen von Post-Deinstall
Skripten.
Der Inhalt dieser Abschnitte ist ein beliebiges sh
-Skript, jedoch
ohne die #!/bin/sh
Zeile.
In diesem Abschnitt müssen die Dateien des fertig übersetzten Paketes
angegeben werden. RPM hat keine Möglichkeit, herauszufinden, welche Dateien als
Ergebnis eines make install
im System installiert werden. Hierfür gibt
es KEINE Möglichkeit. Es gab Vorschläge, dieses mit einem find
vor und nach dem Installieren zu bewerkstelligen. In einem Multiusersystem, bei
dem zur gleichen Zeit von anderen Prozessen Dateien angelegt werden können, die
mit dem Paket nichts zu tun haben, ist dies jedoch nicht sinnvoll.
Hier gibt es ebenfalls einige Makros für spezielle Zwecke. Die folgenden Makros stehen zur Verfügung:
%doc
bezeichnet die Dokumentation aus dem Quellpaket, die
zusammen mit den übersetzten Binärpaketen installiert werden soll. Sie wird in
/usr/doc/$NAME-$VERSION-$RELEASE
installiert. Man
kann mehrere Dokumente auf einer Kommandozeile auflisten oder je eins pro
Makroaufruf.
%config
bezeichnet die Konfigurationsdateien des Paketes.
Dies beinhaltet z.B. Dateien wie sendmail.cf, passwd usw. Wenn man später das
Paket deinstalliert, werden unveränderte Konfigurationsdateien mit dem Paket
zusammen gelöscht und veränderte mit einem angehängten .rpmsave
gesichert. Auch hier können einem Makro mehrere Dateien übergeben werden.
%dir
bezeichnet ein Verzeichnis in einer Dateiliste,
welches komplett mitsamt Inhalt zum Paket gehört. Normalerweise wird ein
Verzeichnis, das OHNE ein %dir
Makro aufgeführt wird,
zusammen mit seinem KOMPLETTEN Inhalt in die Dateiliste aufgenommen und
später mit dem Paket zusammen installiert.
%defattr
erlaubt das Setzen von Default-Attributen für
Dateien, die nach der defattr Deklaration aufgelistet sind. Die Attribute werden
in der Form (mode, owner, group) angegeben, wobei »mode« die oktale
Angabe der neuen Rechte ist (Form wie bei chmod), »owner« der Nutzername des
Besitzers und »group« die Gruppe der sie zugewiesen werden soll. Man kann für
jedes Feld einzeln den installierten Defaultwert übernehmen, indem man ein - an seiner Stelle angibt, wie im Beispielpaket für das mode-Feld
demonstriert (s.u.).
%files -f <filename>
ermöglicht das Auflisten der
zugehörigen Dateien in einer beliebigen anderen Datei im Übersetzungsverzeichnis
der Quellen. Dies ist sinnvoll, wenn man ein Paket hat, das seine eigene
Dateiliste zusammenstellen kann. Man kann diese Liste dann hier angeben, und muß
sie nicht extra noch einmal hier einfügen.
Das größte Problem der Dateilisten ist das Auflisten von
Verzeichnissen. Wenn man aus Versehen /usr/bin
mit auflistet, werden
alle Dateien in /usr/bin
des Systems als zum Paket gehörig
betrachtet.
Dieses ist ein Protokoll der Änderungen die im aktuellen Update des Paketes vorgenommen wurden. Wenn Sie ein existierendes RPM updaten, ist es empfehlenswert, die gemachten Änderungen hier aufzulisten.
Das Format ist einfach. Jeder neue Eintrag beginnt mit einem »*«, gefolgt vom Datum, Ihrem Namen, und Ihrer E-Mail Adresse. Das Datum sollte dasselbe Format haben wie die Ausgabe des Kommandos
date +"%a %b %d %Y"
Der Rest ist ein Freiform-Textfeld, das entsprechend seines Inhaltes etwas
strukturiert werden sollte.