Heute kam ich mal in die Verlegenheit, ein RPM aus einem Binary-Paket zu „backen“. Tante Google bringt zwar viele Infos zum Vorschein, aber nicht jede passt auch wirklich zu meinem Problem. Mit etwas probieren und ein wenig Lektüre habe ich das nachstehende, reale SPEC-File erstellt. Ich bezieh mich hier auf openSUSE 11.3 und dem mitgelieferten RPM in Version 4.8.0.
#Konstanten %define elela_version 1.0.11113 %define elela_release 0 #Specfile fuer EleLa Summary: EleLa - Elektronik Lagerverwaltung Name: EleLa Version: %{elela_version} Release: %{elela_release} License: Freeware Group: Office/Database Source: EleLa-%{elela_version}.tar.bz2 Vendor: Markus Mueller URL: http://www.mmvisual.de Distribution: openSUSE 11.3 Packager: Udo Neist <udo.neist@singollo.de> Prefix: /opt Requires: kchmviewer libsqlite3-0 Obsoletes: %name < %version ExclusiveArch: i586 ExclusiveOS: Linux ExcludeArch: sparc x86_64 m68k alpha %description Management of electronic components. Possibility to store images, creation of cases, type differentiation, order management, quantities, project management, parts lists, history functions, knowledge base, label printing. Supports different database systems, it can be used simultaneously with multiple computers. %description[de] Verwaltung von elektronischen Bauteilen. Speichermöglichkeit von Bildern, Anlegen von Gehäuse, Typunterscheidung, Bestellungverwaltung, Stückzahlen, Projektverwaltung, Stücklisten, Historienfunktion, Wissensdatenbank, Etikettendruck. Unterstützt unterschiedliche Datenbank-Systeme, so kann es auch mit mehreren Rechnern gleichzeitig benutzt werden. %install rm -rf $RPM_BUILD_ROOT%prefix/ mkdir -p $RPM_BUILD_ROOT%prefix/ tar xfvB $RPM_BUILD_SOURCE/%sources -C $RPM_BUILD_ROOT%prefix/ mkdir -p %{buildroot}%{_datadir}/applications cat > %{buildroot}%{_datadir}/applications/%{name}.desktop <<EOF [Desktop Entry] Name=EleLa Name[de]=EleLa Comment=Management of electronic components. Possibility to store images, creation of cases, type differentiation, order management, quantities, project management, parts lists, history functions, knowledge base, label printing. Supports different database systems, it can be used simultaneously with multiple computers. Comment[de]=Verwaltung von elektronischen Bauteilen. Speichermöglichkeit von Bildern, Anlegen von Gehäuse, Typunterscheidung, Bestellungverwaltung, Stückzahlen, Projektverwaltung, Stücklisten, Historienfunktion, Wissensdatenbank, Etikettendruck. Unterstützt unterschiedliche Datenbank-Systeme, so kann es auch mit mehreren Rechnern gleichzeitig benutzt werden. Exec=%{prefix}/EleLa/EleLa Icon=%{prefix}/EleLa/elela.png Terminal=false Type=Application Categories=Qt:KDE;Office;Database; EOF %clean rm -rf $RPM_BUILD_ROOT %pre if [ -d /usr/lib ]; then if [ ! -L /usr/lib/libsqlite3.so ]; then ln -sf /usr/lib/libsqlite3.so.0 /usr/lib/libsqlite3.so; fi fi if [ -d /usr/lib64 ]; then if [ ! -L /usr/lib64/libsqlite3.so ]; then ln -sf /usr/lib64/libsqlite3.so.0 /usr/lib64/libsqlite3.so; fi fi %post if [ ! -f %{prefix}/EleLa/Tables.txt ]; then mv %{prefix}/EleLa/Tables.txt.default %{prefix}/EleLa/Tables.txt fi if [ ! -f %{prefix}/EleLa/EleLa.sq3 ]; then mv %{prefix}/EleLa/EleLa_Elektronik.sq3.default %{prefix}/EleLa/EleLa.sq3 fi if [ ! -f %{prefix}/EleLa/EleLa_Waren.sq3 ]; then mv %{prefix}/EleLa/EleLa_Waren.sq3.default %{prefix}/EleLa/EleLa_Waren.sq3 fi if [ ! -f %{prefix}/EleLa/EleLa.ini ]; then mv %{prefix}/EleLa/EleLa.ini.default %{prefix}/EleLa/EleLa.ini fi rm -rf %{prefix}/EleLa/*.default if [ ! -L /usr/local/bin/EleLa ]; then ln -sf %{prefix}/EleLa/EleLa /usr/local/bin/EleLa; fi chmod 777 %{prefix}/EleLa mkdir -p %{prefix}/EleLa/Log chmod 777 %{prefix}/EleLa/Log %preun if [ "$1" = 0 ] ; then if [ -x %{prefix}/EleLa/EleLa ]; then %{prefix}/EleLa/EleLa -uninstall fi fi %postun if [ "$1" = 0 ] ; then if [ ! -f %{prefix}/EleLa/EleLa ]; then rm -rf %{prefix}/EleLa/Log if [ -L /usr/local/bin/EleLa ]; then rm /usr/local/bin/EleLa; fi fi rmdir --ignore-fail-on-non-empty %{prefix}/EleLa fi %files %defattr(-,root,root) %doc %{prefix}/EleLa/ReadMe.txt %attr(777,root,root) %{prefix}/EleLa/EleLa %attr(666,root,root) %{prefix}/EleLa/EleLa.chm %attr(666,root,root) %{prefix}/EleLa/EleLa.ini_Demo_MySQL %attr(666,root,root) %{prefix}/EleLa/EleLa.ini_Demo_PostgreSQL %attr(666,root,root) %{prefix}/EleLa/EleLa.ini_Demo_SQLite %attr(666,root,root) %{prefix}/EleLa/elela_MySQL_Start.sql %attr(666,root,root) %{prefix}/EleLa/elela_Postgres_Start.sql %{prefix}/EleLa/Lang_DE_Waren.txt %{prefix}/EleLa/Lang_EN.txt %{prefix}/EleLa/lclstrconsts.de.po %{prefix}/EleLa/elela.png %{prefix}/EleLa/libsqlite3.so /usr/share/applications/EleLa.desktop %attr(666,root,root) %{prefix}/EleLa/EleLa.ini.default %attr(666,root,root) %{prefix}/EleLa/EleLa_Elektronik.sq3.default %attr(666,root,root) %{prefix}/EleLa/EleLa_Waren.sq3.default %attr(666,root,root) %{prefix}/EleLa/Tables.txt.default
Das SPEC-File definiert in den ersten Zeilen ein paar Konstanten, die im weiteren Verlauf des Builds verwendet werden. Damit vermeidet man Fehler, die durch nicht korrigierte Zeilen nach einer Änderung übersehen wurden. Die Kopfzeilen Summary bis Prefix sind ja noch einigermassen selbsterklärend, auch %description kann man noch verstehen, aber für die Abschnitte %install, %clean, %post, %postun und %files bedarf es etwas Erklärung.
Der Block %install enthält alle notwendigen Befehle, um das Ziel zu installieren. Da es ein binär-only-Paket sein soll, ist der Block %build erst gar nicht definiert. Die Variable %prefix definiert einen Default für das Installationsverzeichnis. Dieser sollte mit der Option –prefix überschrieben werden können. Zuerst wird ein eventuell vorhandenes Verzeichnis unter $RPM_BUILD_ROOT%prefix gelöscht und dann neu angelegt. Darin wird dann das Archiv entpackt. Im Archiv müssen bereits alle Rechte richtig gesetzt werden.
Nach dem Build wird das Verzeichnis einfach wieder geleert.
Dieser Abschnitt enthält alle Befehle, die nach der Installation ausgeführt werden sollen. Entsprechend gibt es auch ein Abschnitt %pre, der vor der Installation ausgeführt wird.
Analog zu %post undn %pre gibt es auch einen Abschnitt zur Befehlsausführung vor oder nach der Deinstallation.
Hier wird einfach eine Auflistung aller im Archiv vorhandenen Dateien angehängt. Dabei ist zu beachten, das die absoluten Pfade angegeben werden. Mit der „Anweisung“ %doc werden eventuelle Dokumentationen in das entsprechende Paketverzeichnis unter /usr/share/doc/packages kopiert. Das Macro %attr definiert die Rechte (chmod) und den Besitzer/die Gruppe des Files.
Sollte das SPEC-File fertig erstellt worden sein, so reicht ein
rpmbuild -v -bb Foo.spec --target=i586
für das Bauen eines für i586 definierten RPMs. Man kann hier andere Architekturen angeben. Läuft der Build fehlerfrei ab, existiert im zur Architektur passenden RPMS-Unterverzeichnis das fertige RPM. Man sollte es probeweise installieren, um eventuell noch vorhandene Fehler zu finden.
Dazu brauchen wir einen GPG-Schlüssel. Sollte noch keiner vorhanden sein, so lässt sich ein neuer mittels
gpg --gen-key
erstellen. Wenn bereits einer oder mehrere vorhanden sein sollten, kann man mit
gpg -k
eine Liste aller verfügbaren Schlüssel ausgeben lassen. Da ich selbst mehrere Schlüssel besitze, suche ich mir einen passenden mittels
gpg -k "Udo Neist"
aus der Liste heraus. Damit der Schlüssel auch öffentlich überprüfbar ist, sendet man diesen an einen Keyserver, wobei optional ein Keyserver angegeben werden kann. Mit folgender Zeile sendet man den Schlüssel an den Standard-Keyserver:
gpg --send-keys 08335316
Den Schlüssel sollte man auch auf Gültigkeit prüfen:
gpg --check-sigs 08335316
Den öffentlich Teil des Schlüssels exportiere ich mit
gpg --export --armor 08335316 > gpg-pub-key
den ich dann als User root in den RPM-Schlüsselbund importiere:
rpmsign --import gpg-pub-key
Um jedoch die RPMs auch noch zu signieren, muss ich eine Datei .rpmmacros in meinem HOME-Verzeichnis erstellen.
%_signature gpg %_gpg_name Udo Neist (udo@singollo.de) <udo@singollo.de> %_gpg_home /home/udo/.gnupg
Erst damit kann man ein RPM korrekt signieren:
rpmbuild -v --sign -bb Foo.spec --target=i586
Man wird nach dem Passwort für den Schlüssel gefragt, bevor ein signiertes Paket gebaut werden kann.