Referenzieren der Quellen
Eines der Designziele von RPM ist die saubere Trennung des Quellcodes von herstellerspezifischen Anpassungen. Für den Fedora-Paketierer bedeutet dies, dass die zum Erstellen eines Pakets verwendeten Quellen die unveränderten, vom Hersteller bereitgestellten Quellen sein sollten. Um dies für Prüfer und QA-Skripte zu erleichtern, muss der Paketierer angeben, wo der zur Erstellung des RPM-Pakets verwendete Quellcode zu finden ist.
Am häufigsten ist der Fall, dass der Quellcode vom Anbieter als tar.gz-, tar.bz2- oder zip-Archiv bereitgestellt wird, das wir von der Website des Anbieters herunterladen können. In diesen Fällen muss in der Zeile Source: die vollständige URL des Pakets angegeben werden. Zum Beispiel:
Source: https://downloads.sourceforge.net/%{name}/%{name}-%{version}.tar.gz
Source: https://ftp.gnome.org/pub/GNOME/sources/gnome-common/2.12/gnome-common-2.12.0.tar.bz2
|
Kleinstes komprimiertes Archiv
Wenn das Quellarchiv in mehreren komprimierten Formaten verfügbar ist, die unsere Werkzeuge dekomprimieren können, empfiehlt es sich, das kleinste Format zu verwenden. Dadurch wird sichergestellt, dass die Source-RPM-Datei möglichst klein ist und somit Speicherplatz auf den Spiegelservern und beim Herunterladen der Source-RPM-Pakete gespart wird. |
Forges verwenden (gehostete Revisionsverwaltung)
Jede Software-Veröffentlichungswebsite, die das Herunterladen von Quellarchiven über normalisierte URLs ermöglicht, welche sich aus der Projekt-Root-URL sowie Versions-, Commit-, Tag-, SCM- und Erweiterungsinformationen ableiten lassen, ist eine „Forge“, die vom redhat-rpm-config-Makro %{forgemeta} unterstützt wird. Gängige Forge-Beispiele sind GitLab und GitHub. %{forgemeta} zentralisiert und abstrahiert unser Wissen über diese Forges, so dass Paketierer Download-Besonderheiten nicht manuell behandeln müssen.
%{forgemeta} vereinfacht den Wechsel zwischen Release-, Tag- und Commit-Quellcodearchiven. Mit %{forgemeta} werden Forge-Download-URLs oder Richtlinienänderungen ohne manuelle Refaktorisierung in die Spec-Dateien übernommen.
Wenn diese Änderungen zu einer anderen Benennung oder Struktur des Quellarchivs führen, muss die Quelldatei vor dem Neuerstellen bestehender Spec-Dateien in das Bausystem hochgeladen werden. Dies ist der Hauptnachteil der Verwendung von %{forgemeta}.
Die folgenden Beispiele zeigen, wie man die Forge-Makros in verschiedenen Situationen einsetzt.
Release-Beispiel
# This template shows how to package a commit state using the forgemeta macro.
# That should be the default target use case.
# Other less common use cases are documented in separate templates.
#
# The project url on the forge, for example
# https://gitlab.gnome.org/GNOME/gtk/
%global forgeurl
#
# Packaging a release requires setting Version before calling forgemeta.
# Because most forges follow the git model, and git made no provision for
# release objects, forgemeta will try to guess the customary way to write
# release tags on the selected forge.
# If it guesses wrong use the forge-tag template instead of this one.
Version:
#
# forgemeta converts the suppplied rpm variables to variables that can be used
# in the spec file. Most of those can be overriden before or after the
# forgemeta call.
# – use the “-i” flag to display the variables forgemeta reads and sets
# – use the “-v” flag if you want verbose processing
# – remove “-i” and “-v” before commit
%forgemeta
# The following lines use variables computed by forgemeta as default values.
# You can replace them with manual definitions. For example, replace forgeurl
# with the project homepage if it exists separately from the repository URL.
# Only replace the variables when it adds value to the spec file and you
# understand the consequences. Release ordering is controlled by the packager
# with x%{?dist}/0.x%{?dist} number chains.
Name:
Release: 1%{?dist}
Summary:
URL: %{forgeurl}
Source: %{forgesource}
%description
%prep
# forgesetup calls setup with the correct flags for archives downloaded from
# the selected forge. A forgeautosetup autosetup wrapper is also provided. If
# you disagree with the computed setup/autosetup flags, just call
# setup/autosetup directly.
# – use the “-v” flag if you want verbose processing
%forgesetup
#
# After this point the archive extraction is done. forgemeta is no longer used.
%build
%install
%check
%files
%license
%doc
%changelog
Tag-Beispiel
# This template shows how to package a tag state using the forgemeta macro.
# For more explanations on forgemeta, read the forgemeta-release template.
#
# The project url on the forge
%global forgeurl
#
# The tag being packaged
%global tag
#
# – use the “-i” flag to display the variables forgemeta reads and sets
# – use the “-v” flag if you want verbose processing
# – remove “-i” and “-v” before commit
%forgemeta
# The following lines use variables computed by forgemeta as default values.
# You can replace them with manual definitions.
# forgemeta will prepend tag information to dist. Release ordering is
# controlled by the packager with x%{?dist}/0.x%{?dist} numbers chains.
Name:
Version:
Release: 1%{?dist}
Summary:
URL: %{forgeurl}
Source: %{forgesource}
%description
%prep
# – an autosetup wrapper, forgeautosetup, is also provided
# – use the “-v” flag if you want verbose processing; remove it before commit
# – call forgesetup/autosetup directly if you do not like the result
%forgesetup
#
# After this point the archive extraction is done. forgemeta is no longer used.
%build
%install
%check
%files
%license
%doc
%changelog
Commit-Beispiel
# This template shows how to package a commit state using the forgemeta macro.
# For more explanations on forgemeta, read the forgemeta-release template.
#
# The project url on the forge
%global forgeurl
#
# The commit being packaged (when using git, a full hash)
%global commit
#
# – use the “-i” flag to display the variables forgemeta reads and sets
# – use the “-v” flag if you want verbose processing
# – remove “-i” and “-v” before commit
%forgemeta
# The following lines use variables computed by forgemeta as default values.
# You can replace them with manual definitions.
# forgemeta will prepend commit information to dist. Release ordering is
# controlled by the packager with x%{?dist}/0.x%{?dist} numbers chains.
Name:
Version:
Release: 1%{?dist}
Summary:
URL: %{forgeurl}
Source: %{forgesource}
%description
%prep
# – an autosetup wrapper, forgeautosetup, is also provided
# – use the “-v” flag if you want verbose processing; remove it before commit
# – call forgesetup/autosetup directly if you do not like the result
%forgesetup
#
# After this point the archive extraction is done. forgemeta is no longer used.
%build
%install
%check
%files
%license
%doc
%changelog
Branch-Beispiel
# This template shows how to package a branch state using the forgemeta macro.
#
# BRANCH STATES ARE NOT REPRODUCIBLE AND SHOULD NEVER BE SHARED WITH OTHERS.
#
# For more explanations on forgemeta, read the forgemeta-release template.
#
# The project url on the forge
%global forgeurl
#
# The branch being packaged
%global branch
#
# – use the “-i” flag to display the variables forgemeta reads and sets
# – use the “-v” flag if you want verbose processing
# – remove “-i” and “-v” before commit
%forgemeta
# The following lines use variables computed by forgemeta as default values.
# You can replace them with manual definitions.
# forgemeta will prepend branch information to dist. Release ordering is
# controlled by the packager with x%{?dist}/0.x%{?dist} number chains.
Name:
Version:
Release: 1%{?dist}
Summary:
URL: %{forgeurl}
Source: %{forgesource}
%description
%prep
# – an autosetup wrapper, forgeautosetup, is also provided
# – use the “-v” flag if you want verbose processing; remove it before commit
# – call forgesetup/autosetup directly if you do not like the result
%forgesetup
#
# After this point the archive extraction is done. forgemeta is no longer used.
%build
%install
%check
%files
%license
%doc
%changelog
Beispiel für mehrere Quellen
# This template shows how to package multiple source archives using the
# forgemeta macro.
#
# PACKAGING MULTIPLE PROJECT ARCHIVES IN A SINGLE SPEC IS DISCOURAGED. IT OFTEN
# REQUIRES ERROR-INDUCING VERSIONNING DECISIONS. In rpm, versioning is not an
# administrative decoration. Versioning controls the upgrade logic. If upstream
# deemed necessary to release a project through multiple archives, mirror its
# decision using multiple spec files. That will be safer, simpler, and
# ultimately less work.
#
# For more explanations on forgemeta, read the forgemeta-release template.
#
# Start by declaring the characteristics of each source using a number-suffixed
# variable block:
# – no suffix and zero suffix blocks are aliases
# – they are “special” and identify the main source archive
# — they use Version: to identify a release
# – other blocks use a version<number> variable for the same need
# – the syntax is otherwise identical to single archive mode; see the various
# forge templates for examples.
#
# Main archive. In this example we package a full release
%global forgeurl0
Version:
# Second archive.
%global forgeurl1
%global version1
# Third archive. This time a tag. Continue as necessary.
%global forgeurl2
%global tag2
# – use the “-a” flag to process all the source archives in a single pass
# – use “-z <number>” to process only the declaration block suffixed with
# <number>
# — without “-a” of “-z <number>” only the main archive is processed
# – use the “-i” flag to display the variables forgemeta reads and sets
# – use the “-v” flag if you want verbose processing
# – remove “-i” and “-v” before commit
%forgemeta -a
# The following lines use variables computed by forgemeta as default values.
# You can replace them with manual definitions.
# Release ordering is controlled by the packager with x%{?dist}/0.x%{?dist}
# numbers chains.
Name:
Release: 1%{?dist}
Summary:
URL: %{forgeurl0}
# https://github.com/rpm-software-management/rpm/issues/539
Source0: %{forgesource0}
Source1: %{forgesource1}
Source2: %{forgesource2}
%description
%prep
# – use the “-a” flag to process all the source archives in a single pass
# – use “-z <number>” to process only the declaration block suffixed with
# <number>
# — without “-a” of “-z <number>” only the main archive is processed
# – an autosetup wrapper, forgeautosetup, is also provided
# – forgeautosetup does not understand “-a”
# – use the “-v” flag if you want verbose processing; remove it before commit
# – call forgesetup/autosetup directly if you do not like the result
%forgesetup -a
#
# After this point the archive extraction is done. forgemeta is no longer used.
%build
%install
%check
%files
%license
%doc
%changelog
Versionsverwaltung verwenden
In manchen Fällen kann es sinnvoll sein, die Quelltexte aus dem Versionsverwaltungssystem des Upstream-Projekts zu beziehen, da seit der letzten Veröffentlichung viele Änderungen vorgenommen wurden und ein daraus erstellter Tarball die Beziehung des Pakets zur Upstream-Entwicklung genauer darstellt. So können Sie mithilfe eines Kommentars die Herkunft der Quelle angeben:
# The source for this package was pulled from upstream's vcs. Use the # following commands to generate the tarball: # svn export -r 250 https://www.example.com/svn/foo/trunk foo-20070221 # tar -cJvf foo-20070221.tar.xz foo-20070221 Source: foo-20070221.tar.xz
Beim Abrufen von Versionen aus einer Versionsverwaltung denken Sie bitte daran, ein Namens-Versions-Release-Format zu verwenden, das zu den Richtlinien für die Versionsverwaltung kompatibel ist. Beachten Sie insbesondere den Abschnitt zu komplexer Versionsverwaltung.
Wenn das Upstream-Projekt verbotenen Code verwendet
Manche Upstream-Pakete enthalten Patente oder Marken, die wir selbst nicht als Quellcode ausliefern dürfen. In diesen Fällen müssen Sie das Quellcode-Archiv bearbeiten und diesen Code entfernen, bevor Sie es in das Bausystem hochladen. Hier ist ein Beispiel für die Verwendung eines Skripts, um zu dokumentieren, wie Sie vom Upstream-Archiv zum im Paket enthaltenen Archiv gelangt sind:
Aus der Spec-Datei:
Source: libfoo-1.0-nopatents.tar.gz # libfoo contains patented code that we cannot ship. Therefore we use # this script to remove the patented code before shipping it. # Download the upstream tarball and invoke this script while in the # tarball's directory: # ./generate-tarball.sh 1.0 Source1: generate-tarball.sh
generate-tarball.sh:
#!/bin/sh VERSION=$1 tar -xzvf libfoo-$VERSION.tar.gz rm libfoo-$VERSION/src/patentedcodec.c sed -i -e 's/patentedcodec.c//' libfoo-$VERSION/src/Makefile tar -czvf libfoo-$VERSION-nopatents.tar.gz libfoo-$VERSION
Python-Pakete (pypi)
Da PyPI Dateien nun in Verzeichnissen speichert, deren Pfad je nach Dateityp variiert, ist die Verwendung in einer Source:-URL unpraktisch. Stattdessen kann files.pythonhosted.org über das Makro %{pypi_source} gefolgt vom Projektnamen verwendet werden.
Source: %{pypi_source foo}
Mehr Informationen zum Makro finden Sie in den Python-Richtlinien.
Sourceforge.net
Für auf SourceForge gehostete Pakete verwenden Sie
Source: https://downloads.sourceforge.net/%{name}/%{name}-%{version}.tar.gz
Ändern Sie .tar.gz in die entsprechende Endung der Datei der Upstream-Distribution. Beachten Sie, dass wir downloads.sourceforge.net anstelle eines beliebigen Mirrors verwenden. Sie können selbstverständlich auch den Paketnamen und die Paketversion anstelle der Makros %{name} und %{version} verwenden.
Bitte beachten Sie, dass die korrekte URL downloads.sourceforge.net lautet und NICHT download.sourceforge.net.
Git-Hosting-Dienste
Falls das Upstream-Projekt Tarballs erstellt, sollten Sie diese verwenden, da Tarballs eine einfachere Nachverfolgung für diejenigen bieten, die die Pakete prüfen.
Webbasierte Git-Hosting-Dienste bieten die Möglichkeit, bei Bedarf Tarballs zu erstellen, entweder aus einer bestimmten Commit-Revision oder aus einem bestimmten Tag. Falls das Upstream-Projekt keine Tarballs für Releases erstellt, können Sie diesen Mechanismus nutzen, um sie zu generieren.
Der vollständige 40-stellige Hash und das zugehörige Git-Tag können durch Ausführen des folgenden Git-Befehls abgerufen werden:
git ls-remote https://HOSTINGDIENST/EIGENTÜMER/%{name}.git
HOSTINGDIENST: Name des Dienstes, d.h. „github.com“, „bitbucket.org“, „gitlab.com“ usw.
EIGENTÜMER: Benutzername des Eigentümers des Repositorys
PROJEKT: Name des Upstream-Projekts (falls dieser identisch zum Paketnamen ist, verwenden Sie %{name})
Sie können den 40-stelligen Hash und das zugehörige Git-Tag auch über die Weboberfläche des HOSTINGDIENSTES abrufen oder indem Sie das Repository klonen und den Befehl git show-ref ausführen.
Sobald der Commit-Hash und der Git-Tag bekannt sind, können Sie diese in Ihrer Spec-Datei wie folgt definieren:
%global commit 40-CHARACTER-HASH-VALUE
%global gittag GIT-TAG
%global shortcommit %(c=%{commit}; echo ${c:0:7}) [GitHub]
%global shortcommit %(c=%{commit}; echo ${c:0:11}) [Bitbucket]
%global shortcommit %(c=%{commit}; echo ${c:0:7}) [GitLab]
%global shortcommit %(c=%{commit}; echo ${c:0:8}) [Sourcehut]
Commit-Revision
Für den Quellcode-Tarball können Sie die folgende Syntax verwenden:
Source: https://github.com/OWNER/PROJECT/archive/%{commit}/%{name}-%{shortcommit}.tar.gz [GitHub]
Source: https://bitbucket.org/OWNER/PROJECT/get/%{commit}.tar.gz#/%{name}-%{shortcommit}.tar.gz [BitBucket]
Source: https://gitlab.com/OWNER/PROJECT/-/archive/%{commit}/%{name}-%{shortcommit}.tar.gz [GitLab]
Source: https://git.sr.ht/~OWNER/PROJECT/archive/%{shortcommit}.tar.gz#/PROJECT-%{shortcommit}.tar.gz [Sourcehut]
...
%prep
%autosetup -n PROJECT-%{commit} [GitHub]
%autosetup -n OWNER-PROJECT-%{shortcommit} [BitBucket]
%autosetup -n PROJECT-%{commit} [GitLab]
%autosetup -n PROJECT-%{shortcommit} [Sourcehut]
Wenn die Version einem Git-Tag mit einer sinnvollen numerischen Versionsnummer entspricht, müssen Sie diese Version verwenden, um den Version:-Tag in der Spec-Datei zu füllen. Andernfalls prüfen Sie den Quellcode, ob dort eine Versionsnummer angegeben ist, und verwenden Sie diesen Wert. Falls im Code keine numerische Versionsnummer angegeben ist, können Sie Version auf 0 setzen und das Paket als Vorabversion behandeln (und das Makro %{shortcommit} verwenden). Weitere Informationen finden Sie unter Vorabversionen.
Alternativ müssen Sie, wenn Sie eine bestimmte Revision verwenden, sei es eine Vorab- oder eine Nachveröffentlichungsversion, die „Snapshot“-Richtlinien befolgen. Diese sind hier dokumentiert. Sie können in diesem Abschnitt %{checkout} durch %{shortcommit} für den Git-Hash ersetzen.
Git-Tags
Git-Tags repräsentieren einen bestimmten Codepunkt, der vom Upstream-Projekt als wichtig erachtet wird. Sie werden typischerweise verwendet, um Release-Punkte zu markieren.
Bitbucket verwendet den Bezeichner %{shortcommit} als Teil der Archivverzeichnisstruktur, unabhängig davon, ob Sie ihn über Git-Tags oder Commit-Revisionen abrufen. Dies wird im Beispiel im Abschnitt %prep veranschaulicht.
Für den Quellcode-Tarball können Sie die folgende Syntax verwenden:
Source: https://github.com/OWNER/PROJECT/archive/%{gittag}/%{name}-%{version}.tar.gz [GitHub]
Source: https://bitbucket.org/OWNER/PROJECT/get/%{gittag}.tar.gz#/%{name}-%{version}.tar.gz [BitBucket]
Source: https://gitlab.com/OWNER/PROJECT/-/archive/%{gittag}/%{name}-%{version}.tar.gz [GitLab]
Source: https://git.sr.ht/~OWNER/PROJECT/archive/%{version}.tar.gz#/PROJECT-%{version}.tar.gz [Sourcehut]
...
%prep
%autosetup -n PROJECT-%{gittag} [GitHub]
%autosetup -n OWNER-PROJECT-%{shortcommit} [BitBucket]
%autosetup -n PROJECT-%{version} [GitLab]
%autosetup -n PROJECT-%{version} [Sourcehut]
Verwendung von %{version}
Die Verwendung von %{version} in Source: erleichtert das Erhöhen der Version eines Pakets, da Sie in den meisten Fällen Source: nicht bearbeiten müssen, wenn Sie die Spec-Datei für das neue Paket bearbeiten.
Problematische URLs
Wenn die Download-URLs des Upstream-Projekts nicht mit dem Namen des Tarballs enden, kann rpm den Tarball nicht aus der Quell-URL extrahieren. Eine mögliche Ausweichlösung für viele Fälle ist die Erstellung einer URL, in der der Tarball in einem „URL-Fragment“ aufgeführt ist:
Source: https://example.com/foo/1.0/download.cgi#/%{name}-%{version}.tar.gz
rpm verwendet dann %{name}-%{version}.tar.gz als Namen für den Tarball. Wenn Sie spectool -g foo.spec zum Herunterladen des Tarballs verwenden, wird dieser automatisch umbenannt.
Manchmal funktioniert dies nicht, weil das Upstream-CGI versucht, das Fragment zu parsen, oder weil Sie sich anmelden oder ein Formular ausfüllen müssen, um auf den Tarball zuzugreifen. In diesen Fällen müssen Sie lediglich den Dateinamen des Tarballs in den Source:-Tag einfügen. Um klarzustellen, woher Sie den Tarball haben, sollten Sie oberhalb der Source:-Zeile Kommentare hinzufügen, um die Situation für Reviewer und zukünftige Paketierer zu erläutern. Zum Beispiel:
# Mysql has a mirror redirector for its downloads # You can get this tarball by following a link from: # https://dev.mysql.com/downloads/mysql/5.1.html Source: mysql-5.1.31.tar.gz
Kein bedingter „Source:“-Tag
Beim Erstellen eines SRPM ist es entscheidend, dass alle Quellen vorhanden sind, unabhängig von der Plattform, auf der das SRPM generiert wird. Beispielsweise funktioniert der folgende Code nicht (wie man vielleicht erwarten würde):
%if 0%{?fedora} < 35
Source1: mysource-old.tar.bz2
Patch1: oldpatch.patch
%else
Source1: mysource-ng.tar.bz2
Patch1: ngpatch.patch
%endif
Wenn Sie dieses SRPM-Paket von einem Fedora-34-Host aus erstellen (rpmbuild -bs mysource.spec), enthält das resultierende SRPM-Paket die Dateien mysource-old.tar.bz2 und oldpatch.patch. Wenn Sie dieses SRPM-Paket anschließend für Fedora 35 verwenden, schlägt der Vorgang fehl, da die Datei mysource-ng.tar.bz2 nicht verfügbar ist.
Das korrekte Vorgehen besteht darin, stets alle potenziell im Bauvorgang verwendeten Quellen mitzuführen und deren Verwendung anschließend bedingt zu steuern. Zum Beispiel:
Patch1: oldpatch.patch Patch2: ngpatch.patch ... %prep %autosetup -N ... %if 0%{?fedora} < 35 tar xf %{SOURCE1} %patch 1 -p1 %else tar xf %{SOURCE2} %patch 2 -p1 %endif ```
Want to help? Learn how to contribute to Fedora Docs ›