Paketbaurichtlinien für PHP
Paketbaurichtlinien für PHP-Addon-Module in Fedora
Verschiedene Typen von PHP-Paketen
Es gibt im Wesentlichen 4 verschiedene Arten von PHP-Modulen, die für Fedora paketiert sind:
-
Die Module der PHP Extension Community Library (PECL) sind PHP-Module, die üblicherweise in C geschrieben sind und beim Start dynamisch vom PHP-Interpreter geladen werden. Diese werden zugunsten von PIE (Pipe Injection) eingestellt.
-
PEAR-Module (PHP Extension and Application Repository) bietet wiederverwendbare PHP-Komponenten (meist Klassen), die in eigenen PHP-Anwendungen und -Skripten beispielsweise mit der
include()-Direktive eingebunden werden können. Dies gilt jedoch als veraltet und wird nicht mehr empfohlen. Verwenden Sie stattdessen „Composer“. -
Composer-registrierte Bibliotheken, bei denen es sich um wiederverwendbare, in PHP geschriebene Komponenten handelt, in der Regel PSR-0-konforme Klassen, die in einer Paketregistrierung, meist auf Packagist, registriert sind.
-
CHANNEL: Pakete, die einen Kanal registrieren. Ein Kanal ist ein Repository, das PHP-Erweiterungen bereitstellt. Dies ist veraltet und wird nicht mehr empfohlen.
-
PIE registrierte Erweiterungen, die üblicherweise in C geschriebene PHP-Module sind und vom PHP-Interpreter beim Start dynamisch geladen werden. Sie sind in einer Paketregistrierung, meist auf Packagist, registriert.
-
Andere Pakete, die eine PHP-Erweiterung bereitstellen, die nicht von den PEAR/PECL-Mechanismen verarbeitet wird.
Während Upstream für PECL und PEAR das gleiche Paket- und Vertriebsformat verwendet, müssen bei der Erstellung von RPMs einige Unterschiede berücksichtigt werden.
Bei der Installation von php-pear werden 3 Kanäle definiert:
-
pear.php.net(aliaspear): der Standardkanal für das PHP-Erweiterungs- und Anwendungs-Repository -
pecl.php.net(aliaspecl): der Standardkanal für die PHP Extension Community Library -
__uri: Pseudo-Kanal für statische Pakete
Andere Kanäle müssen sowohl während des RPM-Bauprozesses als auch während der RPM-Installation konfiguriert werden.
Benennungsschema
-
PECL-Pakete aus dem Standard-PECL-Kanal sollten nach dem Schema
php-pecl-PECLPaketname-%{version}-%{release}.%{arch}.rpmbenannt werden. -
PEAR-Pakete aus dem Standard-PEAR-Kanal sollten nach dem Schema
php-pear-PEARPaketname-%{version}-%{release}.noarch.rpmbenannt werden. -
CHANNEL-Pakete sollten nach dem Schema
php-channel-ChannelAlias-%{version}-%{release}.noarch.rpmbenannt werden. -
Pakete aus anderen Kanälen sollten nach dem Schema
php-ChannelAlias-Paketname-%{version}-%{release}.noarch.rpmbenannt werden. -
Composer-fähige Pakete (die auf packagist.org oder einer anderen Registry referenziert werden) sollten den Namen
php-vendor-library-%{version}-%{release}.noarch.rpmtragen (wobeivendor/libraryder bekannte Packagist-Name ist, dasname-Attribut incomposer.json). Wennvendorgleichlibraryist, kann eines davon weggelassen werden (z.B. kannsymfony/symfonyinphp-symfonyumbenannt werden). -
PIE-fähige Pakete (die in packagist.org oder einer anderen Registry referenziert werden) sollten den Namen
php-vendor-extension-%{version}-%{release}.%{arch}.rpmtragen (wobeivendor/extensionder bekannte Packagist-Name ist, dasname-Attribut incomposer.json). Wennvendorgleichextensionist, kann eines der beiden weggelassen werden (z.B. kannxdebug/xdebuginphp-xdebugumbenannt werden). -
Andere Pakete sollten den Namen
php-PackageName-%{version}-%{release}.%{arch}.rpmtragen;%{arch}kann gegebenenfalls durchnoarchersetzt werden.
Bitte stellen Sie sicher, dass ein reines PHP-Paket (PEAR, packagist…) korrekt für noarch erstellt wird.
Wie bei anderen Paketen sollte der Name nur Kleinbuchstaben enthalten, Unterstriche und Schrägstriche werden durch Bindestriche ersetzt.
Die Namen PECLPackageName und PEARPackageName sollten mit dem Namensschema des Upstream-Projekts übereinstimmen. Die Crack-PHP-Erweiterung würde demnach php-pecl-crack heißen, und die resultierenden Pakete wären php-pecl-crack-0.4-1.i386.rpm und php-pecl-crack-0.4-1.src.rpm.
Beachten Sie, dass Anwendungen, die in PHP geschrieben sind, nicht in den php-*-Namensraum gehören.
Dateiplatzierung
Nicht-PEAR-PHP-Software, die gemeinsam genutzte Bibliotheken bereitstellt, sollte ihre PHP-Quelldateien für diese Bibliotheken in einem Unterordner von %{_datadir}/php ablegen, dessen Name dem Namen der Software entspricht. Beispielsweise würde eine Bibliothek namens Whizz_Bang (mit einem RPM-Paket namens php-something-Whizz-Bang) die PHP-Quelldateien für ihre gemeinsam genutzten Bibliotheken in %{_datadir}/php/Whizz_Bang ablegen.
Eine PSR-0-konforme Bibliothek [1] würde ihre PHP-Dateien in %{_datadir}/php/ ablegen.
Eine PSR-4-konforme Bibliothek [2]) würde ihre PHP-Dateien in einem PSR-0-konformen Verzeichnisbaum unter %{_datadir}/php/ ablegen.
Die upstreamseitig bereitgestellte PEAR-Dokumentation wird in %{pear_docdir} installiert, sollte dort bleiben und muss als %doc gekennzeichnet werden.
Die upstreamseitig bereitgestellte PECL-Dokumentation wird in %{pecl_docdir} installiert, sollte dort bleiben und muss als %doc gekennzeichnet werden.
Die Datei composer.json wird nicht verwendet und sollte als %doc installiert werden, da sie nützliche Informationen über das Paket und seine Abhängigkeiten enthält.
Requires und Provides
PEAR-Pakete aus dem Standard-Channel/Repository
Ein PEAR-Paket MUSS Folgendes haben:
BuildRequires: php-pear(PEAR)
Requires: php-pear(PEAR)
Requires(post): %{__pear}
Requires(postun): %{__pear}
Provides: php-pear(foo) = %{version}
Das virtuelle „Provides“ sollte exakt mit dem Upstream-Namen übereinstimmen, einschließlich Groß-/Kleinschreibung und Unterstrich, z.B.: php-pear(Text_Wiki)
Für ein PEAR-Paket müssen alle seine Abhängigkeiten als PEAR-Pakete vorliegen. Es sollte daher nur diejenigen Pakete einbinden, die die virtuelle Bereitstellungsmethode php-pear(foo) verwenden. Eine bekannte Ausnahme bilden nicht gebündelte Bibliotheken (die häufig gebündelt werden, da sie in keinem PEAR-Kanal verfügbar sind).
Pakete für CHANNEL- (Repository-)Konfiguration
Ein CHANNEL-Paket MUSS Folgendes haben:
Requires: php-pear(PEAR)
Requires(post): %{__pear}
Requires(postun): %{__pear}
Provides: php-channel(channelname)
PEAR-Pakete aus einem Nicht-Standard-Channel/Repository
Ein PEAR-Paket MUSS Folgendes haben:
BuildRequires: php-channel(channelname)
BuildRequires: php-pear(PEAR)
Requires: php-pear(PEAR)
Requires(post): %{__pear}
Requires(postun): %{__pear}
Requires: php-channel(channelname)
Provides: php-pear(channelname/foo) = %{version}
Composer-registrierte Pakete
Jedes auf Packagist registrierte Paket (das am weitesten verbreitete und daher implizite Paketregister) MUSS Folgendes enthalten:
Provides: php-composer(vendor/library) = %{version}
Pakete aus anderen Registrierungen MÜSSEN Folgendes haben:
Provides: php-composer(registry_url/vendor/library) = %{version}
Das virtuelle „Provides“ sollte exakt mit dem Upstream-Namen übereinstimmen, einschließlich Unterstrich, z. B.: php-composer(pear/console_table)
Pakete, die von PEAR nach Composer/Packagist migriert wurden, sollten bei Bedarf auch php-pear(foo) per „Provides“ bereitstellen (wird von anderen PEAR-Paketen verwendet).
Pakete dürfen keine Abhängigkeiten von php-pear(foo) aufweisen, sollten aber php-composer(pear/foo) verwenden.
composer.json nützliche Attribute (siehe Composer-Schema-Dokumentation)
-
name -
description: eine Zeile, kann als „Summary“ für RPM verwendet werden -
homepage: kann als „URL“ für RPM verwendet werden -
license -
require: Beschreibt obligatorische Abhängigkeiten wie die PHP-Version, PHP-Erweiterungen oder andere Composer-Bibliotheken, die vom RPM-Paket alsphp-composer(foo)eingebunden werden müssen. -
require-dev: beschreibt Entwicklungsabhängigkeiten, die üblicherweise zur Bauzeit nützlich sind (z.B. zum Ausführen von Unit-Tests), und könnte daher als BuildRequires erscheinen. -
suggest: beschreibt optionale Abhängigkeiten und kann daher als Requires erscheinen (Entscheidung des Paketierers). -
conflict: wie „Conflicts“ in RPM -
replace: wie „Obsoletes“ in RPM -
provide: Für zusätzliche virtuelle „Provides“; muss auch in den RPM-„Provides“ alsphp-composer(foo)enthalten sein.
C-Erweiterungen (PECL und andere)
Um sicherzustellen, dass eine Binärerweiterung mit einer bestimmten PHP-Version korrekt ausgeführt wird, muss geprüft werden, ob das jeweilige Paket sowohl eine API als auch eine ABI besitzt, die mit der installierten PHP-Version übereinstimmen. Der Mechanismus hierfür ist wie folgt:
BuildRequires: php-devel
Requires: php(zend-abi) = %{php_zend_api}
Requires: php(api) = %{php_core_api}
Jede Erweiterung MUSS außerdem (um das Heraus-/Einrücken von php-src zu verfolgen) den module-Namen verwenden, wie er von „php --modules“ ausgegeben wird, oder den .so-Dateinamen in Kleinbuchstaben.
Provides: php-module = %{version}
Provides: php-module%{_isa} = %{version}
PECL-Pakete
Die PECL-Erweiterung MUSS eine ABI-Prüfung haben (siehe C-Erweiterungen oben).
Ein PECL-Paket MUSS außerdem Folgendes haben:
Provides: php-pecl(foo) = %{version}
Provides: php-pecl(foo)%{?_isa} = %{version}
PECL-Pakete aus einem nicht standardmäßigen Kanal/Repository
Ein PECL-Paket aus einem nicht standardmäßigen Kanal MUSS (anstelle der bisherigen „Provides“) Folgendes haben:
Requires: php-channel(channelname)
Provides: php-pecl(channelname/foo) = %{version}
Provides: php-pecl(channelname/foo)%{?_isa} = %{version}
PIE-Pakete
Die PIE-Erweiterung MUSS eine ABI-Prüfung haben (siehe C-Erweiterungen oben).
Jedes auf Packagist (dem am weitesten verbreiteten und daher impliziten Paketregister) registrierte Paket MUSS Folgendes enthalten:
Provides: php-pie(vendor/extension) = %{version}
Andere Pakete
PHP-Add-ons, die weder PEAR noch PECL sind, sollten das fordern, was Sinn ergibt (entweder eine Basis-PHP-Version oder ein php-api, php(zend-abi), je nach Bedarf).
Apache-Abhängigkeit
Eine PHP-Bibliothek darf keine expliziten „Requires“ für php oder httpd haben, da diese Bibliotheken mit jedem Webserver oder jeder SAPI (php-cli, php-cgi, php-fpm, …) verwendbar sein sollen.
Nur eine PHP-Webanwendung, die eine spezifische httpd-Konfiguration für Apache bereitstellt, sollte ein „Requires“ für httpd und mod_php haben.
„Requires“ für Erweiterungen
PHP-Erweiterungen müssen ein „Requires“ für alle abhängigen Erweiterungen (php-json, php-gd, php-mbstring, …) enthalten. Diese Erweiterungen sind virtuelle „Provides“ der PHP-Teilpakete.
Folgendes kann ignoriert werden, da immer vorhanden: core, date, filter, hash, pcre, random, reflection, session, spl, standard.
C-Erweiterung und Konfigurationsdateien für PECL-Pakete
Jede Erweiterung sollte eine Konfigurationsdatei in %{php_inidir} und/oder %{php_ztsinidir} ablegen, um die Erweiterung zu aktivieren. Diese Datei muss den Namen der geladenen Erweiterung enthalten. Die Datei muss ein numerisches Präfix verwenden, um die korrekte Ladefolge sicherzustellen:
-
Der Bereich 00-19 ist für zend_extensions reserviert (z.B.:
10-opcache.ini,15-xdebug.ini, …) -
Der Bereich 20-39 ist für Erweiterungen aus PHP-Quellen reserviert (z.B.:
20-pdo.ini,30-pdo_pgsql.ini, …) -
Der Bereich 40-99 ist für andere Erweiterungen verfügbar (z.B.:
40-zip.ini, …)
Makros und Scriptlets
PHP-ZTS-Erweiterung
Wenn der Apache HTTPD im Worker-Modus (anstatt im Prefork-Modus) ausgeführt wird, wird die ZTS-Version („Zend Thread Safe“) von PHP verwendet.
Wenn ein Erweiterungsentwickler eine ZTS-Version dieser Erweiterung bereitstellen möchte, muss er Folgendes sicherstellen:
-
die Erweiterung ist thread-sicher
-
die von der Erweiterung verwendeten Bibliotheken sind thread-sicher
Das Paket php-devel stellt die notwendigen Dateien zum Erstellen von ZTS-Modulen bereit und bietet mehrere Hilfsmakros:
Für Standard-(NTS-)Erweiterungen
%{__php} %{_bindir}/php
%{php_extdir} %{_libdir}/php/modules
%{php_inidir} %{_sysconfdir}/php.d
%{php_incldir %{_includedir}/php
Für ZTS-Erweiterungen
%{__ztsphp} %{_bindir}/zts-php
%{php_ztsextdir} %{_libdir}/php-zts/modules
%{php_ztsinidir} %{_sysconfdir}/php-zts.d
%{php_ztsincldir %{_includedir}/php-zts/php
php-devel stellt die während des Baus einer ZTS-Erweiterung benötigten ausführbaren Dateien bereit, und zwar:
-
zts-phpize -
zts-php-config -
zts-php(was nur zum Ausführen der Testsuite während des Bauprozesses nützlich ist)
Pakete für CHANNEL- (Repository-)Konfiguration
Hier sind einige empfohlene Scriptlets zum ordnungsgemäßen Registrieren und Abmelden des Kanals:
%post
if [ $1 -eq 1 ] ; then
%{__pear} channel-add %{pear_xmldir}/%{name}.xml > /dev/null || :
else
%{__pear} channel-update %{pear_xmldir}/%{name}.xml > /dev/null ||:
fi
%postun
if [ $1 -eq 0 ] ; then
%{__pear} channel-delete %{channelname} > /dev/null || :
fi
PEAR-Module
Das Paket php-pear bietet einige nützliche Makros:
-
%{pear_phpdir} -
%{pear_docdir}(expandiert zu%{_docdir}/pear.) -
%{pear_testdir} -
%{pear_datadir} -
%{pear_xmldir} -
%{pear_metadir}(expandiert zu/var/lib/pear.)
Diese Definitionen für die .spec-Datei dürften von Interesse sein:
BuildRequires: php-pear >= 1:1.4.9-1.2
Provides: php-pear(PackageName) = %{version}
Requires: php-common >= 4.3, php-pear(PEAR)
Requires(post): %{_bindir}/pear
Requires(postun): %{_bindir}/pear
Stellen Sie sicher, dass Sie am Ende von %install alle PEAR-Metadatendateien löschen:
rm -rf %{buildroot}/%{pear_metadir}/.??*
Hier sind einige empfohlene Scriptlets zur ordnungsgemäßen Registrierung des Moduls:
%post
%{_bindir}/pear install --nodeps --soft --force --register-only %{pear_xmldir}/%{name}.xml >/dev/null ||:
Und hier sind einige empfohlene Scriptlets zum ordnungsgemäßen Abmelden des Moduls aus dem Standardkanal:
%postun
if [ "$1" -eq "0" ] ; then
%{_bindir}/pear uninstall --nodeps --ignore-errors --register-only Foo_Bar >/dev/null ||:
fi
Von einem nicht standardmäßigen Kanal (der Befehl pear erfordert die Angabe des Kanals):
%postun
if [ "$1" -eq "0" ] ; then
%{_bindir}/pear uninstall --nodeps --ignore-errors --register-only Foo_channel/Foo_Bar >/dev/null ||:
fi
PECL-Module
Das Paket php-pear bietet einige nützliche Makros:
-
%{pecl_phpdir} -
%{pecl_docdir} -
%{pecl_testdir} -
%{pecl_datadir} -
%{pecl_xmldir}
Um bestimmte Informationen aus PHP zu extrahieren, müssen Sie möglicherweise einige zusätzliche Makros definieren. Es wird empfohlen, Folgendes zu verwenden:
%global php_apiver %((echo 0; php -i 2>/dev/null | sed -n 's/^PHP API => //p') | tail -1)
%{!?__pecl: %{expand: %%global __pecl %{_bindir}/pecl}}
%{!?php_extdir: %{expand: %%global php_extdir %(php-config --extension-dir)}}
Die (De-)Registrierung von Modulen wird automatisch durch Dateitrigger im Paket php-pear gehandhabt.
Für ältere Releases finden Sie hier einige empfohlene Scriptlets zum ordnungsgemäßen Registrieren und Deregistrieren eines Moduls:
BuildRequires: php-pear
Requires(post): %{__pecl}
Requires(postun): %{__pecl}
%post
%{pecl_install} %{pecl_xmldir}/%{name}.xml >/dev/null || :
%postun
if [ $1 -eq 0 ] ; then
%{pecl_uninstall} %{pecl_name} >/dev/null || :
fi
Weitere Module
Wenn Ihr Modul kompilierten Code enthält, müssen Sie möglicherweise einige Makros definieren, um Informationen aus PHP zu extrahieren. Es wird empfohlen, Folgendes zu verwenden:
%global php_apiver %((echo 0; php -i 2>/dev/null | sed -n 's/^PHP API => //p') | tail -1) %global php_extdir %(php-config --extension-dir 2>/dev/null || echo "undefined") %global php_version %(php-config --version 2>/dev/null || echo 0)
Zusätzliche Hinweise für Paketierer
PEAR-und PECL-Pakete
Das Quellarchiv enthält eine package.xml-Datei außerhalb eines Verzeichnisses, daher müssen Sie
%setup -q -c
in Ihrem `%prep-Abschnitt verwenden, um zu verhindern, dass Dateien ins BuildRoot geschrieben werden.
PEAR-Pakete
Um Ihre erste Spec-Datei zu erstellen, können Sie die Standardvorlage des Pakets rpmdevtools verwenden:
rpmdev-newspec -t php-pear php-pear-Foo
Oder Sie können eine selbst erzeugen; stellen Sie sicher, dass Sie das Paket +php-pear-PEAR-Command-Packaging installiert haben:
pear make-rpm-spec Foo.tgz
Want to help? Learn how to contribute to Fedora Docs ›