Ein rpm bauen - wie gehe ich da vor?

Hallo zusammen, ich kompiliere hie und da mal ein paar kleine Programmlis aus den Quellen heraus und würde gerne mal wissen, wie ich da RPMs von baue. Also checkinstall kenne ich schon, das habe ich gerne mit meinen eigenen WINE Bauten verwendet. Allerdings habe ich auch Programme, die mit dem checkinstall wenig anfangen können weil die auch kein make install ausführen. Im Grunde müssen bei den Programmen die Dateien nur an spezielle Verzeichnisse kopiert werden. Wie gehe ich da vor, wenn ich beispielsweise alles in /usr/lib/meinprogramm/ kopieren möchte und von usr/lib/meinprogramm/programm.sh ein Link auf /usr/bin/programm.sh erstellt werden muss. Also ein implementiertes

ln -s usr/lib/meinprogramm/programm.sh /usr/bin/programm.sh

Thanks for any Anregung :slight_smile:

cu
Gargi

Schau dir mal https://build.opensuse.org/ an.

CT’ 14/2010 s. 174 .

Naja, fehlt nur noch
man rpm
als Antwort :wink:

Also nachdem ich über google das Web Länge mal Breite mal Höhe abgesucht habe bin ich soweit, dass ich ein spec File geschrieben habe, das auch kompiliert, mir die Dateien nach /usr/lib/meinprogramm kopiert. Aber dann tickt das beim Buildroot aus. D.h. ich kriege die Meldung dass eben die Dateien im Buildroot nicht gefunden werden. So ist es denn auch. Das Buildroot wird angelegt, aber nichts aus /usr/lib/meinprogramm wird zum Packen dorthin kopiert. Irgendwas passt mit dem Teil noch nicht. Gibt’s da nen Kniff bezüglich dem Buildroot? Spezialitätet wie
BuildRoot: %{_tmppath}/build-%{name}-%{version}
habe ich bereits versucht.

cu
Gargi

nicht “man rpm” sondern “man rpmbuild” .

sudo zypper in -t pattern devel_rpm_build
cp -r /usr/src/packages/ ~/rpmbuild

Gucke man in ~/rpmbuild. Alle gebrauchte Verzeichnisse sind da.

Dann brauchst du eine Datei ~/.rpmmacros, die mehr oder weniger so aussieht:

%_topdir        /home/Gargi/rpmbuild
%_tmppath       /home/Gargi/rpmbuild/tmp
%packager       Gargi <gargi@opensuse.org> 
%distribution   openSUSE
%vendor         openSUSE
%distsuffix     openSUSE

Dann installierst du die rpm Quellen :
rpm -ivh dingsbums.src.rpm

Dann modifizierst du die spec Datei. Die findet sich im Unterverzeichnis ~/rpmbuild/SPECS

Dann compilieren …

cd ~/rpmbuild/SPECS
rpmbuild -ba dingsbums.spec

voilà

Hab’s :slight_smile: Hatte nur nen (wirklich doofen!) Denkfehler beim Erstellen der Installationsanweisungen beim spec File. Ich denke wenn ich mein verhunztes spec gepostet hätte, hätte es jemand gleich gesehen. Wie schon gesagt, soll eigentlich nur ein Quick and Dirty spec sein, also ein make absetzen und die fertigen Files in ein spezielles Verzeichnis dann später kopieren. Das geht dann auch (wenn man weiß wie) relativ easy. Ich schreibe das alles einwenig zusammen und stell es hier rein. Sicherlich gibt es da deutlich ausgefeiltere Methoden, aber oftmals sind es ja nur ein paar wenige Dateien, die in ein Verzeichnis rein müssen und dafür sollte es reichen :slight_smile: Aber auf jeden Fall eine interessante Thematik mit der ich mich noch nicht auseinanderesetzt hatte ( nach dem make install war’s bei mir dann in der Regel erledigt :wink: )

Bis denne!
cu
Gargi

Also das grobe Vorgehen: Ich kompiliere aus den Quellen eines Programmes ein Programm. Na und das heißt zum Beispiel dann meinprogramm. Meinprogramm soll dann einfach mal nach /usr/bin/ kopiert werden, damit es später von dort aus aufrufbar ist. Ich weiß, dass man sowas in /usr/local lieber reinschieben sollte und eventuell ein Startskript nach /usr/bin , aber nur wegen den Beispiel eine Datei kompilieren und dann kopieren.

Vom Vorgehen dann alles als root (um das so einfach wie möglich zu halten): Wir bewegen uns nun im Verzeichnis /usr/src/packages . Dort finden sich folgende für uns wichtige Verzeichnisse: SPECS , SOURCES , RPMS.

Um nun ein RPM zu bauen müssen wir die Quellen des Programmes als tar.gz gepackt nach SOURCES kopieren. Bei dem Programm genügt es einen einfachen “make” abzusetzen. Das Paket nenne ich dann im Verlauf quelle.tar.gz

Jetzt legen wir eine Textdatei in SPECS an: meinprogramm.specs

Diese Datei schaut dann wie folgt aus:

#Specfile fuer meinprogramm
Summary: Mein Testprogramm
Name: meinprogramm
Version: 1.0
Release: svn
License: GPLv2+
Group: Games/Puzzle
Source: quelle.tar.gz
URL: http://blah
Distribution: openSUSE 11.3
Packager: Hans Wurst <hans@weiss.wurst>

%description
Das ist nur ein testprogramm und hier steht dann eine kurze Beschreibung.

%prep
%setup
%build
make

%install
mkdir -p $RPM_BUILD_ROOT/usr/bin
cp meinprogramm $RPM_BUILD_ROOT/usr/bin/meinprogramm

%files
/usr/bin/meinprogramm

Dieses Specfile lässt sich natürlich dann auch um einen configure Befehl und vieles mehr erweitern, aber wie schon gesagt, nur die Basics.

Nach dem Speichern baut man dann das Paket mittels:

rpmbuild -ba meinprogramm.spec

Wenn alles glatt gelaufen ist findet sich dann das fertige rpm im RPMS Verzeichnis unter dem entsprechenden Ordner der verwendeten Systemarchitektur (x86_64, i386 usw.).

Wo ich hängen geblieben bin war im Bereich $RPM_BUILD_ROOT. Da musste ich erst dahinter kommen, dass das Build Root beim Rumschieben der Dateien ja auch vermerkt werden muss :wink:

cu
Gargi

Das Thema eigene rpm Pakete zu erstellen finde ich sehr interessant.

Hier ein paar nützliche Links:

RPM-build-MINI-HOWTO
Linux RPM HOWTO: RPM-Pakete erstellen
LinuxUser - Das Magazin für die Praxis - LU 07/2003 - Software-Verwaltung mit RPM
Building RPMs
How-To create a RPM | RPM-Based
Packaging software with RPM, Part 1: Building and distributing packages

Wenn du ein rpm baust ist es auch egal, denn du kannst es einfach wieder installieren. Ansonsten /usr/local/bin waere empfohlen fuer selbstkompilierte Sachen. Es mach aber erst wirklich Sinn, wenn /usr/local auf einer separaten Partition liegt, die beim Neuinstallieren nicht formatiert wird. /usr/local/bin sollte auch im Pfad sein.

Nein, auf gar keinen Fall.

In einem openSUSE-konformen RPM hat kein einziges File etwas in /usr/local/ zu suchen, das ist -wie von meinem Vorposter angemerkt- selbstkompiliertem Kram, der nicht über die Paketverwaltung installiert wurde, vorbehalten.

Ich würde sogar so weit gehen, daß man selbstgebastelte Programme ausschließlich nach /usr/local installieren lässt und so eine komplette Trennung einhält, egal ob /usr/local nun eine eigene Partition ist oder nicht, den Sinn dieser Bemerkung verstehe ich eh nicht (von möglicherweise nicht mehr laufenden Binaries nach einem Update des Sytems auch wenn /usr/local “erhalten” geblieben ist mal ganz abgesehen), denn diese Dateien würde ich dann vor einem Update eh genau so wie meine eigenen Dateien oder alle Dateien in /etc (und /etc darf übrigens nie auf einer eigenen Partition liegen) extern sichern.

Würde man seine RPM-Pakete im OBS bauen, dann bin ich mir sicher, daß sich rpmlint heftigst über Dateien in /usr/local beschweren würde (und falls nicht, dann wäre es ein Fehler im System), seit einiger Zeit werden nicht mal mehr Dateien in /opt akzeptiert.

Ah okay, da scheiden sich die Geister. Habe vor einiger Zeit mal fast einen Einlauf verpasst bekommen, als ich Sachen in ein Tutorial nach /usr/bin/ kopiert habe :slight_smile: War aber eine andere Distri. Ne, ist schon klar, über RPM lässt sich das auch entsprechend schön verwalten. Aber wie schon gesagt, das obige Beispiel nur als Klettergerüst :slight_smile:

Aber vielen Dank für die Hinweise, sowas ist unheimlich wertvoll um hier auch etwas über entsprechende Konventionen zu lernen.

Nun ja, sollte dieses “wir kopieren $EXECUTABLE nach /usr/bin” in einem Tutorial vorgekommen sein, wo von Hand installiert wurde, dann war der “Einlauf” auch vollkommen gerechtfertigt

Eigentlich ist es ganz simpel, und AFAIK müssten sich alle großen Distris auch genau daran halten.

Was über die Paketverwaltung installiert wird, hat NIE --prefix=/usr/local sondern --prefix=/usr, was per Dreisatz (oder allgemein “von Hand”) installiert wird, sollte IMMER nach /usr/local installiert werden.

Der Grund ist einfach, man hat nun mal bei “Handarbeit” keinerlei Kontrolle, was da genau installiert wird bzw. es werden auch schon vorhandene Dateien selben Namens beim “make install” ohne Warnung überschrieben, bei RPM ist das ein wenig anders.

Des Weiteren geht das System davon aus, daß der User bei selbstgebautem Kram weiß, was er da tut (OK, diese Annahme ist natürlich gefährlich ;), aber man muss hier eine Entscheidung treffen), denn /usr/local wird bevorzugt aufgerufen, sowohl in $PATH als auch in $LD_LIBRARY_PATH:

Fatboy:~ # useradd dummy -m -d /home/dummy
Fatboy:~ # su - dummy 
dummy@Fatboy:~> echo $PATH 
/home/dummy/bin:**/usr/local/bin:**/usr/bin:/bin:/usr/bin/X11:/usr/X11R6/bin:/usr/games:/opt/kde3/bin:/usr/lib/mit/bin:/usr/lib/mit/sbin:/opt/gnome/bin:/usr/lib/qt3/bin:/opt/real/RealPlayer:/usr/sbin

Damit verhindert man allerdings nicht, daß ein von Hand installiertes Programm andere Anwendungen zerschiesst, denn wie oben bemerkt werden evtl. von diesem “handgemachtem” Programm mitinstallierte Bibliotheken in /usr/local/lib ebenfalls bevorzugt aufgerufen, und wenn z.B. die selbe Bibliothek in anderer Version auch in /usr/lib liegt, kann es vorkommen, daß andere Anwendungen, die ebenfalls gegen diese Bibliothek (aber eben die in /usr/lib!) gelinkt sind auf einmal mit netten “symbol lookup errors” die Grätsche machen.

Der Vorteil ist dann aber, daß man

a) den Kram auch wieder ohne Nachinstallation von Paketen loswerden kann, denn die Bibliothek des Systems wurde nicht überschrieben

b) mit ldd auch sofort sieht, ob eine Bibliothek aus /usr/local/lib aufgerufen wird, hätte man nach /usr/lib installiert, dann wäre das Auffinden der “faulen Eier” deutlich schwerer.

Okay, das habe ich dann soweit verstanden :slight_smile: Was ich beispielsweise gestern bei meinem Programm gemacht habe war alle Files nach /usr/lib/meinprogrann/… installieren zu lassen. Gestartet wird das dann über ein Shellskript, das ich dann nach /usr/bin/ gelegt habe. Ich denke so ist das dann auch am aufgeräumtesten und sieht mir zumindest nach der Datenstruktur her konform aus. Das Programm gibt es bereits als fertiges Paket, allerdings soweit ich sehen kann nicht in der aktuellen svn. Das haut dann soweit hin, dass ich tatsächlich über YAST auch die Versionen (offizielles Paket, mein Kompile) sauber austauschen kann.

Halte ich in Anbetracht dieser Tatsache hier

für suboptimal.

Naja, am saubersten -und auch deutlich einfacher- wäre es in diesem Fall sich das src.rpm des Paketes zu holen und das SPEC auf die neue Version anzupassen. Dann hat man ein “normales” Update und hält mit großer Wahrscheinlichkeit die Paketkonventionen ein (sofern das Paket der Distribution den Paketkonventionen entsprach).

Zum Thema Paketkonventionen

Paketbau/SUSE-Paketkonventionen

Das schwirrt auch als PDF irgendwo herum, Tante G wird da behilflich sein.