Capitolo 3. Modificare i sorgenti

Indice

3.1. Configurare quilt
3.2. Correggere i bug nel sorgente originale
3.3. Installazione dei file nei loro percorsi
3.4. Distinguere le librerie

È disponibile la riscrittura di questo tutorial, con contenuti aggiornati e con esempi più pratici, denominato Guide for Debian Maintainers. Si prega di utilizzare il nuovo tutorial come documento primario.

Non c'è spazio qui per approfondire tutti i dettagli su come modificare i sorgenti originali, ma verranno trattati alcuni passaggi fondamentali e le problematiche più comuni.

Il programma quilt offre un metodo semplice per registrare le modifiche dei sorgenti originali per la pacchettizzazione Debian. È comodo averlo leggermente personalizzato per la pacchettizzazione Debian, utilizzando l'alias dquilt, aggiungendo le seguenti linee al file ~/.bashrc. La seconda riga fornisce la stessa funzionalità di shell completion del comando quilt al comando dquilt:

alias dquilt="quilt --quiltrc=${HOME}/.quiltrc-dpkg"
. /usr/share/bash-completion/completions/quilt
complete -F _quilt_completion -o filenames dquilt

Si crei il file ~/.quiltrc-dpkg come segue:

d=. ; while [ ! -d $d/debian -a $(readlink -e $d) != / ]; do d=$d/..; done
if [ -d $d/debian ] && [ -z $QUILT_PATCHES ]; then
    # if in Debian packaging tree with unset $QUILT_PATCHES
    QUILT_PATCHES="debian/patches"
    QUILT_PATCH_OPTS="--reject-format=unified"
    QUILT_DIFF_ARGS="-p ab --no-timestamps --no-index --color=auto"
    QUILT_REFRESH_ARGS="-p ab --no-timestamps --no-index"
    QUILT_COLORS="diff_hdr=1;32:diff_add=1;34:diff_rem=1;31:diff_hunk=1;33:diff_ctx=35:diff_cctx=33"
    if ! [ -d $d/debian/patches ]; then mkdir $d/debian/patches; fi
fi

Per l'utilizzo di quilt si veda quilt(1) e /usr/share/doc/quilt/quilt.pdf.gz.

Si supponga di trovare un errore, nel file Makefile distribuito con il programma originale, ad esempio la stringa install: gentoo avrebbe dovuto essere install: gentoo-target.

install: gentoo
        install ./gentoo $(BIN)
        install icons/* $(ICONS)
        install gentoorc-example $(HOME)/.gentoorc

Si può correggere questo errore e registrarlo, con il comando dquilt utilizzando come file fix-gentoo-target.patch: [22]

$ mkdir debian/patches
$ dquilt new fix-gentoo-target.patch
$ dquilt add Makefile

Si modifichi il file Makefile come segue:

install: gentoo-target
        install ./gentoo $(BIN)
        install icons/* $(ICONS)
        install gentoorc-example $(HOME)/.gentoorc

Adesso bisogna chiedere a dquilt di generare la patch debian/patches/fix-gentoo-target.patch e di aggiungere una descrizione conforme a DEP-3: Patch Tagging Guidelines:

$ dquilt refresh
$ dquilt header -e
... describe patch

La maggiorparte dei programmi di terze parti si auto-installano in sottodirectory di /usr/local. I pacchetti Debian invece non devono usare quella directory, dal momento che è riservata agli amministratori (o utenti) del sistema per uso privato, ma dovrebbero usare le directory di sistema come la sottodirectory /usr/bin, conformi allo Standard di Gerarchia dei Filesystem (FHS, /usr/share/doc/debian-policy/fhs/fhs-2.3.html).

Normalmente, make(1) è usato per costruire automaticamente il programma, invece l'esecuzione di make install installa il programma direttamente nella destinazione prestabilita (configurata nella sezione install nel file Makefile). Per far in modo che Debian fornisca dei pacchetti installabili pre-compilati, viene modificato il sistema di compilazione in modo da installare i programmi in un'immagine dell'albero dei file, creata dentro una directory temporanea, anziché nella destinazione prestabilita.

Le 2 differenze tra la normale installazione di un programma e l'installazione tramite il sistema di pacchettizzazione Debian può essere affrontato in modo trasparente dal pacchetto debhelper, attraverso i comandi dh_auto_configure e dh_auto_install, se le seguenti condizioni sono soddisfatte:

  • Il file Makefile deve seguire le convenzioni GNU e supportare la variabile $(DESTDIR). [23]

  • Il sorgente deve essere conforme allo Standard di Gerarchia dei Filesystem (FHS).

I programmi che usano GNU autoconf sono automaticamente conformi alle convenzioni GNU e la loro pacchettizzazione può essere molto semplice. Con questi ed altri accorgimenti, si stima che il pacchetto debhelper funzioni su quasi il 90% dei pacchetti senza apportare pesanti modifiche al loro sistema di compilazione. La pacchettizzazione non è così complicata come potrebbe sembrare.

Se è necessario apportare delle modifiche al Makefile, si dovrebbe fare attenzione a supportare la variabile $(DESTDIR). Anche se non è impostata di default, la variabile $(DESTDIR) viene anteposta ad ogni percorso usato per l'installazione del programma. Lo script di pacchettizzazione imposta la variabile $(DESTDIR) nella directory temporanea.

Per il pacchetto sorgente che genera un singolo pacchetto binario, la directory temporanea, utilizzata dal comando dh_auto_install, è debian/pacchetto. [24] Tutto quello contenuto nella directory temporanea verrà installato sul sistema dell'utente, appena si installa il pacchetto, l'unica differenza è che dpkg installerà i file nella radice del file system anzichè nella directory di lavoro.

Bisogna tenere in considerazione che, anche se il programma viene installato in debian/pacchetto, deve comunque potersi installare nella directory radice dal pacchetto .deb. Per questo motivo non bisogna consentire al sistema di compilazione di utilizzare stringhe impostate manualmente come costanti, ad esempio /home/me/deb/pacchetto-versione/usr/share/pacchetto nei file del pacchetto.

Questa è la parte più importante del Makefile del pacchetto gentoo [25]:

# Where to put executable commands on 'make install'?
BIN     = /usr/local/bin
# Where to put icons on 'make install'?
ICONS   = /usr/local/share/gentoo

Da notare che i file verranno installati in /usr/local. Come descritto sopra, questa directory, in Debian, è riservata per l'utilizzo locale, si modifichino questi percorsi con:

# Where to put executable commands on 'make install'?
BIN     = $(DESTDIR)/usr/bin
# Where to put icons on 'make install'?
ICONS   = $(DESTDIR)/usr/share/gentoo

Le posizioni che dovrebbero essere usate per i binari, le icone, la documentazione, ecc. sono specificate nella Gerarchia dei Filesystem (FHS). Si consiglia di sfogliarlo e leggere le sezioni riguardanti il pacchetto interessato.

Si dovrà installare, quindi, il file eseguibile in /usr/bin anziché in /usr/local/bin, la pagina di manuale in /usr/share/man/man1 anziché /usr/local/man/man1, ecc. Da notare che nel Makefile del pacchetto gentoo non è presente una pagina di manuale, ma dal momento che la policy di Debian prevede che ogni programma ne abbia una, ne verrà creata una e sarà installata in /usr/share/man/man1.

Alcuni programmi non usano le variabili nel Makefile per definire dei percorsi come questi. Questo indica che potrebbe essere necessario modificare qualche sorgente in C, per fargli usare il percorso giusto. Ma dove cercarlo, e per farci cosa? Lo si può scoprire eseguendo questo:

$ grep -nr --include='*.[c|h]' -e 'usr/local/lib' .

grep cercherà tutte le corrispondenze in maniera ricorsiva attraverso tutto l'albero dei sorgenti, indicando il nome del file e il numero della riga.

Si modifichino quei file in quelle righe, sostituendo usr/local/lib con /usr/lib. Questo può essere fatto automaticamente, come mostrato di seguito:

$ sed -i -e 's#usr/local/lib#usr/lib#g' \
        $(find . -type f -name '*.[c|h]')

Se invece si vuole dare la conferma per ogni sostituzione, si può utilizzare il seguente comando:

$ vim '+argdo %s#usr/local/lib#usr/lib#gce|update' +q \
        $(find . -type f -name '*.[c|h]')

A questo punto si dovrebbe trovare il target install (si cerchi la riga che inizia con install:, di solito è quella corretta) e modificare tutti i riferimenti alle directory diverse da quelle definite nel Makefile.

Originariamente, il target del pacchetto gentoo riporterà:

install: gentoo-target
        install ./gentoo $(BIN)
        install icons/* $(ICONS)
        install gentoorc-example $(HOME)/.gentoorc

Si può correggere e registrare la modifica con il comando dquilt salvandola come debian/patches/install.patch.

$ dquilt new install.patch
$ dquilt add Makefile

Per il pacchetto debian si modifichi come segue, utilizzando un editor:

install: gentoo-target
        install -d $(BIN) $(ICONS) $(DESTDIR)/etc
        install ./gentoo $(BIN)
        install -m644 icons/* $(ICONS)
        install -m644 gentoorc-example $(DESTDIR)/etc/gentoorc

Si sarà fatto caso che adesso c'è un comando install -d prima degli altri, nella regola. Il Makefile originale non ce l'ha perché generalmente usa /usr/local/bin e altre directory che già esistono nel sistema su cui si esegue make install. Tuttavia, dal momento che verrà installato nella nostra directory vuota (o anche inesistente), si dovrà creare ogni singola directory.

È possibile anche aggiungere altre cose alla fine della regola, come l'installazione di documentazione aggiuntiva che gli autori originali talvolta omettono:

        install -d $(DESTDIR)/usr/share/doc/gentoo/html
        cp -a docs/* $(DESTDIR)/usr/share/doc/gentoo/html

Dopo un'attenta analisi, se tutto è andato bene, si può generare con dquilt la patch che crea il file debian/patches/install.patch ed aggiungendogli una descrizione:

$ dquilt refresh
$ dquilt header -e
... describe patch

Adesso si avranno una serie di patch.

  1. Correzione del bug riguardante il sorgente originale: debian/patches/fix-gentoo-target.patch

  2. Modifica specifica per il sistema di pacchettizzazione Debian: debian/patches/install.patch

Ogni volta che si apportano delle modifiche che non sono specificatamente legate alla pacchettizzazione Debian, come debian/patches/fix-gentoo-target.patch, bisogna assicurarsi di inviare le modifiche al manutentore originale, in modo che possano essere incluse nella prossima versione del programma e possano beneficiarne altri utenti. Ci si ricordi, di creare delle correzioni portabili, ovvero di non renderle specifiche per Debian o Linux — o altri Unix!. Questo renderà più semplice applicare le correzioni.

Da notare che non è necessario inviare i file debian/* all'autore originale.

C'è un altro problema comune: le librerie sono spesso diverse da piattaforma a piattaforma. Per esempio, il Makefile può contenere un riferimento a una libreria che non esiste nei sistemi Debian. In tal caso occorre cambiare il riferimento ad una libreria che serve allo stesso scopo e che esista in Debian.

Supponiamo che una riga nel Makefile del programma (o nel Makefile.in) che riporta qualcosa come segue.

LIBS = -lfoo -lbar

Se il programma non viene compilato perché la libreria foo non esiste e il suo equivalente, su un sistema Debian, è fornito dalla libreria foo2, è possibile risolvere questo problema di compilazione, modificando il file debian/patches/foo2.patch cambiando foo con foo2: [26]

$ dquilt new foo2.patch
$ dquilt add Makefile
$ sed -i -e 's/-lfoo/-lfoo2/g' Makefile
$ dquilt refresh
$ dquilt header -e
... describe patch


[22] La directory debian/patches dovrebbe essere stata creata se si è eseguito dh_make, come descritto prima. Questo esempio crea la directory nel caso in cui si stia aggiornando un pacchetto esistente.

[24] Per il pacchetto sorgente che genera pacchetti binari multipli, il comando dh_auto_install utilizza la directory temporanea debian/tmp, mentre il comando dh_install, con l'aiuto dei file debian/pacchetto-1.install e debian/pacchetto-2.install suddivide il contenuto di debian/tmp nelle directory temporanee debian/pacchetto-1 e debian/pacchetto-2 per creare pacchetti binari pacchetto-1_*.deb e pacchetto-2_*.deb.

[25] Questo è solo un esempio che mostra come un Makefile dovrebbe apparire. Se il Makefile è creato dal comando ./configure, il modo giusto per correggere il Makefile è eseguire il comando ./configure dal comando dh_auto_configure includendo come opzione predefinita --prefix=/usr.

[26] Se ci sono modifiche delle API dalla libreriafoo alla libreria foo2, le modifiche necessarie per il codice sorgente devono essere fatte basandosi sulle nuove API.