Spec
La "ricetta" per la creazione di una pacchetto rpm é un file "spec". Questi file terminano con l'estensione ".spec" e contengono il nome del pacchetto, la versione, il numero di revisione RPM, i passi per costruire, installare, e "pulire" il pacchetto, e un log dei cambiamenti. Molti pacchetti (destinati a diversi sistemi operativi e processori) possono essere costruiti da un singolo file spec, se lo si desidera, e soprattutto se si ha la capacità di crearne uno annidato. I pacchetti rpm vengono creati dai file spec, utilizzando il comando "rpmbuild". Ma vediamo ora come preparare il nostro sistema a pacchettizzare da utente e non do root evitando quindi spiacevoli sorprese, per poi analizzare in dettaglio il file spec.
Indice
Preparare il nostro sistema
Teoricamente un pacchetto per essere compilato necessita di essere costruito con i diritti di root, questa situazione però può provocare errori inattesi..una errata configurazione del file spec infatti può portare all'installazione del pacchetto, che se compilato erroneamente potrebbe alterare la stabilità del sistema. Vediamo quindi come rendere possibile la compilazione da utente evitando quindi ogni tipo di problema.
Di default gli rpm vengono pacchettizzati in /usr/src/packages/ oppure in /usr/src/rpms/ in base alle distro, il nostro obbiettivo è quello di ricreare la struttura di queste cartelle nella nostra home!
La struttura che vogliamo ricreare è la seguente:
/usr/src/packages/RPMS/noarch (In questa cartella vengono creati pacchetti multi-archittettura) /usr/src/packages/RPMS/i586 (In questa cartella vengono creati pacchetti con architettura i586) /usr/src/packages/RPMS/i686 (In questa cartella vengono creati pacchetti con architettura i686) /usr/src/packages/RPMS/i486 (In questa cartella vengono creati pacchetti con architettura i486) /usr/src/packages/RPMS/i386 (In questa cartella vengono creati pacchetti con architettura i386) /usr/src/packages/RPMS/athlon (In questa cartella vengono creati pacchetti con architettura athlon) /usr/src/packages/BUILD (In questa cartella vengono decompressi ed elaborati i sorgenti) /usr/src/packages/SRPMS (In questa cartella vengono creati gli rpm dei sorgenti, con estensione .src.rpm) /usr/src/packages/SOURCES (In questa cartella vengono "depositati" i sorgenti da elaborare) /usr/src/packages/SPECS (In questa cartella vengono "depositati" i file spec) /usr/src/tmp (se esiste, è la cartella in cui si salvano temporaneamente i file prima di essere pacchettizzati, in altri casi si usa la cartella /tmp)
Ora che abbiamo preso conoscenza di quello con cui andremo a lavorare, apriamo una shell e digitiamo da utente e NON DA ROOT quanto segue: (poichè tutti i comandi andranno digitati da utente non verrà utilizzata la convenzione dei segni, $ utente, # root).
cd ~ mkdir -p src/rpm/RPMS/i386 mkdir -p src/rpm/RPMS/i486 mkdir -p src/rpm/RPMS/i586 mkdir -p src/rpm/RPMS/i686 mkdir -p src/rpm/RPMS/noarch mkdir -p src/rpm/RPMS/athlon mkdir -p src/rpm/SRPMS mkdir -p src/rpm/SOURCES mkdir -p src/rpm/BUILD mkdir -p src/tmp
Adesso bisognerà creare nella nostra home 2 file di testo conteneti alcune configurazioni. Il primo chiamato .rpmrc il secondo .rpmmacros. Ricordatevi il punto (.) in quanto i file saranno nascosti.
Nel primo (.rpmrc) incolliamo questo testo:
buildarchtranslate: i386: i586 buildarchtranslate: i486: i586 buildarchtranslate: i586: i586 buildarchtranslate: i686: i586
Questo file è necessario inquanto la maggior parte delle distro utilizzano solamente architettura i586, ed alcuni prorammatori potrebbero aver creato il file spec per architetture differenti.
Nel secondo file (.rpmmacros), invece scriviamo quanto segue:
%_topdir /home/anubis/src/rpm %_tmppath /home/anubis/src/tmp %distribution SUSE %vendor SUSE %distsuffix anubisg1
ovviamente modificando alle prime 2 righe /home/anubis con la vostra home (/home/nome_utente); in %distribution e %vendor sostituite SUSE con il nome della vostra distribuzione, nel mio è openSUSE, in %distsuffix dovrete sostituire anubisg1 con il vostro nick, o comunque con un suffisso che serva ad identificare univocamente i vostri pacchetti.
Il nostro computer ora è pronto, procuriamoci un file spec e analizziamolo in dettaglio.
Ottenere il primo file spec da studiare
Poichè per ora non abbiamo la minima idea di cosa sia, e di come sia strutturato un file spec, abbiamo la necessità di procurcene uno già preparato, magari con il codice sorgente a cui si riferisce, per poterlo magari usare e creare il nostro primo pacchetto. Per fare ciò dobbiamo scaricare un file di estensione .src.rpm, questo rpm contiene al suo interno solamente il codice sorgente (con relative patch, se esistenti) e il file spec necessario a compilarlo. in questo esempio utilizzeremo il file amsn-0.97RC1-9.1.src.rpm che scaricheremo direttamente dal mio repository.
Una volta scaricato sul Desktop, per esempio, provvediamo ad installarlo. (ricordate di NON eseguire nessun comando come root)
rpm -ivh /home/nome_utente/Desktop/amsn-0.97RC1-9.1.src.rpm
se avrete eseguito il comando da utente normale, (non mi scoccierò mai di ricordarvelo), troverete questi file installati nel vostro sistema
/home/anubis/src/rpm/SOURCES/amsn-0.97RC1.tar.bz2 (ovvero il codice sorgente di amsn) /home/anubis/src/rpm/SPECS/amsn.spec (il file spec che tanto sogniamo!)
ottenuti questi due file apriamo il file amsn.spec ed analizziamolo: (per quanto possibile cercherò di mantenere la stessa formattazione, colori compresi, che si ottiene aprendo il file con KWrite)
Name: amsn Version: 0.97RC1 Release: 9.1 License: GPL BuildRoot:%{_tmppath}/amsn-0.97RC1-build Requires: tcl >= 8.4 Requires: tk >= 8.4 BuildRequires: glibc-devel make autoconf automake libtool gcc gcc-c++ BuildRequires: libjpeg-devel libpng-devel xorg-x11-devel BuildRequires: tcl tk tcl-devel tk-devel BuildRequires: update-desktop-files %if %suse_version >= 1021 BuildRequires: gcc41-c++ %endif Group: Productivity/Networking/AOLInstantMessenger Packager: Andrea Florio <andreafl@libero.it> Summary: MSN Messenger clone for Linux URL: http://www.amsn-project.net/ Source: amsn-0.97RC1.tar.bz2 Conflicts: amsnSVN %description This is the last STABLE VERSION This is Tcl/Tk clone that implements the Microsoft Messenger (MSN) for Unix,Windows, or Macintosh platforms. It supports file transfers, groups, and many more features. Visit http://amsn-project.net/ for details. This is an ongoing project, and it is already going pretty well. %prep %setup -q %build %configure --prefix=/usr %install rpm -fr $RPM_BUILD_ROOT make DESTDIR=$RPM_BUILD_ROOT install %suse_update_desktop_file -r amsn Productivity/Networking/AOLInstantMessenger %clean rm -rf "$RPM_BUILD_ROOT" %files %defattr(-,root,root) %{_bindir}/* %{_datadir}/amsn/* %{_datadir}/pixmaps/amsn.png %{_datadir}/applications/amsn.desktop
Sezione Sommario
la sezione sommario è il primo blocco di istruzioni presente nel file spec:
Name: amsn Version: 0.97RC1 Release: 9.1 License: GPL BuildRoot:%{_tmppath}/amsn-0.97RC1-build Requires: tcl >= 8.4 Requires: tk >= 8.4 BuildRequires: glibc-devel make autoconf automake libtool gcc gcc-c++ BuildRequires: libjpeg-devel libpng-devel xorg-x11-devel BuildRequires: tcl tk tcl-devel tk-devel BuildRequires: update-desktop-files %if %suse_version >= 1021 BuildRequires: gcc41-c++ %endif Group: Productivity/Networking/AOLInstantMessenger Packager: Andrea Florio <andreafl@libero.it> Summary: MSN Messenger clone for Linux URL: http://www.amsn-project.net/ Source: amsn-0.97RC1.tar.bz2 Conflicts: amsnSVN
Quesa parte non è difficile da capire, vengono infatti elencate le caratteristiche principali del pacchetto:
- Name: - il nome
- Version: - la versione
- Release: - il "rilascio"
- License: - la licenza con cui viene distribuito
- BuildRoot - è la cartella dove vengono elaborati in file temporanei, precedentemente l'abbiamo definita nel file .rpmmacros, più esattamente abbiamo definito la %{_tmppath}.
- Requires - indica le dipendenze necessarie a far "funzionare" il programma, mentre BuildRequires indica le dipendenze necessarie alla compilazione del pacchetto; in entrambi i casi si potrebbero scrivere tutte le dipendenze in un'unica riga, divise da uno spazio, ma si preferisce solitamente dividerle (vedi le due righe utilizzate per Requires) in caso di dipendenze particolarmente importanti che necessitano di essere visualizzate immediatamente.
- Group - indica il gruppo di apparteneza del pacchetto, grazie a questo, se esiste, viene posizionata l'icona del programma nel vostro menù
- Packager: - è chi pacchettizza il programma
- Summary: - una breve descrizione del programma
- URL: - è il sito di riferimento del programma
- Source: - è il nome del codice sorgente
- Conflicts: - è una lista di pacchetti con il quale il nostro, eventualmente può entrare in conflitto
Solo una parte richiede una spiegazione più approfondita:
%if %suse_version >= 1021 BuildRequires: gcc41-c++ %endif
Questo pezzo infatti e un "condizionale", la base per creare spec annidati per varie distribuzioni. In questo caso viene "comandato":
Se (%if) la versione di suse (%suse_version) è maggiore o uguale alla 10.2 (>= 1021) allora un BuildRequires aggiuntivo è il pacchetto gcc41-c++. La fine del comando è dato da endif (fine-se).
Le Macro
Per una definizione approfondita del termine macro in informatica rimando a questo link.
Sostanzialmente però, le macro permettono di definire tramite una singola "parola" un'intera funzione, o un percorso, o qualunque altra cosa noi vogliamo. Ciò serve per non riscrivere ogni volta una stringa più o meno lunga, basterà infatti inserire la macro precedentemente definita.
Le Macro presenti nel nostro file spec
Nel file spec che stiamo utilizzando sono presenti solamente tre macro.
- %{_tmppath}
- %{_bindir}
- %{_datadir}
Queste 3 non sono state definite nel file spec, vediamo ora il perchè e a cosa si riferiscono:
la prima:
- %{_tmppath}
è stata definita precedentemente nel file .rpmmacros:
%_tmppath /home/anubis/src/tmp
ciò vuol dire che la stringa
BuildRoot: %{_tmppath}/amsn-0.97RC1-build
è identica a
BuildRoot: /home/anubis/src/tmp/amsn-0.97RC1-build
La seconda e la terza invece:
- %{_bindir}
- %{_datadir}
sono alcune delle macro standard predefinite di rpm. Ecco alcune di queste macro predefinite:
%{_bindir} /usr/bin %{_datadir} /usr/share %{_libdir} /usr/lib %{_sysconfdir} /etc %{_mandir} /usr/share/man %{_docdir} /usr/share/doc %{_iconsdir} /usr/share/icons
Altre Macro standard
Oltre alle precedenti tre importantissime macro standard quasi sempre utilizzate sono le seguenti:
- %{name}
- %{version}
- %{release}
queste tre vengono definite automaticamente all'inzio del file spec, indicano infatti il nome, la versione e la release del nostro pacchetto; praticamente le prime tre righe dello spec. Vediamo come sono comunemente utilizzate, servendoci della stringa:
BuildRoot: %{_tmppath}/amsn-0.97RC1-build
Questa infatti potrebbe essere sostituita con questa:
BuildRoot: %{_tmppath}/%{name}-%{version}-build
analogamente questa:
Source: amsn-0.97RC1.tar.bz2
può essere sostituita con questa:
Source: %{name}-%{version}.tar.bz2
anche se a prima vista sembra meno conveniente utilizzare le macro, andiamo infatti a scrivere una stringa più lunga, l'utilità delle macro appare evidente quando vogliamo aggiornare un pacchetto; Se il programma non è stato modificato radicalmente (non abbiamo ciò necessità di rifare il file spec) ci basterà modificare solo le prime righe e non tutto il file, con il rischio di dimenticare qualcosa.
Definire Macro personalizzate
Definire delle macro personalizzate è semplicissimo, basta seguire questo schema:
%define nome_macro valore_macro
ecco un esempio:
%define xorg /etc/X11
quando vorremo utilizzare questa macro ci basterà digitare %{xorg}
Sezione Descrizione e "Build"
Questa parte può essere definita come il "cuore" del file spec, è qui che si dice come il nostro pacchetto deve essere compilato.
%description This is the last STABLE VERSION This is Tcl/Tk clone that implements the Microsoft Messenger (MSN) for Unix,Windows, or Macintosh platforms. It supports file transfers, groups, and many more features. Visit http://amsn-project.net/ for details. This is an ongoing project, and it is already going pretty well. %prep %setup -q %build %configure --prefix=/usr %install rpm -fr $RPM_BUILD_ROOT make DESTDIR=$RPM_BUILD_ROOT install %suse_update_desktop_file -r amsn Productivity/Networking/AOLInstantMessenger %clean rm -rf "$RPM_BUILD_ROOT"
esaminiamo ora il tutto nel dettaglio:
- %description - Qui va scritta la descrizione del pacchetto con tutte le informazioni necessarie. Questa parte verrà visualizzata all'interno del nostro Gestore di pacchetti.
- %prep - Con questo comando si prepara l'ambiente di compilazione.
- %setup -q - Grazie a questa direttiva viene decompresso l'archivio del codice sorgente, è possibile aggiungere l'opzione -n nome_cartella, cioè l'equivalente di cd nome_cartella. Ci si sposta nella cartella indicata, necessario nel caso in cui la cartella in cui si trovano in sorgenti abbia un nome diverso dell'archivio.
- %build - Con questo comando inizia la compilazione.
- %configure - il corrispondente di ./configure,mentre --prefix=/usr è una delle opzioni del "configure"
%install rpm -fr $RPM_BUILD_ROOT make DESTDIR=$RPM_BUILD_ROOT install
Con questi comandi diamo avvio al make ed al make install. Bisogna notare che $RPM_BUILD_ROOT è un macro, infatti sostituisce interamente la stringa
BuildRoot:%{_tmppath}/%{name}-%{version}-build
- %suse_update_desktop_file - Questo comando, insieme alle relative opzioni, è supportato solo se è installato il pacchetto update-desktop-files, questo pacchetto
- %clean - Grazie al clean si pulisce la cartella temporanea. La stringa rm -rf "$RPM_BUILD_ROOT" cancella la cartella temporanea.
Sezione Files
Una volta che abbiamo "installato" il nostro pacchetto dobbiamo dare le indicazioni per inserire nel nostro rpm i file che abbiamo "creato". Queste direttive vengona date dalla sezione files del nostro file spec.
%files %defattr(-,root,root) %{_bindir}/* %{_datadir}/amsn/* %{_datadir}/pixmaps/amsn.png %{_datadir}/applications/amsn.desktop
- %files - Questo è il comando per aprire la sezione files.
- %defattr (-,root,root) - Qui si impostano i diritti dei file, possono essere inseriti i permessi di chmod, ma sotto forma di "terna numerica", ovvero utilizzando la forma "ottale"
%{_bindir}/* %{_datadir}/amsn/* %{_datadir}/pixmaps/amsn.png %{_datadir}/applications/amsn.desktop
Questa è la lista dei file insieme al loro percorso di destinazione, da notare l'utilizzo delle macro.
Ora abbiamo finito di analizzare il nostro file spec. Vediamo quindi come creare finalmente il nostro rpm partendo dal codice sorgente e dal file spec
Ovviamente il discorso è molto più amplio e complicato.. non mi certo possibile srcivere tutto qui, sarebbe necessario scrivere un libro, e non ho nemmeno tutte le conoscenze necessarie, ma adesso avete una idea di come si comporti il file spec.
Creare il nostro primo rpm
Una volta creato il file spec e il codice sorgente del programma che vogliamo pacchettizzare, la creazione dell'rpm è molto semplice.
Per prima cosa spostare il sorgente all'interno della cartella /home/nome_utente/src/rpm/SOURCES/ (come detto precedentemente se abbiamo installato il pacchetto .src.rpm i file necessari si troveranno già al loro posto).
Successivamente dobbiamo spostarci nella cartella in cui è presente il file spec e quindi digitare:
rpmbuild -ba nome_programma.spec
nel caso del pacchetto che abbiamo esaminato fino ad ora:
cd /home/anubis/src/rpm/SPECS/ rpmbuild -ba amsn.spec
se tutto è andato a buon fine otterremo un output di questo tipo:
Wrote: /home/anubis/src/rpm/SRPMS/amsn-0.97RC1-9.1.src.rpm Wrote: /home/anubis/src/rpm/RPMS/i586/amsn-0.97RC1-9.1.i586.rpm Executing(%clean): /bin/sh -e /var/tmp/rpm-tmp.85100 + umask 022 + cd /usr/src/packages/BUILD + cd amsn-0.97RC1 + rm -rf /var/tmp/amsn-0.97RC1-build + exit 0
Ci viene indicato dove sono stati creati gli rpm (sia del programma che del sorgente). L'operazione andata a buon fine termina con un + exit 0
Ora non vi resta altro che testare il vostro nuovo pacchetto!
Andrea Florio Anubisg1