Paketbau-Tutorial 1: banner

Dieses Tutorial demonstriert die Erstellung von RPM-Paketen anhand des Programms banner. Es handelt sich um ein einfaches Programm mit einem einfachen GNU Autotools-Bauskript.

Ausführliche Informationen zum Erstellen von RPM-Dateien finden Sie im RPM-Referenzhandbuch. Wenn Sie ein RPM-Paket für das Fedora-Repository erstellen möchten, folgen Sie dem unter Beitritt zu den Paketbetreuern beschriebenen Prozess und beachten Sie dabei die entsprechenden Fedora-Richtlinien.

Dieses Tutorial ist für ein Fedora-42-System konzipiert. Es sollte jedoch auch mit anderen Fedora-Versionen funktionieren. Ersetzen Sie einfach Zeichenfolgen wie f42 durch Ihre Versionsnummer. Da dieses Tutorial Fedora-spezifische Funktionen verwendet, die in anderen Umgebungen möglicherweise nicht verfügbar sind, kann es sein, dass es mit Fedora-basierten Systemen wie CentOS Stream oder Red Hat Enterprise Linux nicht funktioniert.

Das Tutorial ist schrittweise aufgebaut, wobei in den meisten Schritten die Spec-Datei des Pakets bearbeitet wird. Die resultierende Spec-Datei ist am Ende aufgeführt. Sollten Sie also Fragen zur Anwendung einer bestimmten Änderung haben, können Sie dort nachsehen.

Paketbauwerkzeuge installieren

Zunächst müssen Sie die Paketbauwerkzeuge installieren.

Erstellen des Paketverzeichnisses

In Fedora sind die Anweisungen zum Erstellen von Paketen in sogenannten dist-git-Repositories organisiert. Für jedes Paket gibt es ein separates Repository. Wir bilden dieses System nach, indem wir für dieses Tutorial ein neues Verzeichnis erstellen. In dist-git entspricht der Repository-Name dem Paketnamen. Die Benennung von Fedora-Paketen ist in den Richtlinien zur Benennung beschrieben. Für das Paket „banner“ sollte es einfach banner heißen. Dies ist auch der Name des offiziellen Banner-Pakets von Fedora.

$ mkdir banner && cd banner

In einer Spec-Datei

RPM-Pakete werden mithilfe von .spec-Dateien konfiguriert. Werkzeuge wie rpmdev-newspec können verwendet werden, um leere Spec-Dateien für verschiedene Zwecke zu erzeugen. Erstellen Sie für dieses Tutorial einfach eine Datei namens banner.spec und fügen Sie die folgende minimale Spec-Datei ein. Sie funktioniert noch nicht, aber wir werden versuchen, das Paket zu bauen und auftretende Fehler zu beheben.

Name:     banner
Version:  1.3.6
Release:  %autorelease
Summary:  Prints a short string to the console in very large letters
License:  GPL-2.0-only
URL:      https://github.com/pronovic/banner
Source:   https://github.com/pronovic/banner/releases/download/BANNER_V%{version}/banner-%{version}.tar.gz

%description
This is a classic-style banner program similar to the one found in Solaris or
AIX in the late 1990s. It prints a short string to the console in very large
letters.

%prep
%autosetup

%build
%configure
%make_build

%install
%make_install

%files

%changelog
%autochangelog

Die Spec-Datei beginnt mit einer Reihe von Tags, wie z.B. Name: und Version:, gefolgt von Abschnitten wie %description und %prep. Jeder Tag steht in einer eigenen Zeile, während sich jeder Abschnitt bis zum Beginn des nächsten fortsetzt.

Beachten Sie, dass das Prozentzeichen % verwirrenderweise nicht nur die Abschnittsnamen kennzeichnet, sondern auch RPM-Makros. Daher sind %autosetup, %configure, %make_build, %make_install und %autochangelog keine Abschnitte.

Tags

Version enthält die Versionsnummer der paketierten Software.

Release nummeriert Aktualisierungen der Spec-Datei, Paketneuerstellungen und andere Arbeiten innerhalb von Fedora. Der hier verwendete Wert %autorelease ist Teil von rpmautospec, das für Fedora-Pakete empfohlen wird. Er verknüpft Release mit dem Git-Verlauf des Pakets. Da wir kein Git-Repository verwenden, wird %autorelease standardmäßig auf den Wert 1 gesetzt.

Der Inhalt von Summary kann oft aus der README-Datei des Quellcodes kopiert werden. Der erste Buchstabe sollte großgeschrieben werden, um Fehlermeldungen von rpmlint zu vermeiden.

License beschreibt die Lizenz des resultierenden Binärpakets mithilfe einer SPDX-Lizenzkennung. Sie muss den Fedora-Lizenzierungsrichtlinien entsprechen. In der Praxis erfordert die Ermittlung des korrekten Werts häufig die Prüfung der Lizenzhinweise in den einzelnen Quelldateien. Gegebenenfalls müssen auch die Entwickler des Upstream-Projekts um Klärung oder Korrektur gebeten werden. In diesem Tutorial gehen wir einfach davon aus, dass die Lizenz die GNU General Public License, Version 2, ist.

URL verweist auf die Website des Upstream-Projekts, in diesem Fall die Seite des GitHub-Repositorys.

Source definiert die beim Erstellen des Pakets verwendeten Quelldateien. Normalerweise handelt es sich, wie in diesem Fall, um eine URL, die auf ein vom Quellcode bereitgestelltes Tar-Archiv verweist. Es kann aber auch eine lokale Datei sein. Bei Bedarf können mehrere Source-Tags verwendet werden.

Abschnitte

%description kann oft aus der README-Datei des Upstream-Projekts kopiert werden.

%prep enthält ein Shell-Skript zur Vorbereitung der Quellen für den Bauprozess. Oft handelt es sich dabei lediglich um das Makro %autosetup, das in diesem Fall die Quellen entpackt.

%build enthält ein Shell-Skript für die erforderlichen Bauschritte, wie beispielsweise das Kompilieren von Quellcode zu Binärdateien. Da das Bausystem von Banner auf Autotools basiert, erfordert der Bauprozess die Ausführung von configure und make. Die Makros %configure und %make_build rufen diese Befehle mithilfe der Kompilierungsflags von Fedora und weiterer Konfigurationen auf.

%install enthält ein Shell-Skript, das die Ergebnisse von %build in ein anfänglich leeres Buildroot-Verzeichnis kopiert. Da Banner Autotools verwendet, kommt das Makro %make_install zum Einsatz.

%files listet den Inhalt des resultierenden Pakets auf. Die Dateien stammen größtenteils aus dem Build-Verzeichnis, das mit %install erstellt wurde. Dokumentations- und Lizenzdateien können aber auch direkt aus den Quellen hinzugefügt werden. Dieser Abschnitt ist vorerst leer und wird später ausgefüllt.

Das %changelog (Änderungsprotokoll) dokumentiert die Änderungen in jeder neuen Paketversion und jeder Veröffentlichung. Die Changelog-Daten können mit rpm --query --changelog PAKETNAME angezeigt werden. Dies ist beispielsweise nützlich, um herauszufinden, ob bestimmte Bug- und Sicherheitspatches enthalten sind. Der Wert %autochangelog stammt ebenfalls aus rpmautospec. Er füllt das Änderungsprotokoll mit Git-Commit-Nachrichten. Da wir kein Git-Repository verwenden, ist das Änderungsprotokoll leer.

Nicht benötigte Zeilen können mit dem Hash-Zeichen # auskommentiert werden.

Weitere Informationen finden Sie im Abschnitt Spec-Dateiformat des RPM-Referenzhandbuchs.

Herunterladen der Quellen

Wir benötigen den durch das Source-Tag definierten Quellcode, der oft auch als Upstream-Quellcode bezeichnet wird. Dies lässt sich am einfachsten mit dem Befehl spectool erreichen:

$ spectool -g banner.spec

Die Datei sollte nun im Verzeichnis Source Ihres Arbeitsverzeichnisses aufgeführt sein:

$ ls *.tar.gz
banner-1.3.6.tar.gz

Bau des Pakets

Wir sind bereit für den ersten Durchlauf zum Erstellen von Quellcode-, Binär- und Debugging-Paketen. Dies und viele weitere Aufgaben werden mit dem Werkzeug fedpkg erledigt. Die Produktionsversionen von Fedora werden im Bausystem Koji erstellt, welches wiederum Mock zur Verwaltung isolierter Bauumgebungen verwendet. Um lokal eine möglichst produktionsnahe Umgebung zu erreichen, nutzen wir den Befehl fedpkg mockbuild, der ebenfalls Mock aufruft:

$ fedpkg --release f42 mockbuild

Die von Mock erstellte Bauumgebung ist sehr einfach. Sie enthält standardmäßig keinen C-Compiler, daher schlägt der Bauvorgang fehl. Der Grund dafür wird in der Ausgabe erläutert:

checking whether the C compiler works... no
configure: error: in `/builddir/build/BUILD/banner-6':
configure: error: C compiler cannot create executables
See `config.log' for more details

RPM build errors:
error: Bad exit status from /var/tmp/rpm-tmp.R4Tf16 (%build)
    Bad exit status from /var/tmp/rpm-tmp.R4Tf16 (%build)

Zusätzliche Bauwerkzeuge werden durch Hinzufügen von BuildRequires:-Zeilen zur Spec-Datei definiert. In Fedora ist GCC der Standardcompiler, daher muss eine Zeile für gcc hinzugefügt werden. Autotools verwendet ebenfalls make, daher sollte auch dafür eine Zeile hinzugefügt werden. Fügen Sie diese Zeilen nach Source ein:

BuildRequires:   gcc
BuildRequires:   make

Führen Sie den Mock-Build erneut aus.

Dateien installieren

Als Nächstes bemängelt rpm nicht paketierte Dateien, also Dateien, die zwar im System installiert würden, aber nicht als zum Paket gehörig deklariert wurden. Diese müssen im Abschnitt %files deklariert werden. Die Behebung dieser Fehler ist ein iterativer Prozess. Nachdem eine fehlende Datei in der Spec-Datei deklariert wurde, führen Sie fedpkg erneut aus, deklarieren Sie die nächste fehlende Datei usw.

Wir werden die Dateiliste nacheinander durchgehen.

Ausführbare Dateien

Installed (but unpackaged) file(s) found:
/usr/bin/banner

Dies ist das ausführbare Binärprogramm. /usr/bin hat, wie viele andere Systemverzeichnisse, ein Standard-RPM-Makro definiert. Die Makros sollten immer verwendet werden, sofern verfügbar. Daher ist die ausführbare Datei in %files wie folgt aufgeführt:

%files
%{_bindir}/banner

Handbuchseiten

Installed (but unpackaged) file(s) found:
/usr/share/man/man1/banner.1.gz

Die Paketbaurichtlinien enthalten einen eigenen Abschnitt für Handbuchseiten. Gemäß den dortigen Anweisungen werden die Handbuchseiten wie folgt aufgelistet:

%{_mandir}/man1/banner.1.*

An diesem Punkt wird der Mock-Build erfolgreich abgeschlossen, aber es gibt noch weitere Dateien, die wir zum Paket hinzufügen sollten.

Lizenzdatei

Jedes Paket muss seine Lizenz installieren, die mit der Direktive %license gekennzeichnet ist. Im Fall von Banner, wie auch bei vielen anderen Projekten, befindet sich die Lizenzdatei im Hauptverzeichnis des Quellcode-Archivs und wird möglicherweise während der Installation gar nicht in das Buildroot-Verzeichnis kopiert. Ungeachtet dessen kann sie mithilfe eines relativen Pfads im Standardlizenzverzeichnis installiert werden:

%files
%license COPYING

Zusätzliche Dokumentation

Oft enthalten Paketquellen Dokumentationen, die auch für Endbenutzer nützlich sein können. Diese können installiert und mit der Direktive %doc als Dokumentation gekennzeichnet werden. Ähnlich wie bei %license können relative Pfade verwendet werden, um Dateien direkt aus dem Quellcode-Archiv anstatt aus dem Buildroot einzubinden:

%doc AUTHORS ChangeLog NEWS README

Überprüfen des Ergebnisses mit rpmlint

Als Nächstes sollten Sie die Einhaltung der RPM-Designregeln überprüfen, indem Sie rpmlint auf die Spec-Datei, das Source-RPM und das Binär-RPM anwenden. Der Befehl fedpkg lint führt dies aus:

$ fedpkg --release f42 lint

Wenn alles in Ordnung ist, sollten keine Warnungen oder Fehler auftreten. Zur Veranschaulichung haben wir in den vorherigen Schritten absichtlich einen Fehler eingebaut:

 banner.x86_64: E: zero-length /usr/share/doc/banner/NEWS

Beschreibungen verschiedener Fehlercodes können mit rpmlint -e <Fehlercode> abgefragt werden. In diesem Fall muss die unnötige, leere Datei entfernt werden. Ändern Sie die docs-Zeile entsprechend in:

%doc AUTHORS ChangeLog README

Führen Sie fedpkg mockbuild und fedpkg lint erneut aus und beobachten Sie, dass die Ursache der Warnung behoben ist.

Vollständige Spec-Datei

Hier ist die endgültige Version von banner.spec:

Name:           banner
Version:        1.3.6
Release:        %autorelease
Summary:        Prints a short string to the console in very large letters
License:        GPL-2.0-only
URL:            https://github.com/pronovic/banner
Source:         https://github.com/pronovic/banner/releases/download/BANNER_V%{version}/banner-%{version}.tar.gz
BuildRequires:  gcc
BuildRequires:  make

%description
This is a classic-style banner program similar to the one found in Solaris or
AIX in the late 1990s. It prints a short string to the console in very large
letters.

%prep
%autosetup

%build
%configure
%make_build

%install
%make_install

%files
%{_bindir}/banner
%{_mandir}/man1/banner.1.*
%license COPYING
%doc AUTHORS ChangeLog README

%changelog
%autochangelog

Mit dieser Spec-Datei sollten Sie den Bauprozess erfolgreich abschließen und die Quell- und Binär-RPM-Pakete erstellen können.

Überprüfen des Ergebnisses

Nachdem wir eine funktionierende Spec-Datei erstellt und RPM-Pakete daraus generiert haben, können wir das Ergebnis überprüfen. Bevor wir das Ergebnis durch die Installation des Pakets testen, führen wir einige einfache Prüfungen durch. Hierfür kann der RPM-Paketmanager rpm verwendet werden.

Dateien

Dateien auflisten, die im Paket enthalten sind:

$ rpm --query --package --list results_banner/1.3.6/1.fc42/banner-1.3.6-1.fc42.x86_64.rpm
/usr/bin/banner
/usr/lib/.build-id
/usr/lib/.build-id/01
/usr/lib/.build-id/01/360ae02508eaa0a77d216953b8b658a1e90b10
/usr/share/doc/banner
/usr/share/doc/banner/AUTHORS
/usr/share/doc/banner/ChangeLog
/usr/share/doc/banner/README
/usr/share/licenses/banner
/usr/share/licenses/banner/COPYING
/usr/share/man/man1/banner.1.gz

Sie können sehen, dass alle im Abschnitt %files der Spec-Datei aufgeführten Dateien eingebunden sind. Unter /usr/lib/.build-id befindet sich außerdem eine automatisch generierte Datei. Dabei handelt es sich um einen symbolischen Link, der eine Build-ID der Binärdatei banner zu Debugging-Zwecken zuordnet.

Requires

Listen Sie die Laufzeitabhängigkeiten des Pakets mit folgendem Befehl auf:

$ rpm --query --package --requires results_banner/1.3.6/1.fc42/banner-1.3.6-1.fc42.x86_64.rpm
libc.so.6()(64bit)
libc.so.6(GLIBC_2.2.5)(64bit)
libc.so.6(GLIBC_2.3)(64bit)
libc.so.6(GLIBC_2.3.4)(64bit)
libc.so.6(GLIBC_2.34)(64bit)
libc.so.6(GLIBC_2.4)(64bit)
rpmlib(CompressedFileNames) <= 3.0.4-1
rpmlib(FileDigests) <= 4.6.0-1
rpmlib(PayloadFilesHavePrefix) <= 4.0-1
rpmlib(PayloadIsZstd) <= 5.4.18-1
rtld(GNU_HASH)

Um zu überprüfen, welche Pakete in den Fedora-Paketquellen diese Abhängigkeiten bereitstellen, können Sie dnf repoquery verwenden:

$ dnf -C repoquery --whatprovides 'libc.so.6()(64bit)'
glibc-0:2.38-16.fc42.x86_64
glibc-0:2.38-7.fc42.x86_64

Sie werden feststellen, dass glibc die einzige Abhängigkeit von banner ist, welches Symbole in libc.so.6 sowie rtld(GNU_HASH) bereitstellt.

Die rpmlib-Abhängigkeiten sind speziell. Sie geben verschiedene rpm-Funktionen an, die im rpm-Paket selbst verwendet werden, und schränken die Version von rpm ein, die zur Installation des Pakets verwendet werden kann.

Provides

Umgekehrt können Sie, um zu überprüfen, was das Paket bereitstellt, Folgendes tun:

$ rpm --query --package --provides results_banner/1.3.6/1.fc42/banner-1.3.6-1.fc42.x86_64.rpm
banner = 1.3.6-1.fc42
banner(x86-64) = 1.3.6-1.fc42

Die „Provides“ dieses Pakets sind sehr einfach. Es stellt lediglich seinen eigenen Namen in allgemeiner und architekturspezifischer Form bereit.

Installieren

Zur abschließenden Überprüfung kann das Paket installiert und ausgeführt werden:

$ sudo dnf -C -y install ./results_banner/1.3.6/1.fc42/banner-1.3.6-1.fc42.x86_64.rpm
$ banner success

 #####   #     #   #####    #####   #######   #####    #####
#     #  #     #  #     #  #     #  #        #     #  #     #
#        #     #  #        #        #        #        #
 #####   #     #  #        #        #####     #####    #####
      #  #     #  #        #        #              #        #
#     #  #     #  #     #  #     #  #        #     #  #     #
 #####    #####    #####    #####   #######   #####    ##### ..

Um Ihr System zu bereinigen, machen Sie die Installation rückgängig:

$ sudo dnf -C -y history undo last

Bau des Pakets in der Fedora-Infrastruktur

Obwohl das Paket noch nicht Teil der Fedora-Distribution ist, kann ein Scratch-Build durchgeführt werden, um sicherzustellen, dass das Paket im Koji-Bausystem von Fedora erfolgreich erstellt wird und für alle von Fedora unterstützten Architekturen lauffähig ist. Dieser Bauvorgang wird gestartet, indem ein Source-RPM-Paket an fedpkg scratch-build übergeben wird.

Beachten Sie, dass Koji Kerberos zur Authentifizierung verwendet. Weitere Informationen finden Sie unter Kerberos-Ticket anfordern.

$ fedpkg --release f42 scratch-build --srpm results_banner/1.3.6/1.fc42/banner-1.3.6-1.fc42.src.rpm
Building banner-1.3.6-1.fc42.src.rpm for f42-candidate
Created task: 92465688
Task info: https://koji.fedoraproject.org/koji/taskinfo?taskID=92465688
Watching tasks (this may be safely interrupted)...

Sie können den Link zu den Aufgabeninformationen in einem Browser öffnen, um den Baufortschritt, die Protokolle und die Ergebnisse anzuzeigen. Das Befehlszeilenprogramm meldet den Fortschritt ebenfalls in Echtzeit. Eine erfolgreiche Ausführung sieht etwa so aus:

92465688 build (f42-candidate, banner-1.3.6-1.fc42.src.rpm): free
92465688 build (f42-candidate, banner-1.3.6-1.fc42.src.rpm): free -> open (buildvm-ppc64le-25.iad2.fedoraproject.org)
  92465698 rebuildSRPM (noarch): open (buildvm-s390x-24.s390.fedoraproject.org)
  92465745 buildArch (banner-1.3.6-1.fc42.src.rpm, x86_64): free
  92465748 buildArch (banner-1.3.6-1.fc42.src.rpm, s390x): open (buildvm-s390x-19.s390.fedoraproject.org)
  92465746 buildArch (banner-1.3.6-1.fc42.src.rpm, aarch64): open (buildvm-a64-26.iad2.fedoraproject.org)
  92465747 buildArch (banner-1.3.6-1.fc42.src.rpm, ppc64le): open (buildvm-ppc64le-11.iad2.fedoraproject.org)
  92465744 buildArch (banner-1.3.6-1.fc42.src.rpm, i686): open (buildhw-x86-12.iad2.fedoraproject.org)
  92465698 rebuildSRPM (noarch): open (buildvm-s390x-24.s390.fedoraproject.org) -> closed
  1 free  5 open  1 done  0 failed
  92465745 buildArch (banner-1.3.6-1.fc42.src.rpm, x86_64): free -> open (buildhw-x86-06.iad2.fedoraproject.org)
  92465745 buildArch (banner-1.3.6-1.fc42.src.rpm, x86_64): open (buildhw-x86-06.iad2.fedoraproject.org) -> closed
  0 free  5 open  2 done  0 failed
  92465748 buildArch (banner-1.3.6-1.fc42.src.rpm, s390x): open (buildvm-s390x-19.s390.fedoraproject.org) -> closed
  0 free  4 open  3 done  0 failed
  92465746 buildArch (banner-1.3.6-1.fc42.src.rpm, aarch64): open (buildvm-a64-26.iad2.fedoraproject.org) -> closed
  0 free  3 open  4 done  0 failed
  92465744 buildArch (banner-1.3.6-1.fc42.src.rpm, i686): open (buildhw-x86-12.iad2.fedoraproject.org) -> closed
  0 free  2 open  5 done  0 failed
92465688 build (f42-candidate, banner-1.3.6-1.fc42.src.rpm): open (buildvm-ppc64le-25.iad2.fedoraproject.org) -> closed
  0 free  1 open  6 done  0 failed
  92465747 buildArch (banner-1.3.6-1.fc42.src.rpm, ppc64le): open (buildvm-ppc64le-11.iad2.fedoraproject.org) -> closed
  0 free  0 open  7 done  0 failed

92465688 build (f42-candidate, banner-1.3.6-1.fc42.src.rpm) completed successfully