Capitolo 3. Modificare i sorgenti

# Capitolo 3. Modificare i sorgenti

È 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.

## 3.1. Configurare quilt

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`.

## 3.2. Correggere i bug nel sorgente originale

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

## 3.3. Installazione dei file nei loro percorsi

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.

## 3.4. Distinguere le librerie

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.

[23] Vedere GNU Coding Standards: 7.2.4 DESTDIR: Support for Staged Installs.

[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 libreria`foo` alla libreria `foo2`, le modifiche necessarie per il codice sorgente devono essere fatte basandosi sulle nuove API.

Capitolo 2. Primi passi |  | Capitolo 4. File richiesti nella directory `debian`