Springe zum Hauptinhalt

RPM


RPMs bauen


Kursinhalt:

Stand: April 2006


Grundsätze

  • Ein RPM enthält alle Daten und Anweisungen (%pre, %post, usw.) die nötig sind, um eine Software zu installieren.
    • Konfigurieren ist nicht enthalten, eine sinnvolle Standard-Konfiguration aber gut.
    • Der Prozess des Installierens und Entfernens darf wegen der automatischen Installationsverfahren nicht interaktiv sein; also keine Nutzer-Abfragen in die Anweisungen!

  • Ein Source-RPM enthaelt alle Daten und Anweisungen (das Spec-File) die nötig sind, um RPMs für eine Software zu erstellen.
    • Ein RPM sollte nur in absoluten Ausnahmefällen etwas enthalten, was nicht auch im zugehörigen Source-RPM ist.

  • Der eigentliche Bau-Prozess sollte ausser in absoluten Ausnahmefällen nicht mit root-Rechten durchgeführt werden.
    • Dazu wird mittels eines sog. Buildroot-Verzeichnisses die Installation in %install an irgendeinen frei zugaenglichen temporaeren Platz ausgeführt und die Files von RPM dann so eingepackt, das sie später am richtigen Ort landen.

  • Der Name eines Paketes besteht aus dem eigentlichen Namen, der Version und dem Release: <name>-<version>-<release>
    • Name, Version und Release werden durch - (Minus) getrennt, wobei zu beachten ist, dass die Zählung von rechts nach links erfolgt. Dadurch ist es möglich, auch innerhalb des Namens das Zeichen - (Minus) zu verwenden.
    • Der Name kennzeichnet den Namen des Paketes. Dabei ist zu beachten, dass von einem Paketnamen auch immer nur ein Paket resp. eine Version bzw. Release auf einem System installiert sein kann. D.h. möchte ich 2 Versionen einer Software parallel installieren, müssen sich diese im Namen unterscheiden.
    • Beispiel:
      • gimp-1.2.5-2 und gimp2-2.0.1-1
      • kernel-module-openafs-2.6.9-5.0.5.ELsmp-1.3.80-1.SL.i686 und kernel-module-openafs-2.6.7-5.0.1.ELsmp-1.3.80-1.SL.i686
    • Die Version korrespondiert mit der Softwareversion.
    • Das Release kennzeichnet die Release der Version eines Paketes. Dabei wird zwischen der Softwarerelease und der Paketierungsrelease unterscheiden. Gibt es eine Softwarerelease, so ist diese zuerst in den Releasetag einzufügen. Wird es notwendig, eine Paket der gleichen Version und Softwarerelease noch einmal zu erstellen (z.B. durch Fehler beim Paketbau), so ist an die Softwarerelease eine durch Punkt getrennte Paketierungsrelease anzuhängen und mit jedem Paketbau zu erhöhen.
    • Beispiel:
      • gimp2-2.0.1-1 und gimp2-2.0.1-2
      • usbutils-0.11-6.1 und usbutils-0.11-6.2
    • TU-Chemnitz Spezifika
      • Kennzeichnung erfolgt immer mit dem Suffix tucz
      • Werden Pakete speziell für unserer Einrichtung erstellt oder umgebaut, so ist dies im Releasetag durch den Suffix .tucz zu kennzeichen
        • print-2.6-1.tucz
      • Werden zu existierenden Paketen Anpassungen in Form von RPM-Pakten realisiert, so ist dies im Namen durch den Suffix _tucz zu kennzeichen
        • mozilla_tucz-1.7.7-1


RPM-Build-Repositorys

Mittels des nun vorgestellten Verfahren ist es möglich, die bei der Erstellung von RPMs anfallenden Daten im Filesystem sauber zu strukturieren. Dazu wird mittels rpmrepo an beliebiger Stelle eine lokale RPM-Build-Hierarchie angelegt, darin kann dann am Paket gearbeitet und auch der Bauprozess mit rpmrbuild angestossen werden. Weiterhin können diese Verzeichnisse beliebig bewegt und untereinander umgeordnet werden. Das Kommando rpmrbuild passt die RPM-Topdir Variable automatisch an.

Tip zur Vereinfachung: Wenn man folgende Zeile in ~/.bashrc einträgt, kann man wie gewohnt einfach rpmbuild (ohne 'r') tippen:

    alias rpmbuild='rpmrbuild'

Eine RPM-Build-Hierarchie enthält folgende Unterverzeichnisse:

  • SOURCE: Für die Quellen, Patches, Skripte und sonstigen Daten, die zum Bau das RPM notwendig sind.
  • BUILD: Hier erfolgt die Softwaregenerierung. (Das ist ein Link ins /tmp, damit das AFS nicht bremst.)
  • SPECS: Für das Spec-File.
  • RPMS: Hier legt rpmbuild die fertigen RPMs ab; die Unterverzeichnisse (i386, noarch, usw.) werden automatisch angelegt.
  • SRPMS: Hier legt rpmbuild fertige Source-RPMs ab.
Weitere Verzeichnisse für sonstige Daten können problemlos parallel dazu angelegt werden.

Achtung: Die Skripte löschen den Inhalt von ~/.rpmmacros! Eigene Einstellungen können in ~/.rpmmacros.base erfolgen, diese Datei wird an die erzeugte ~/.rpmmacros angehängt.

Beispiel 1: Bau der Software "foobar" aus einem existierenden Source-RPM.

  • repodir: Basisdirectory unter das das neue Repository gehangen wird
  • srpmdir: hier liegt das alte Source-RPM

  1    cd repodir
  2    rpmrepo foobar
  3    cd srpmdir
  4    rpm -ivh foobar-1.2.3.src.rpm
  5    cd repodir/foobar
  6    .....
  7    cd repodir/foobar/SPECS
  8    rpmrbuild -ba foobar.spec

  • 2: Unterverzeichnis foobar wird im aktuellen Verzeichnis (repodir) und darunter eine Hierarchie angelegt.
  • 4: Das Source-RPM wird in die im Schritt 2 angelegte RPM-Hierarchie installiert, nicht nach /usr/src/redhat/. Alternativ könnte man hier auch ein Tar-File aus dem Netz holen und im SOURCE-Verzeichnis ablegen sowie ein neues Spec-File in SPECS anlegen.
  • 6: Beliebige Arbeiten an Sourcen und Spec-File.
  • 8: Bauprozess starten.

Danach liegen die fertigen RPMs in repodir/foobar/RPMS/....

Beispiel 2: Umbauten an "foobar"

  1    cd repodir/foobar
  2    .....
  3    cd repodir/foobar/SPECS
  4    rpmrbuild -ba foobar.spec

  • 2: Beliebige Arbeiten an Sourcen und Spec-File.
  • 4: Bauprozess starten.

Danach liegen die fertigen RPMs in repodir/foobar/RPMS/....


Spec-File

  • Die Prefix: Zeilen haben nichts mit dem Installationsort zu tun! Wenn RPM feststellt, das es fuer alle im Paket enthaltenen Files passende solche Prefix-Zeilen gibt, gilt das Paket als relokierbar. Braucht das Programm einen festen Installationsort (und das ist wohl der Normalfall), dürfen solche Zeilen nicht im Spec-File enthalten sein.

  • RPM stellt eine Unmenge an Variablen zur Verfügung, z.B. enthalten %{name}, %{version} und %{release} den Inhalt der gleichnamigen Definitionszeilen.

Aufbau eines spec-Files (am unvollständigen Beispiel)

  1    Summary:      Calendar and Day Planner
  2    Name:       plan
  3    Version:    1.8.7
  4    Release:    6
  5    License:    special, see README
  6    Group:       Applications/Productivity
  7    URL:       http://www.bitrot.de/plan.html
  8    Packager:    Karsten Petersen <kapet@hrz.tu-chemnitz.de>
  9    BuildRoot:    %{_tmppath}/%{name}-%{version}-root
 10
 11    Source:       %{name}-%{version}.tar.gz
 12    Source1:    netplan.conf
 13    Patch0:       plan-1.8.7-config.diff
 14    Patch1:       plan-1.8.7-togglesize.diff
 15
 16    %description
 17    plan is a schedule planner based on X/Motif. It displays a month calendar
 18    similar to xcal, but every day box is large enough .......
 19
 20    %prep
 21    %setup -q
 22    %patch0 -p1
 23    %patch1 -p1 -b .togglesize
 24
 25    %build
 26    %configure --with-something=yes
 27    make %{?_smp_mflags}
 28
 29    %install
 30    [ -n "%{buildroot}" -a "%{buildroot}" != / ] && rm -rf %{buildroot}
 31    mkdir -p   %{buildroot}%{_sysconfdir} \
 32          %{buildroot}%{_datadir}/applications
 33
 34    make install DESTDIR=%{buildroot}
 35    install -m755 %{SOURCE1} %{buildroot}%{_sysconfdir}/netplan.conf
 36
 37    cat > %{name}.desktop << EOF
 38    [Desktop Entry]
 39    Name=Plan
 40    Type=Application
 41    Comment=Calendar Program
 42    GenericName=Calendar Program
 43    Exec=/usr/bin/plan
 44    Icon=plan.png
 45    Terminal=0
 46    EOF
 47
 48    desktop-file-install --vendor= \
 49                         --dir=%{buildroot}%{_datadir}/applications \
 50                         --add-category=X-Red-Hat-Base \
 51                         --add-category=Application \
 52                         --add-category=Office \
 53                         %{name}.desktop 
 54    
 55    %clean
 56    [ -n "%{buildroot}" -a "%{buildroot}" != / } && rm -rf %{buildroot}
 57
 58    %files
 59    %defattr(-,root,root)
 60    %doc AUTHORS ChangeLog COPYING NEWS README TODO
 61    %config(noreplace) %{_sysconfdir}/netplan.conf
 62    %{_bindir}/plan
 63    %(_libdir)/plan/*
 64    %{_datadir}/applications/%{name}.desktop 
 65
 66    %changelog
 67    * Mon Feb 20 2004 Karsten Petersen <kapet@hrz.tu-chemnitz.de>
 68    - new patch xx, fixes problem ...
 69    - some changes in %files
 70
 71    * Thu Feb 12 2004 Karsten Petersen <kapet@hrz.tu-chemnitz.de>
 72    - new version 1.8.7

Header-Section

  • 1: Kurzbeschreibung
  • 2: Name des Paketes
  • 3: Version der Software
  • 4: Release des Paketes (ggf. + tucz)
  • 5: Lizenz unter der die Software kommt, meist "GPL" oder "BSD"
  • 6: Klassifizierung nach /usr/share/doc/rpm-*/GROUPS
  • 7: URL der Homepage der Software
  • 8: wer das Paket zusammengebaut hat (also i.d.R. das Spec-File entworfen hat)
  • 9: wo das Programm während des Buildprozesse hininstalliert wird, der Eintrag hier ist allgemeingültig
  • [optional]
    • Requires:
    • Provides:
    • AutoProv: no
    • AutoReq: no

  • 11-14: Quellen und Patches (müssen im SOURCE-Verzeichnis vorhanden sein, werden in das SRPM eingepackt), eine fehlende Zahl entspricht der 0 ("Source:" == "Source0:")

  • 16-18: Beschreibung des Paketes

Prep-Section

bereitet das Paket zur Übersetzung vor, also Quellen in das =%{buildroot}=-Verzeichnis auspacken, Patches anwenden.

  • 21: Auspacken der Daten; "-q" hinter %setup unterdrückt die Ausgabe beim Auspacken des Tar-Files; Unterscheidet sich der Name des Verzeichnisses, welches beim Auspacken der Quellen entsteht von %{name}-%{version}, so muss der Name mit "-n" übergeben werden; %setup -n %{name}-20050512cvs
  • 22-23: Anwenden von Patches; Die Nummer hinter dem Patchmacro koresspondiert mit der Nummer des Patchfiles aus der Headersection. Die OPtion "-p" wird an das Patchkommando übergeben. Soll ein Backup der gepatchten Files entstehen, so kann man das Patchmacro anweisen eine entsprechende Fileendung zu verwenden %patch -b .test

Build-Section

Die ausgepackten und gepatchten Quellen werden übersetzt. Üblicherweise die Schritte autoconf (./configure) und make.

  • 26: Ist die Software für autoconf entworfen, so sollte ./configure durch das Macro %configure ersetzt werden. Dadurch werden dem configure korrekte Argumente für --prefix, --bindir, --mandir usw. übergeben.
  • 27: Für make gibt es kein Macro. %{?_smp_mflags} ist ein Makro, welches make mitteilt, wieviele CPUs im System vorhanden sind und für den Übersetzungsprozess verwendet werden können. Das Macro jat keinen Einfluss auf das entstehende Binary.

Install-Section

Verlief der Übersetzungsprozess erfolgreich, werden die Binarys jetzt installiert. Dabei ist zu beachten, dass die Installation in ein temporäres Verzeichnis, die Buildroot erfolgt. Darunter werden die sonst in der Wurzel zu findenden Verzeichnisse wie etc, usr/bin, usw. aufgespannt. ALERT! Für die Verzeichnisse sollten die vordefinierten Macros verwendet werden! Siehe dazu auch /usr/lib/rpm/macros

  • 30: löscht zunächst die Buildroot
  • 31-32: da wir später ein Konfigfile manuell installieren wollen, legen wir schon mal eine etc/ und ein Verzeichnis für Startmenüsymbole an.
  • 34: Installieren des Programmes in die Buildroot.
  • 35: Das Konfigfile %{SOURCE1} wird manuell in sein Zielverzeichnis installiert.
  • 37-46: Wir erstellen einen Files für das Startmenü.
  • 48: und installieren dieses in die Buildroot mit dem Kommando desktop-file-install

Clean-Section

  • 56: Die Buildroot wird nach erfolgreichem Paketbau entfernt. Treten Fehler während des Paketbaues auf, wird die Cleansection nicht ausgeführt.

Scripts-Section

Die Scriptssection enthält Shellscripte, welche vor bzw, nach der Installation bzw. Deinstallation ausgeführt werden. Beachte unbedingt die Reihenfolge insbesondere beim Upgrade.

  • %pre
  • %post
  • %preun
  • %postun

Files-Section

Beschreibt alle Dateien, die ins Binary-Paket sollen. Es wird bei Definition einer Buildroot automatisch dort gesucht.

  • 59: Standardeinstellungen für Eigentümer und Zugriffsrechte werden festgelegt
  • 60: Dokumentation, aufgeführte Files und Verzeichnisse aus dem Quellpaket werden unter /usr/share/doc/%{name}-%{version} abgelegt
  • 61: Konfigurationsfiles werden mit %config gekennzeichnet. Das hat zur Folge, dass nach einer Modifikation dieser Files ein späteres Verify (rpm -V) keine Fehler (modifizierte Files) meldet. Wird die Option "(noreplace)" angegeben, so wird ein schon vorhandenes Konfigfile bei der Installation bzw. Upgrade nicht überschrieben.
  • 62-64: Zum Paket gehörende Files. (Executables, Librarys, usw)
  • 50-53: Dateien, die in das zusätzliche Binary-Paket sollen

Changelog-Section

  • 67-72: Das Changelog enthält die Paket-Historie; es sollte erkennbar sein, wann und warum das Paket verändert wurde. Das Datum muss im Format LANG=C date +"%a %b %d %Y" sein.


Links

http://www.rpm.org/

http://dag.wieers.com/howto/bits/rpm-build-user.php

http://dag.wieers.com/howto/rpm/

http://www-106.ibm.com/developerworks/library/l-rpm1/

http://freshrpms.net/docs/fight/

http://qa.mandrakesoft.com/twiki/bin/view/Main/RpmHowTo

http://www.fedora.us/docs/spec.html

GURULABS-RPM-GUIDE-v1.0.PDF: RPM-Guide (engl.)


Tips und Tricks für Ausnahmefälle

Beim builden von RPMs erhalte ich die Fehlermeldung: RPM build errors: Installed (but unpackaged) file(s) found:

Das neueste RPM (ab Redhat 9) mag es nicht, wenn Dateien zwar "installiert" werden (in %install), dann aber in der Fileliste fehlen. In dem Fall schlägt das RPM-Erstellen einfach fehl. Abhilfe bringt entweder das Anpassen des Spec-Files (fehlende Files in %install löschen oder mit einpacken) oder ausnahmsweise (wirklich nur ausnahmsweise!) bei ganz schlimmen Fällen folgende Einstellungen in /usr/lib/rpm/macros ändern:
     #%__check_files         /usr/lib/rpm/check-files %{buildroot}
     %_unpackaged_files_terminate_build     0
     %_missing_doc_files_terminate_build    0
     

Was verbirgt sich in den debuginfo-RPMs?

Debuginfo-Pakete werden normalerweise bei jedem Buildprozess generiert. Darin enthalten sind unstripped (mit Debuggersymbolen) Binarys und Bibliotheken sowie die zugehörigen Quellen. Binaries sind unter /usr/lib/debug/, die Quellen unter /usr/src/debug/ zu finden.

Eine coole GUI zum gdb ist ddd

Beim rebuilden von RPMs erhalte ich den Fehler: Could not open %files file */debugfiles.list: No such file or directory

Hier ist das extrahieren von Debuginfos aus den Binary nicht möglich oder fehlgeschlagen. Ggf. kann man verhindern, daß debuginfo-Pakete angelegt werden.
     %define debug_package %{nil}    (im Specfile)
     %debug_package %{nil}         (oder im  ~/.rpmmacros)