openSUSE:Richtlinien für Spezifikationsdateien

(Weitergeleitet von openSUSE:Specfile guidelines)
Wechseln zu: Navigation, Suche
RPM hat sehr wenige Einschränkungen bezüglich Spezifikationsdateien. Sie können diese sehr komplex gestalten. Diese Richtlinien versuchen die Variationen in speziellen Bereichen zu minimieren, so dass die Spezifikationsdateien einfach zu warten sind.

Grundsätzliche Regeln

Alle Spezifikationsdateien müssen lesbar sein. Wenn andere Paketbauer diese nicht lesen können, wird es unmöglich eine Durchsicht auszuführen und an dem Paket mitzuwirken.


Spezifikationsdatei-Vorlage

Wenn Sie ein Paket von Grund auf neu schreiben, sollten Sie Ihre Spezifikationsdatei auf der Vorlage für RPM-Entwicklungswerkzeuge aufbauen. Die grundlegende Einrichtung für ein Paket MEINPAKET kann mit

 osc install Entwicklung:Werkzeuge rpmdevtools

oder

 sudo zypper -p http://download.opensuse.org/repositories/devel:/tools/openSUSE_12.1 -v in osc rpmdevtools

erzeugt werden.

 cd .../MEINPROJEKT
 osc mkpac MEINPAKET
 cd MEINPAKET
 wget http://upstream.example.org/source/.../MEINPAKET-1.0.tar.gz
 rpmdev-newspec -t lib MEINPAKET
 osc vc
 vi MEINPAKET.spec
 # danach: osc build
 #         osc ci
 #         osc in


Bitte legen Sie Ihre Vorlieben über die Formatierung und die Organisation von Spezifikationsdateien beiseite und versuchen Sie dieser Vorlage so gut wie möglich zu folgen. Das ist nicht weil wir glauben, das ist der einzig richtige Weg, eine Spezifikationsdatei zu schreiben, sondern weil für OA es oft leichter ist, Fehler zu erkennen und schneller zu verstehen ist, was Sie zu tun versuchen.

Spezifikationsdateien für spezielle Sprachen können oft mit speziellen Werkzeugen wie cpanspec or gem2rpm-opensuse erstellt werden. Weitere Informationen finden Sie hier:

Kodierung der Spezifikationsdatei

Außer, wenn Sie Zeichen außerhalb der ASCII Zeichenmenge benötigen, brauchen Sie sich keine Gedanken über die Kodierung der Spezifikationsdatei zu machen. Wenn Sie Nicht-ASCII-Zeichen benötigen, sichern Sie Ihre Spezifikationsdateien im Format UTF-8. Wenn Sie Zweifel haben, ob Ihre Zeichen ASCII sind, sehen Sie bitte hier nach an ASCII Zeichen.

Lizenzierung von Spezifikationsdateien

Aus rechtlichen Gründen müssen Spezifikationsdateien einen Lizenzbeschreibung am Anfang haben. Beachte, dass der OBS wird standardmäßig eine Lizenzbeschreibung am Anfang der Spezifikationsdatei hinzufügen, wenn Sie das vergessen sollten. Das könnte natürlich sein, dass das nicht das ist, was Sie wollen. Sie könnten dann die folgende Vorlage verwenden:

 #
 # Spezifikationsdatei für Paket python-$FOO
 #
 # Copyright (c) $LAUFENDES_JAHR $IHR_NAME_MIT_MAILADRESSE
 #
 # Alle Modifikationen und Ergänzungen zu der Datei, 
 # die von dritter Seite beigetragen werden, bleiben das Eigentum
 # des Eigentümers des Urheberrechts, außer es wird etwas anderes vereinbart. 
 # Die Lizenz für diese Datei, sowie Modifikationen und Ergänzungen
 # zu dieser Datei ist die gleiche wie für das ursprüngliche Paket 
 # (außer die Lizenz für das ursprüngliche Paket ist 
 # keine Open Souce Lizenz, in dem Fall gilt 
 # die MIT-Lizenz).
 # Eine "Open Source Lizenz" ist eine Lizenz, die mit der 
 # Open Source Definition) übereinstimmt und
 # von der Open Source Initiative veröffentlicht wird.
 # Bitte reichen Sie Fehlerbereinigungen oder Kommentare   
 # via http://bugs.opensuse.org/ ein.
 #

Makros

Verwenden Sie Makros anstelle von fest programmierten Verzeichnis-Bezeichnungen (siehe Paketbauvereinbarungen zu RPM-Makros). Makros in einer Source: oder Patch: -Zeile zu haben, ist eine Sache des Stils. Manche Leute erfreuen sich an einer fertig lesbaren Quellzeile ohne Makros. Andere bevorzugen die Leichtigkeit der Aktualisierung neuer Versionen, wenn Makros verwendet werden. In allen Fällen denken Sie daran, in Ihrer Spezifikationsdatei konsequent zu sein und überprüfen Sie, dass die URLs, die Sie aufführen, gültig sind. Wenn Sie die aktuelle Zeichenkette bestimmen müssen, wenn sie Makros enthalten, können Sie rpm verwenden. Zum Beispiel, um den wirklichen Source:-Wert zu bestimmen, können sie folgendes eingeben:

rpm -q --specfile foo.spec --qf "$(grep -i ^Source foo.spec)\n"

Vorsicht: Das obige Kommando funktioniert mit %name und %version, könnte aber fehl schlagen mit Benutzer definierten Makros.

Makros im Vergleich mit RPM Variablen

Es gibt zwei Stilarten, die Build Root und Optimization Flags in einer Spezifikationsdatei zu definieren.

Makro Stil Variablen Stil
Build Root  %buildroot $RPM_BUILD_ROOT
Opt. Flags  %optflags $RPM_OPT_FLAGS

Es hat nur einen geringen Nutzen, den einen oder den anderen Stil zu wählen, da sie die gleichen Werte in allen Szenarios auflösen. Sie sollten einen Stil auswählen und ihn ständig während Ihrer Packarbeit verwenden. Das Mischen von zwei Stilarten, weil sie verfügbar sind, ist schlecht aus der Sicht eines OA und der Benutzerfreundlichkeit und sollte in openSUSE Paketen nicht gemacht werden.

RPM-Makros werden, bevor das Shellskript, das es enthält, gestartet wird, erweitert. Da sh notorisch langsam ist, scheint es, dass der %-style bevorzugt werden sollte, ebenso weil man bereits Makros wie %_bindir benutzt, die kein variables Äquivalent haben.

Bedingungen

Wenn eine Spezifikationsdatei bedingte Abhängigkeiten enthält, die basierend auf der Anwesenheit von optionalen --mit(ohne) foo Argumenten für rpmbuild ausgewählt werden, bauen Sie das Quell-RPM, damit es mit Standard-Optionen eingereicht wird, z. B. so dass keines dieser Argumente in der rpmbuild Kommandozeile vorhanden ist. Der Grund ist, dass diese Forderungen in das resultierende Quell-RPM "angeordnet" wird, z.B. die Bedingungen nicht länger gelten.

Vorwort

Das sind Regeln für das Vorwort einer Spezifikationsdatei.

Bezeichnung / Versionsangaben

Siehe Richtlinien zur Bezeichnung von Paketen.

Metadaten-Markierungen (Metadata Tags)

  • Die Paketbauer-Markierung darf in Spezifikationsdateien nicht verwendet werden. Der Umbau der RPM-Paketes irgendwo zwingt diesen Paketbauer-Wert zur dritten Person und führt zu Verwirrungen darüber, wer zu kontaktieren ist. Die Identitäten der Paketbauer sollten stattdessen mit Changelog-Einträgen spezifiziert werden.
  • Die Verkäufer-Markierung darf aus dem gleichen Grund nicht verwendet werden. Im Build-Service ist er automatisch gesetzt. Wenn Sie ihn überschreiben wollen, verwenden Sie einen prjconf-level %define.
  • Die Copyright -Markierung ist veraltet. Verwenden Sie bitte stattdessen die Lizenz-Markierung, wie unter openSUSE:Paketbau Richtlinien#Lizenzierung detailliert dargestellt ist.
  • Die Quelle sollte ein vollständiger URL zum eingereichten Tar-Archiv haben. Wenn das Tar-Archiv manuell komprimiert wurde, ist das nicht anwendbar. Die Angabe eines Ortes für die Downloadseite in einem Kommentar ist sehr willkommen.
  • Die Gruppen-Markierung sollte nur Paketgruppen enthalten, die den openSUSE:Package group guidelines folgen.
  • Die BuildRoot -Markierung sollte immer benutzt werden, auch wenn neuere RPMs diese überschreiben. Der bevorzugte Pfad ist %_tmppath/%name-%version-build.
  • Die AutoReqProv -Markierung ist standardmäßig an. So ist es unnötig, sie zu spezifizieren, wenn man nicht sie gerade ausschalten möchte.

Zusammenfassung

  • Sie sollte nicht mit einem Punkt enden. Wenn Sie das aus grammatikalischer Sicht stören sollte, setzen Sie sich, atmen tief ein und versuchen Sie darüber weg zu kommen.
  • Sie sollte eine kurze und prägnante Beschreibung des Paketes sein, mit einer maximalen Länge von 80 Zeichen.
  • Sie sollte alle Standardsituationen umfassen keine speziellen Zusammenhang beschreiben.
  • Sie sollte allein hilfreich sein, in alphabetisch sortierten und unsortierten Listen einiger ausgewählter Pakete und in alphabetisch sortierten und unsortierten Listen aller Pakete.
  • Sie sollte die Hauptfunktion des Paketes beschreiben und einige spezielle Eigenschaften des Paketes hervorheben, um den Anwender beim Vergleich ähnlicher Pakete zu unterstützen. Zum Beispiel, der Begriff "Webbrowser" umfasst alle Webbrowser. Aber die Verwendung zusätzlicher Adjektive (wie minimal, Text basiert oder schnell) helfen, ein spezielles Paket zu charakterisieren.

Beschreibung

Die Beschreibung ist gegenüber der Zusammenfassung umfassender. Beziehen Sie keine Installationsanleitungen in die Beschreibung ein. Sie ist keine Bedienungsanleitung. Wenn das Paket eine Konfigurationsanleitung benötigt oder es gibt andere wichtige Hinweise für den Benutzer führen Sie den Benutzer zur Dokumentation im Paket. Wenn Sie glauben, es ist notwendig, fügen Sie ein README.SUSE oder ähnliches ein. Stellen Sie bitte sicher, dass in der Beschreibung keine Zeilen mehr als 70 Zeichen besitzen. (Das ist verbunden mit der Größe des YaST Beschreibungsfensters im Ncurses-Modus.) Ebenso sollte die Beschreibung nicht mehr als 20 Zeilen umfassen.

Die Paketbeschreibung sollte dem Anwender bei der Entscheidung helfen, das geeignete Paket für seine Zwecke auszuwählen, ohne ähnliche Pakete vorher zu testen.Das ist der richtige Ort, den Nutzer mehr über die Funktionsweise des Paketes zu informieren. Es sollte weitere Informationen über die Funktionen und die Unterschiede zu anderen vergleichbaren Paketen enthalten. Wenn ein Paket die Installation eines Benutzers beeinträchtigen könnte, sollte die Beschreibung klare Notizen über seine möglichen Risiken oder Nebenwirkungen enthalten.

Bitte legen Sie persönliche Vorzüge beiseite und verwenden Sie amerikanisches Englisch in der Beschreibung. Die RPM-Spezifikationsdatei enthält nur die englische Version der Zusammenfassung und Beschreibung, um die RPM-Datenbasis klein zu halten. Die übrigen Sprachen werden von YaST gehandhabt.

Die Autorenliste am Ende der Beschreibung sollte nicht länger einbezogen werden (NB:seit Sommer 2011). Wir verwenden eine extra Datei AUTHORS. Wenn die Datei noch nicht Teil des neuen Paketes ist, sollten Sie es wie folgt erstellen:

Source2:        AUTHORS
...
%setup
cp %{S:2} .
...
%files
%doc AUTHORS

Markenzeichen in Zusammenfassung oder Beschreibung

Paketbauer sollten sorgfältig darin sein, wie sie Markenzeichen in Zusammenfassung oder Beschreibung verwenden. Es gibt einige regeln zu beachten:

  • Verwenden Sie niemals (TM)" oder "(R)" (oder die Unikode-Entsprechungen ™/®). Das ist unwahrscheinlich kompliziert, diese richtig zu verwenden. So ist es momentan sicherer für uns, diese überhaupt nicht zu nutzen.
  • Verwenden Sie Markenzeichen in einer Weise, dass sie nicht mehrdeutig sind. Vermeiden sie Redewendungen wie "vergleichbar zu" oder "ähnlich". Einige Beispiele:
  • SCHLECHT: Es ist vergleichbar mit Adobe Photoshop.
  • GUT: Es unterstützt Adobe Photoshop PSD Dateien, ...
  • SCHLECHT: Eine Linux-Version von Microsoft Office
  • GUT: Ein Textverarbeitungsprogramm mit Unterstützung für Microsoft Office DOC-Dateien.

Wenn Sie sich nicht sicher sind, fragen Sie sich selbst, ob die Chance besteht, dass irgend jemand durcheinander gebracht wird und denkt: Ist dieses Paket eine Markenzeichensache? Wenn Sie Zweifel haben, lassen Sie das Markenzeichen weg.

Abhängigkeiten

Requires

RPM hat sehr gute Fähigkeiten zum automatischen auffinden von Abhängigkeiten für Bibliotheken und Perl-Module. Kurz, erfinden Sie das Rad nicht neu, sondern lassen Sie RPM seinen Job erledigen. Es gibt gewöhnlich keine Notwendigkeit explizit aufzulisten z. B. Requires: libqt4, wenn die Abhängigkeiten bereits von RPM eingesammelt wurden, in der Form: abhängig von gemeinsam benutzten Bibliotheken im Paket libqt4.

Wenn das Paket sich in Unter-Pakete aufteilt, könnten diese das Grundpaket in der versionierten Abhängigkeit benötigen: Requires: %name = %version.

-devel Unter-Pakete müssen explizit von Paketen mit den gemeinsam genutzten Paketen abhängen, so dass die devel-Pakete einen symbolischen Link haben, z.B. libfoobar-devel benötigt Requires: libfoo2 = %version, libbar5 = %version.

PreReq

Pakete sollten nicht die Markierung PreReq verwenden. Hin und wieder in Abhängigkeitsschleifen "gewann" gewöhnlich PreReq über das konventionelle Requires, wenn RPM die Installationsreihenfolge in Transaktionen bestimmte. Das ist nicht länger der Fall.

BuildRequires

Im Gegensatz zu Requires gibt es für BuildRequires keinen automatischen Prozess, um Abhängigkeiten zu finden. Sie müssen explizit die Pakete auflisten, die Ihr Paket benötigt, um erfolgreich zu bauen. Geeignete Bauanforderungen zu haben, spart die Zeit aller Entwickler und Tester, weil dann nicht nach fehlenden Bauanforderungen manuell suchen müssen. Es ist ebenso sicher zu stellen, dass der Bau reproduzierbar ist und immer die gleichen Funktionen verwendet. configure-Skripte, zum Beispiel, könnten PNG-Unterstützung ausschließen, in Abhängigkeit von der Verfügbarkeit von libpng im Bausystem. Mit BuildRequires: libpng-devel (oder seit openSUSE 11.4: BuildRequires: pkgconfig(libpng14), stellen Sie sicher, dass der Bau fehlschlägt, wenn libpng nicht vorhanden ist.

OBS Vorbehalt

BuildRequires sind bedingt auf einfache Variablen begrenzt. RPM unterstützt gewöhnlich komplexe Konstrukte wie die in einem %if Ausdruck:

%if 0%(test "%irgendetwas" = "enabled" && echo 1)

Aber wenn man BuildRequires beurteilt, läuft der RPM-Parser von BuildService in einer Umgebung, in der Subshellerweiterungen deaktiviert sind Sie werden Warnungen wie diese erhalten:

Warning: spec file parser line 109: can't expand %(...)

Das folgende Beispiel verwendet nur eine einfache Variable, die mit BuildRequires funktioniert:

%if ! 0%?have_own_mpfr
BuildRequires: mpfr-devel
%endif
Ausnahmen

Es gibt keine Notwendigkeit das folgende Paket oder ihre Abhängigkeiten als BuildRequires einzubeziehen, weil sie zu oft vorkommen würden. Diese Pakete werden als die minimale Bauumgebung angesehen.

Versuchen Sie dieses Kommando für eine Liste:

osc meta prjconf openSUSE:Factory | egrep '^(Preinstall:|Support:|Required:)'
Preinstall: aaa_base acl attr bash coreutils diffutils
Preinstall: filesystem fillup glibc grep insserv libacl libattr
Preinstall: libbz2-1 libgcc%{gcc_version} libxcrypt m4 libncurses5 pam
Preinstall: permissions libreadline6 rpm sed tar zlib libselinux1
Preinstall: liblzma5 libcap2 libpcre0
Preinstall: libpopt0 libelf1 liblua5_1
Required: gcc gcc%{gcc_version} glibc perl rpm tar patch
Support: autoconf automake binutils bzip2 gcc gcc%{gcc_version}
Support: gettext-runtime glibc libtool perl rpm zlib
Support: libncurses5
Support: libaudit1 cpio cpp cpp%{gcc_version} cracklib cvs
Support: file findutils gawk gdbm gettext-tools
Support: glibc-devel glibc-locale groff gzip info less
Support: libbz2-devel libdb-4_8
Support: libstdc++%{gcc_version}
Support: udev
Support: libxcrypt libzio
Support: linux-glibc-devel make man netcfg
Support: net-tools pam-modules patch perl-base sysvinit-tools
Support: texinfo timezone util-linux libmount1 login
Support: libgomp%{gcc_version} libuuid1 psmisc
Support: terminfo-base update-alternatives pwdutils build-mkbaselibs
Support: brp-check-suse post-build-checks rpmlint-Factory
Support: build-compare
Support: libunwind libunwind-devel

Konflikte

Wenn immer es möglich ist, sollten openSUSE Pakete Konflikte untereinander vermeiden. Unglücklicher Weise ist das nicht immer möglich. Detaillierte Informationen zu openSUSE Konfliktregeln finden Sie unter en:openSUSE:Packaging conflicts.

Datei-Abhängigkeiten

RPM gibt Ihnen die Möglichkeit der Abhängigkeit von Dateien anstatt von Paketen. Wenn immer es möglich ist, sollten Sie Datei-Abhängigkeiten außerhalb von /etc, /bin, /sbin, /usr/bin, oder /usr/sbin vermeiden. Die Verwendung von Dateiabhängigkeiten außerhalb dieser Verzeichnisse erfordert yum (und andere Löser von Abhängigkeiten, die das Format repomd verwenden) um eine große XML-Datei herunterzuladen und zu analysieren, um nach den Abhängigkeiten zu suchen. Um den Entwicklern zu helfen, vermeiden Sie bitte diesen Prozess, indem Sie die Abhängigkeiten von den Paketen anstelle von Dateien verwenden. Das spart unseren Endanwendern eine Menge Zeit. Es gibt Zeiten, in denen technische Gesichtspunkte diese aufwiegen. Ein einfaches Beispiel ist wenn Paketen in %_libdir/mozilla/plugins installieren. In diesem Fall behauptet ein spezieller Browser in Ihrem Paket, dieses Verzeichnis zu besitzen und könnte eine große Menge nutzloser Pakete herein ziehen. Das Verzeichnis aufzufordern, die Abhängigkeiten zu lösen, ist die bessere Wahl.

Patches

Alle Patches in openSUSE Spezifikationsdateien SOLLTEN einen Kommentar dazu über ihren Status haben. Detailinformationen finden Sie auf der Seite Paketbau Richtlinien für Patches.

Abschnitt Vorbereitung (%prep)

Dies sind die Regeln für den Abschnitt Vorbereitung der Spezifikationsdatei.

Quiet %setup

Sie sollten die Option -q an das Makro %setup</tt weiter geben. Das wird die Größe der Bau-Logdatei bedeutend reduzieren, speziell bei Quellarchiven mit einer Menge Dateien.

Abschnitt Bauen (%build)

Es gibt Regeln für den Bauabschnitt der Spezifikationsdatei.

Compiler Flags

Mit Compilern gebaute Pakete sollten den anwendbaren Compiler Flags, die in der Systemkonfiguration von RPM gesetzt sind, gerecht werden. Das bedeutet in der Praxis: <tt>%optflags (Variable: $RPM_OPT_FLAGS, siehe oben) für C, C++, und Fortran Compiler. Gerecht werden bedeutet, das der Inhalt dieser Variable, die als Basis der aktuellen Flags, die während des Paketbaus vom Compiler verwendet werden, verwendet werden. Wenn es einen guten Grund gibt, ist es erlaubt, Teile dieser Flags zu überschreiben, zu filtern oder hinzu zu fügen. Der Grund, warum das so gemacht wird, sollte überprüft und in der Spezifikationsdatei dokumentiert werden, speziell im Fall der Überschreibung und Filterung.

Paralleles make

Wenn immer es möglich ist, sollten Aufrufe von make als

make %{?_smp_mflags}

ausgeführt werden. Das beschleunigt grundsätzlich das Bauen, besonders auf SMP-Maschinen. Das gilt vorzugsweise für %{?jobs:-j%jobs}, die es erlauben, abwechselnde Make-Flags zu verwenden, wie make -lN und nicht fest programmierend -jN. Stellen Sie sicher, dass das Paket sauber auf diese Weise gebaut wird, da einige Make-Dateien kein paralleles Bauen unterstützen, oder Sie haben zerbrochene Abhängigkeiten.

Für den Fall, dass eine Quelle das parallele Bauen nicht unterstützt, kennzeichnen Sie das bitte in der Spezifikationsdatei, indem Sie einen Kommentar einbringen und eventuell -j1 verwenden, um das Finden solche Pakete zu erleichtern.

Abschnitt Installation (%install)

Es gibt Regeln für den Installationsabschnitt der Spezifikationsdatei.

Da rpmbuild als ein unprivilegierter Benutzer läuft, darf das Verwenden von `make install` keine Änderung der Benutzerrechte (chown) der Dateien versuchen (entweder Sie lassen chown direkt laufen oder unter Verwendung von zum Beispiel `install -o root...`). Die Eigentumsrechte von Dateien sollten stattdessen später im Abschnitt %files eingerichtet werden.

Es gibt zwei gleichnamige, und das ist verwirrend, Installations-Makros, die von RPM und SUSE's RPM-Makros unterstützt werden:


# Das make install Gegenstück von %configure für moderne Autotools:
%make_install make install DESTDIR=%{?buildroot}

#------------------------------------------------------------------------------
# Das frühere make install Gegenstück, behalten wegen der 
# Kompatibilität und für alte/zerbrochene
#  Pakete, die nicht ausreichend DESTDIR unterstützen.
%makeinstall \
  make \\\
        prefix=%{?buildroot:%{buildroot}}%{_prefix} \\\
        exec_prefix=%{?buildroot:%{buildroot}}%{_exec_prefix} \\\
[...]

SUSE's rpm, z.B. /usr/lib/rpm/suse_macros definiert beide zu praktisch der gleichen Sache um:

%make_install           make install DESTDIR=%{?buildroot}
%makeinstall            make DESTDIR=%{?buildroot:%{buildroot}} install

Deswegen sollte man wahrscheinlich nur %make_install verwenden.

Entfernung von buildroot

openSUSE markiert es als schlechten Kodierungsstil, wenn man rm -rf %{buildroot} oder rm -rf $RPM_BUILD_ROOT am Anfang eines %install -Abschnitts hat, wie hier:

  %install
  rm -rf $RPM_BUILD_ROOT
  mkdir -p $RPM_BUILD_ROOT/usr/...  or make install

Warum?

RPM_BUILD_ROOT befindet sich normalerweise innerhalb /var/tmp. Und Sie haben gerade eine einfache Wettlaufbedingung für einen örtlichen Angreifer auf Ihrer Maschine eröffnet, Ihr Benutzerkonto zu übernehmen (oder auch von Root, wenn Sie als Root bauen). Es ist besser, überhaupt nicht "rm -rf $RPM_BUILD_ROOT" in %install zu verwenden (und sich auf %clean zu verlassen, das zu machen).

Wenn Sie das bereinigen wollen, machen Sie besser folgendes:

  %install
  rm -rf $RPM_BUILD_ROOT
  mkdir $RPM_BUILD_ROOT
  mkdir -p $RPM_BUILD_ROOT/usr ... oder make install

In diesem Fall würde "mkdir $RPM_BUILD_ROOT" fehlschlagen und der Bau abbrechen, wenn ein Angreifer versucht, den buildroot durch seinen eigenen symbolischen Link zu ersetzen.

Bereinigungsabschnitt (%clean)

Der %clean Abschnitt, wenn spezifiziert, wird gestartet, wenn die Binär- und Quell-RPM's erzeugt wurden. Im Open Build Service ist dieser Abschnitt nicht notwendig, weil chroots und/oder VM-Umgebungen, die verwendet werden, um das Paket zu bauen, grundsätzlich sowieso heruntergerissen werden. Der Bau von Paketen in Umgebungen, die nicht ganz von vorn begonnen wurden, werden gewöhnlich nicht für openSUSE Pakete unterstützt (cf. bnc#176528 c4).

Seit rpm-4.7/openSUSE_11.3 führt rpm "%clean: rm -Rf %buildroot" standardmäßig aus, wenn der %clean-Abschnitt in der Spezifikationsdatei komplett abwesend ist.

In der fernen Vergangenheit prüften einige Pakete in %clean, dass %{buildroot} nicht / war, bevor es gelöscht wurde. Das ist in openSUSE nicht mehr notwendig.

Scriptlets (%post* / %pre*)

Es gibt Regeln für die Scriptlet-Abschnitte einer Spezifikationsdatei. Bei der Verwendung von Scriptlets sollte man große Sorgfalt walten lassen. Wenn Scriptlets verwendet werden, müssen diese vernünftig sein. Einige gebräuchliche Scriptlets sind unter openSUSE:Packaging scriptlet snippets dokumentiert.

Anforderungen an Scriptlets

Ihr Paket muss alles voraussetzen, was Sie in den Scriptlets verwenden. Die Schreibweise ist wie folgt:

Requires(pre): ...
Requires(post): ...

Scriplets nur in ein bestimmtes Verzeichnis schreiben

Bauscripte von Paketen (%prep, %build, %install, %check und %clean) dürfen Dateien nur verändern (erstellen, modifizieren, löschen) unter %buildroot, %_builddir und an gültigen zeitweisen Orten, wie /tmp, /var/tmp (oder $TMPDIR (gültig?) oder %_tmppath wie durch den rpmbuild Prozess erstellt) gemäß der folgenden Matrix:

/tmp, /var/tmp, $TMPDIR, %{_tmppath>}  %{_builddir}  %{buildroot}
%prep yes yes no
%build yes yes no
%install yes yes yes
%check yes yes no
%clean yes yes yes

Weitere Klärung: Das sollte gelten, ungeachtet der UID des Paketbauers.

Abschnitt Dateien (%files)

Es gibt Regeln für den Abschnitt Dateien der Spezifikationsdatei. openSUSE folgt dem Standard für die Hierarchie des Dateisystems (FHS) mit Bezug auf die Gestaltung des Dateisystems. Der FHS definiert, wo die Dateien auf dem System angeordnet werden sollten. Jede Abweichung vom FHS sollte als Kommentar in der Spezifikationsdatei begründet werden.

Inhalt/Eigentumsrecht

Ihr Paket sollte alle Dateien enthalten, die als Teil des Prozesses %install installiert werden. Die Pakete dürfen keine Pakete enthalten, die bereits in anderen Paketen enthalten sind. Die Daumenregel hier ist, das das erste Paket, das installiert wird, sollte die Dateien enthalten, auf die sich andere verlassen können. Wenn Sie glauben, einen guten Grund zu haben, eine Datei einzuschließen, das ein anderes Paket bereits besitzt, dann präsentieren Sie das bitte während der Zeit der Paketdurchsicht.

Der Verzeichnisinhalt ist etwas komplexer als der Dateiinhalt. Obwohl die Daumenregel die gleiche ist: besitze alle Verzeichnisse, die Sie erstellen, aber keins der Verzeichnisse von Paketen, von denen Sie abhängen. Es gibt verschiedene Instanzen für mehrere Pakete, das Verzeichnis zu besitzen. Beispiele dafür sind:

  1. Das Paket, von dem Sie abhängen, ein Verzeichnis bereit zu stellen, könnte wählen, ein anderes Verzeichnis in einer späteren Version zu besitzen und Ihr Paket wird mit dieser späteren Version unmodifiziert laufen. Ein allgemeines Beispiel dafür ist ein Perl-Modul. Angenommen perl-A-B hängt von perl-A ab und installiert Dateien unter /usr/lib/perl5/vendor_perl/5.8.8/i386-linux-thread-multi/A/B. Das Basis-Perl-Paket garantiert, dass es /usr/lib/perl5/vendor_perl/5.8.8/i386-linux-thread-multi besitzt so lange wie es mit Version 5.8.8. kompatibel ist. Aber ein zukünftiges Upgrade der Paketes perl-A könnte in /usr/lib/perl5/vendor_perl/5.9.0/i386-linux-thread-multi/A installieren und das besitzen. So muß das Paket perl-A-B /usr/lib/perl5/vendor_perl/5.8.8/i386-linux-thread-multi/A besitzen und ebenso /usr/lib/perl5/vendor_perl/5.8.8/i386-linux-thread-multi/A/B, um ausreichende Eigentumsrechte zu erhalten.
  2. Mehrere Pakete haben Dateien in einem allgemeinen Verzeichnis, aber keines von ihnen benötigt andere. Ein Beispiel
Foo-Animal-Emu legt Dateien in /usr/share/Foo/Animal/Emu
Foo-Animal-Llama legt Dateien in /usr/share/Foo/Animal/Llama

Kein Paket hängt vom anderen ab. Kein Paket hängt von einem anderen Paket ab, das das Verzeichnis /usr/share/Foo/Animal besitzt. In diesem Fall muss jedes Paket das Verzeichnis /usr/share/Foo/Animal besitzen.

In allen Fällen sichern wir ab, dass keine besitzende Verzeichnisse auf einem System vorhanden sind. Bitte suchen Sie unter Packaging/Unowned_Directories nach detaillierten Informationen.

Ein openSUSE Paket darf keine doppelten Dateien in der %files-Auflistung enthalten, sowohl im Sinn von ein Dateipaket zwei mal oder mehr (in zwei oder mehreren Subpaketen) und im Sinn von Inhalt. Starte %fdupes %buildroot (erfordert das Hinzufügen von BuildRequires: fdupes), um doppelte Inhalte geschickt zu beseitigen, indem diese Dateien durch Hartlinks zu einander ersetzt werden.

Erlaubnisse

Erlaubnisse auf Dateien müssen ordentlich gesetzt werden. Ausführbare sollten zum Beispiel mit der Erlaubnis zur Ausführung gesetzt werden. Jeder %files Abschnitt muss eine Zeile %defattr(...) enthalten. Hier ist ein guter Standard:

%files
%defattr(-,root,root)

Außer Sie haben einen guten Grund, davon abzuweichen, sollten Sie %defattr(-,root,root) für alle %files Abschnitte in Ihrem Paket verwenden.


SUID Angelegenheiten

FIXME: Dieser Abschnitt basiert meist auf der Versuch-und-Irrtum-Methode. Der Autor hat keine Dokumentation darüber gefunden.

Sicherheitsrelevante Erlaubnisse werden bei openSUSE über /etc/permissions* geregelt. Paket-spezifische Erlaubnisse können über die Dateien in /etc/permissions.d/ definiert werden. Lesen Sie die Dateien unter /etc/permissions*, um mehr über die Grundlagen zu erfahren.

Wenn Sie ein Paket mit SUID-Programmen erstellen wollen, machen Sie folgendes:

  • Fügen Sie einen Header Requires(post): permissions zu Ihrer Spezifikationsdatei.
  • Erzeugen Sie die Dateien permissions{,.easy,.secure,.paranoid} für Ihr Paket. permissions wird verwendet, wenn keine Datei permissions.*, auf die die momentanen Sicherheitseinstellungen des Systems passen, gefunden werden. Als Daumenregel gilt, permissions.easy sollte Erlaubnisse enthalten, wie sie von make install installiert wurden. permissions.paranoid sollte alle SUID-Stückchen beseitigen (auch wenn das die Funktionsweise zerbricht). permissions.secure kann etwas zwischen beiden sein.
  • Fügen Sie diese Erlaubnis-Dateien als Quellen zur Spezifikationsdatei und lassen Sie %install diese in %{buildroot}%{_sysconfdir}/permissions.d/packagename[.suffix] installieren.
  • Im Abschnitt %files definieren Sie die Attribute der Dateien, die in Ihren Erlaubnis-Dateien aufgelistet sind, so wie sie für permissions.secure definiert sind. Instruieren Sie rpmverify, die Eigentumsrechte oder Erlaubnisse nicht zu prüfen.
  • Fügen Sie ein Scriptlet %post hinzu, das Ihre Paket-Erlaubnisse gemäß dem momentanen Sicherheitsniveau des Systems einrichtet.
  • Fügen Sie ein Scriptlet %verifyscript hinzu, das Ihre Erlaubnisse der Pakete gemäß dem momentanen Sicherheitsniveau des Systems prüft.
  • Um Fehlermeldungen von rpmlint über verweigerte Erlaubniss-Dateien zu vermeiden, erzeugen Sie eine Datei packagename-rpmlintrc, die die Zeile setBadness('permissions-unauthorized-file', 333) enthält und listen diese als Quelle in Ihrer Spezifikationsdatei auf. (Modifizieren Sie die "333", wenn Sie weniger oder mehr als 3 verweigerte Dateien haben.)

Und weil das Oberen einige nicht-offensichliche Details enthält, hier ein Beispiel:

[...]
Source2:        permissions
Source3:        permissions.easy
Source4:        %{name}-rpmlintrc
[...]
PreReq:         permissions
[...]

%install
[...]
mkdir -p %{buildroot}%{_sysconfdir}/permissions.d/
install -m 644 %{S:2} %{buildroot}%{_sysconfdir}/permissions.d/%{name}
install -m 644 %{S:3} %{buildroot}%{_sysconfdir}/permissions.d/%{name}.easy

%if 0%{?suse_version} >= 1120
%verifyscript
%verify_permissions -e %{_bindir}/mysuidprogram
%endif

%post
%if 0%{?set_permissions:1} > 0
    %set_permissions %{name}
%else
    %run_permissions
%endif

%files
%defattr(-,root,root,-)
[...]
%verify(not user group mode) %attr(0711,root,root) %{_bindir}/mysuidprogram
[...]

Das funktioniert zumindest für Pakete in Ihrem Home-Projekt.

Dokumentationsdateien

Jede relevante Dokumentation, die in der Quell-Distribution enthalten ist, sollte im Paket enthalten sein. Eine unwichtige Dokumentation enthält Bauanweisungen, die allgegenwärtige Datei INSTALL, die zum Beispiel typische Bauanweisungen enthält, und eine Dokumentation für nicht-Linux-Systeme, wie z.B. README.MSDOS. Beachten Sie auch in welches Subpaket Sie eine Dokumentation einbringen. Zum Beispiel gehört die API-Dokumentation in das Subpaket -devel und nicht in das Hauptpaket. Oder wenn es einen großen Dokumentationsumfang gibt, ziehen Sie in Betracht, sie in ein eigenes Subpaket zu stecken. In diesem Fall wird empfohlen, *-doc als Bezeichnung für das Subpaket zu verwenden und Documentation als Wert der Group-Markierung.

Wenn ein Paket etwas wie %doc enthält, darf es nicht die Laufzeit der Anwendung beeinflussen. Zusammen gefasst: Wenn es in %doc ist, muss das Programm ordentlich laufen, als wenn es nicht vorhanden ist.

Konfigurationsdateien

Konfigurationsdateien müssen als solche in Paketen gekennzeichnet werden. Als Daumenregel verwenden Sie %config(noreplace) anstelle von reinem %config, außer Ihre beste gebildete Annahme ist, das so zu machen, wird die Sachen zerstören. Mit anderen Worten, denken Sie schwer nach, bevor Sie lokale Änderungen in Konfigurationsdateien von Paketaktualisierungen überschreiben. Ein Beispielfall ist, wenn Sie nicht noreplace verwenden, wenn Sie eine Konfigurationsdatei eines Paketes ändern, führt dazu, dass die neue Paketrevision nicht mit der Konfigurationsdatei der vorhergehenden Paketrevision arbeiten würde. Wenn immer das einfache %config verwendet wird, fügen Sie einen kurzen Kommentar in die Spezifikationsdatei ein, die erklärt warum.

Verwenden Sie nicht %config oder %config(noreplace) unter /usr. Unter openSUSE gilt, dass /usr keine Konfigurationsdatein enthält.

Entwicklungsdateien

Wenn Software, die gepackt wird, Dateien enthält, die ausschließlich für die Entwicklung vorgesehen sind, sollten diese Dateien in ein Subpaket -devel stecken. Das Folgende sind Beispiele für Dateitypen, die in -devel sein sollten:

  • Header Dateien (z.B. .h Dateien)
  • Nicht versionierte gemeinsame Bibliotheken (z.B. libfoo.so). Versionnierte gemeinsame Bibliotheken, z.B. libfoo.so.3, libfoo.so.3.0.0 sollte nicht in -devel sein.
  • pkgconfig Dateien. Eine begründete Ausnahme ist, wenn das Hauptpaket selbst ein Entwicklungswerkzeug ist, z.B. gcc oder gdb.

Pakete, die pkgconfig (.pc)-Dateien enthalten, müssen BuildRequires: pkg-config benutzen, so dass eine ausreichende Laufzeitabhängigkeit Requires: pkg-config hinzugefügt wird.

Sprachdateien

openSUSE enthält ein RPM-Makro, genannt %find_lang. Dieses wird alle die Sprachdateien aufspüren, die zu Ihrem Paket (durch die Bezeichnung) gehören und steckt diese Liste in eine Datei. Sie können dann diese Datei verwenden, um alle diese Sprachen hinzu zu fügen. %find_lang sollte im %install-Abschnitt Ihrer Spezifikationsdatei ausgeführt werden, nachdem alle Dateien in buildroot installiert wurden. Die Verwendung von %find_lang hält die Spezifikationsdatei einfach und hilft, mehrere andere Paketbaufehler zu vermeiden.

  • Pakete, die %{_datadir}/* verwenden, um alle Sprachdateien in einer zu erfassen, erfassen ebenso die Eigentumsrechte der örtlichen Verzeichnisse, was nicht erlaubt ist.
  • Die meisten Pakete, die Sprachen enthalten, enthalten eine Menge Sprachen. Die Verwendung von %find_lang ist viel einfacher für Spezifikationsdateien als folgendes machen zu müssen:
%{_datadir}/locale/ar/LC_MESSAGES/%{name}.mo
%{_datadir}/locale/be/LC_MESSAGES/%{name}.mo
%{_datadir}/locale/cs/LC_MESSAGES/%{name}.mo
%{_datadir}/locale/de/LC_MESSAGES/%{name}.mo
%{_datadir}/locale/es/LC_MESSAGES/%{name}.mo
...
  • Da neue Sprachdateien in nachfolgenden Paketrevisionen erscheinen, wird %find_lang sie automatisch einbeziehen, wenn es gestartet wird. Es vermeidet, dass Sie die Spezifikationsdatei nicht mehr als notwendig aktualisieren.

Nicht-ASCII Dateibezeichnungen

Dateibezeichnungen, die nicht-ASCII-Zeichen enthalten, müssen als UTF-8 verschlüsselt werden. Da es dafür keine Möglichkeit gibt, zu erkennen, in welcher Kodierung die Dateibezeichnung ist. Die Verwendung der gleichen Kodierung für alle Dateibezeichnungen ist der beste Weg, sicher zu stellen, dass die Anwender die Dateibezeichnungen richtig lesen können. Wenn der Upstream eine Dateibezeichnung liefert, die nicht in UTF-8 kodiert ist, können Sie ein Dienstprogramm wie convmv (vom Paket convmv) verwenden, um die Dateibezeichnung in Ihrem %install-Abschnitt zu konvertieren.

Libexecdir

Der Dateisystem Hierarchie Standard enthält keine Regelung für libexecdir. Aber openSUSE Pakete können geeignete Pakete dort ablegen. Libexecdir (was auf openSUSE Systemen zu /usr/lib umdefiniert wurde) sollte als Verzeichnis für ausführbare Programme verwendet werden, die ursprünglich dafür entwickelt wurden, von anderen Programmen gestartet zu werden und nicht durch den Benutzer. openSUSE RPM enthält ein Makro für libexecdir, %{_libexecdir}. Paketbauer werden stark angehalten, libexecdir-Dateien in einem Paket-spezifischen Unterverzeichnis von %{_libexecdir} zu speichern, wie etwa %{_libexecdir}/%{name}.

Abschnitt Changelog (%changelog)

Immer wenn Sie ein Paket verändern, müssen Sie einen Changelog-Eintrag hinzufügen. Das ist wichtig, nicht nur über die Geschichte eines Paketes Bescheid zu wissen, sondern auch dem Anwender, Partnerpakete und OA-Leuten zu ermöglichen, die Änderungen, die Sie machen, zu erkennen.

Der Open Build Service verwendet eine separate Datei für Paketänderungen. Diese Datei wird wie die Spezifikationsdatei benannt, hat aber .changes am Ende, anstelle von .spec. Changelog-Einträge müssen in einer chronologischen Anordnung sein. Neuere Changelog-Einträge sind in der Datei oberhalb älterer Einträge aufgelistet. Es sind keine Fixes früherer Changelog-Einträge erlaubt, wenn ein Paket in die offiziellen Paketquellen "eingecheckt" wird.

Einträge in diese Änderungsdateien haben die folgende Struktur:

-------------------------------------------------------------------
Tue Apr 22 20:54:26 UTC 2011 - your@email.com

- bullet point 1
* bullet point 1.1 with long
  long long description
* bullet point 1.2
- bullet point 2 with long long long
  description
* bullet point 2.1

Patches in den Änderungsdateien sollten den Patches Richtlinien folgen (speziell der Teil Abkürzungen).

Warnung!Pakete in openSUSE:Factory erfordern, dass Änderungen mit jedem neuen Upstream-Release aufgelistet werden. Sie müssen noch diese Information in der Datei .changes liefern, wie zum Beispiel "update to 1.2.3: no changelog available"