I computer sono inutili, possono dare solo risposte.

— Pablo Picasso

RPM: Patch e rebuild di un package

http://www.stenoweb.it/files/blog/rpm.jpg Avete mai pensato di creare o più semplicemente (si fà per dire...) applicare una patch ad un pacchetto RPM ? No ? Allora non continuate a leggere ;)
Per gli altri ecco come creare un patchfile delle vostre modifiche e come applicarle durante la creazione del pacchetto RPM usando rpmbuild.

Preparazione

Di default in una distro basata su RedHat (Fedora, CentOS, ...) viene usata la directory /usr/src/redhat come destinazione nella creazione dei pacchetti RPM. Non che non si possa ignorare il problema ma per evitare le compilazioni come superutente è probabilmente (anzi consigliato) più opportuno piazzare questa nella home del nostro utente. In questo modo, dirottando appunto tutto il processo su cartelle nella nostra home, possiamo lanciare e portare a termine il processo di compilazione/creazione evitando sia di autenticarci come root che errori tipo "permission denied".
La "location"" viene definita nella macro %_topdir che possiamo cambiare editando il file ~/.rpmmacros:

nano ~/.rpmmacros

inserendo, ad esempio :
# Path build area
%_topdir /home/steno/rpmbuild

così /home/steno/rpmbuild ora è la "root" di compilazione per l'utente "steno".

Ora però dobbiamo anche creare la struttura necessaria :

mkdir ~/rpmbuild
cd ~/rpmbuild
mkdir BUILD RPMS SOURCES SPECS SRPMS
mkdir RPMS/i{3,4,5,6}86 RPMS/noarch RPMS/athlon

Il processo di creazione e compilazione RPM non è semplicissimo da capire, e di sicuro non sono certo io che posso insegnarlo a qualcuno. Basti sapere le cose basilari tipo a che cosa servono queste cartelle che abbiamo creato:

  1. BUILD : qui verranno estratti e compilati i sorgenti ed è più o meno una cartella temporanea che serve solo durante questo processo.
  2. SOURCES : contiene i tarballs dei sorgenti, le patch e i file aggiuntivi che vengono estratti dai pacchetti SRPM (sorgenti RPM) che eventualmente installiamo e che vengono poi inclusi nel pacchetto RPM che creiamo.
  3. RPMS e SRPMS : sono le directory dove viene messo il pacchetto pronto dopo la compilazione. RPMS contiene, poi, una directory per ogni architettura supportata, ad esempio i686 per i pacchetti specifici.
  4. SPECS : in questa cartella viene posto lo specfile del pacchetto. Altro non è che un file di testo in cui, con una precisa sintassi, viene ad esempio inserita la descrizione del pacchetto, le dipendenze ecc.. Attenzione che ogni volta che viene installato il pacchetto sorgente questo file viene sovrascritto, quindi occhio a salvare le proprie modifiche ...

Creazione di un RPM dal suo SRPM

Se vogliamo ricreare un pacchetto senza apportare alcuna modifica non è nemmeno necessario installare il corrispondente pacchetto sorgente SRPM ma possiamo usarlo direttamente digitando :

rpmbuild --rebuild pacchetto-1.0.src.rpm

Ma cosa serve ricompilare in questo caso ? Bè, ad esempio supponiamo di volere la versione specifica per una architettura del nostro pacchetto preferito:
rpmbuild --rebuild --target i686 pacchetto-1.0.src.rpm

In questo modo con il parametro --target i686 in /home/steno/rpmbuild/RPMS/i686 ci sarà pacchetto-1.0-i686.rpm bello ottimizzato per l'architettura i686.

Installazione di un SRPM

Se invece qualche modifica la dobbiamo fare allora dobbiamo installare i pacchetto sorgente:

rpm -ivh pacchetto-1.0.src.rpm

Dopo questa operazione in /home/steno/rpmbuild/SPECS ci sarà in nostro pacchetto.specs e in /home/steno/rpmbuild/SOURCES il tar.gz con il sorgente, le varie patch e file aggiuntivi necessari.

Modifica dei flags "configure"

Se abbiamo bisogno di modificare i flag di configurazione per la successiva compilazione non c'e' bisogno di metter mano al sorgente: basta agire sullo spec file nella sezione %configure in cui in modo abbbastanza evidente vediamo cosa dobbiamo fare ;)

Patching del sorgente

Siccome rpmbuild elimina i file estratti ripartendo da zero quando crea il pacchetto è meglio fare il nostro lavoro su una copia dei sorgenti dandogli un nome differente. Ad esempio se estraendo il nostro pacchetto-1.0.tar.gz viene creata una directory pacchetto-1.0, facciamone una copia chiamata pacchetto-1.0p e applichiamo qui le nostre modifiche.

In seguito, per creare una patch che contiene le nostre personalizzazioni andiamo nella direcory BUILD e usiamo il comando diff per creare il nostro patchfile nella cartella SOURCES. Siccome potrebbero esserci altri file di questo genere diamo un nome univoco al nostro magari specificando anche la natura della patch.
Usiamo diff con il parametro "-u" per ottenere un formato standard per le patches, "-N" per includere eventuali nuovi file da noi creati nella patch e "-r" per operare ricorsivamente nelle cartelle dei sorgenti :

diff -uNr pacchetto-1.0/ pacchetto-1.0p/ > ../SOURCES/pacchetto-1.0-my.patch

Le prime righe nel patchfile pacchetto-1.0-my.patch dovrebbbero contenere qualcosa del tipo :
--- pacchetto-1.0/file Sun Sep 14 16:24:49 2008
+++ pacchetto-1.0p/file Thu Sep 18 01:24:17 2008

Pronto all'uso.

Applicare la patch al pacchetto

Ora dobbiamo istruire rpmbuild affinchè applichi la nostra patch al pacchetto risultante. Per fare questo ritorniamo al nostro specfile:

nano /home/steno/rpmbuild/SPECS/pacchetto.spec

Le patch vengono applicate in sequenza. Supponiamo di voler applicata la nostra per prima, in questo caso aggiungiamo nel file dopo la sezione Source0, Source1, ...:
Patch0: pacchetto-1.0-my.patch

e più sotto, i comandi per applicare la patch tipicamente tra la sezione %setup e %build:
%setup ...
%patch0 -p1
%build ...

Attenzione alle altre eventuali patch presenti (patch1, patch2 ...): diamo alla nostra un numero univoco e assicuriamoci che le nostre personalizzazioni non interferiscano con le altre ...

Rebuild del pacchetto

Ora siamo pronti, possiamo ricreare il pacchetto con le nostre personalizzazioni:

rpmbuild -ba SPECS/pacchetto.spec

rpmbuild applica le patch, configura e compila il sorgente, crea il binario RPM in RPMS/ e il pacchetto SRPM in SRPMS contenente il sorgente originale, le patch e un nuovo specfile, così il pacchetto potrà essere ricompilato con le nostre modifiche anche da altri.
Usando "-bb" verrà invece ricreato il sono binario RPM, come di contro usando "-bs"" solo il pacchetto sorgente SRPM.

Un modo più semplice ?

A parte che rileggendo questo post mi rendo conto che non ci si capisce una benemerita fava, ma porcaccia miseria, tutto stò casino per una patch ?

Bè se vogliamo che la nostra patch possa essere applicata e compilata anche da altri e se vogliamo un pacchetto RPM non c'e' molta scelta.

Forse possiamo saltare qualche piccolo passaggio ma in linea di massima il procedimento pare proprio essere questo.

Altrimenti c'e' sempre la tripletta :

./configure
make
make install

Ma questo con gli RPM non c'entra una mazza...

forse questo può aiutare:

http://www.linuxpedia.netsons.org/index.php/Guida_alla_creazione_di_file...

e la tua conoscenza potrebbe essere utile a migliorare le mie guide che dici?

Grande!!!

E grazie pure ad Anubi per la segnalazione della sua guida.

//@anubis//
Uh ! Tra l'altro ho visto che hai un articolo molto simile a questo :D

Complimenti per il progetto, un wiki molto "impegnativo".
Ma in un blog mi sento più libero di sparare magari inconsapevoli "boiate" ;)

Se ti fà piacere e ti sembra utile attingi pure ai contenuti di questo blog.
La guida server di archlinux, ad esempio, l'ho già "duplicata" in parte io sul wiki ufficiale.

http://wiki.archlinux.org/index.php/ArchLinux_Small_Business_Server_(SBS)

Ciao.

Ciao,
sono giunto al tuo blog perchè sto cercando di capire come fare un pacchetto rpm in maniera più corretta possibile,
fin'ora ne ho fatto uno che semplicemente prende tutta una serie di files compilati e li va a mettere in determinate cartelle..
quello che adesso dovrei fare è invece prendere il codice sorgente compilarlo e fare tutto il resto,
non ho idea di come potere fare questa cosa, so solo che il codice è scritto in java ma non l'ho sviluppato io..
mi potresti dare qualche dritta?
ho visto che si fanno riferimento a makefile, o configure files.. cose che io nn ho.. dovrei costruirli?? nn saprei da dove iniziare..
grazie per un tuo eventuale aiuto..
ciao