## Pacchettizzare da zero

Requisiti: build-essential, automake, gnupg, lintian, fakeroot e pbuilder.

In questo esempio useremo il programma GNU hello come esempio. Puoi scaricare l'archivio dei sorgenti da ftp.gnu.org. Per questo esempio, useremo la directory `~/hello/`.

    mkdir ~/hello
    cd ~/hello
    wget http://ftp.gnu.org/gnu/hello/hello-2.1.1.tar.gz

We will also compare our package to one that is already packaged in the Ubuntu repository. For now, we will place it in the `ubuntu` directory so we can look at it later. To get the source package, make sure you have a "deb-src" line in your `/etc/apt/sources.list` file for the Main repository. Then, simply execute:

    mkdir ubuntu
    cd ubuntu
    apt-get source hello
    cd ..

A differenza di molti comandi di apt-get, non hai bisogno dei permessi di root per scaricare il pacchetto sorgente perchè è scaricato nella directory corrente. Infatti è consigliabile usare apt-get source solo come utente normale, in modo da poter modificare i filie nel pacchetto sorgente senza aver bisogno dei privilegi di root.

Questo è quanto compie il comando apt-get source:

1. Scarica il pacchetto sorgente. Un pacchetto sorgente di solito contiene un file .dsc che descrive il pacchetto e fornisce gli hash MD5 del pacchetto sorgente, un file .orig.tar.gz che contiene il codice sorgente degli autori originali e un file .diff.gz che contiene le modifiche applicate al codice sorgente comprensive delle informazioni di pacchettizzazione.

2. Scompatta il file .orig.tar.gz nella directory corrente.

3. Applica il file .diff.gz decompresso nella directory dei sorgenti.

Se hai scaricato manualmente il pacchetto sorgente (i file .dsc, .orig.tar.gz e .diff.gz), puoi scompattarli nello stesso modo di apt-get source usando dpkg-source in questo modo:

    dpkg-source -x *.dsc

La prima cosa che dovrai fare è fare una copia dell'archivio originale (a volte chiamato "upstream") nel seguente formato: `<nomepacchetto>_<versione>.orig.tar.gz`. Questo passaggio fa due cose. In primo luogo, crea due copie del codice sorgente. Se per sbaglio modifichi o cancelli la copia su cui stai lavorando puoi usare quella che hai scaricato. In secondo luogo è considerata non una buona tecnica di pacchettizzazione modificare l'archivio dei sorgenti originale se non strettamente necessario. Si veda la sezione chiamata “Errori comuni” per i motivi.

    cp hello-2.1.1.tar.gz hello_2.1.1.orig.tar.gz
    tar -xzvf hello_2.1.1.orig.tar.gz

L'underscore, "_", tra il nome del pacchetto (hello) e la versione (2.1.1), in contrapposizione al trattino, "-", è molto importante. Il tuo pacchetto sorgente non sarà compilato come un pacchetto nativo di Debian.

Ora abbiamo una directory `hello-2.1.1` contenente i file sorgente. Ora dobbiamo creare la solita directory debian dove sono contenute tutte le informazioni di pacchettizzazione, consentendoci di separare i file di pacchettizzazione da quelli dell'applicazione.

    mkdir hello-2.1.1/debian
    cd hello-2.1.1/debian/

We now need to create the essential files for any Ubuntu source package: `changelog`, `control`, `copyright`, and `rules`. These are the files needed to create the binary packages (.deb files) from the original (upstream) source code. Let us look at each one in turn.

### changelog

Il file `changelog`, come suggerisce il suo nome, è un elenco dei cambiamenti effettuati in ogni versione. Ha un formato predefinito che fornisce il nome del pacchetto, la versione, la distribuzione, le modifiche e chi e quando ha fatto le modifiche. Se hai una chiave GPG, assicurati di usare lo stesso nome e indirizzo di posta elettronica nel `changelog` di quello riportato nella tua chiave. Il seguente è un modello di `changelog`:

    package (version) distribution; urgency=urgency

      * change details
        more change details
      * even more change details

     -- maintainer name <email address>[two spaces]  date

Il formato (in particolar modo dedlla data) è importante. La data dovrebbe essere in formato RFC822, la quale può essere ottenuta dal programma 822-date.

Ecco un esempio del file `changelog` per hello:

    hello (2.1.1-1) edgy; urgency=low

       * New upstream release with lots of bug fixes.

     -- Captain Packager <packager@coolness.com>  Wed,  5 Apr 2006 22:38:49 -0700

Osserva che la versione contiene un -1 in coda ad essa e si definisce revisione di Debian, la quale è usata in modo tale che i pacchetti possano essere aggiornati (per correggere bug per esempio) con nuovi caricamenti all'interno del medesima versione del file sorgente.

Ubuntu and Debian have slightly different package versioning schemes to avoid conflicting packages with the same source version. If a Debian package has been changed in Ubuntu, it has ubuntuX (where X is the Ubuntu revision number) appended to the end of the Debian version. So if the Debian hello package was changed by Ubuntu, the version string would be `2.1.1-1ubuntu1`. If a package for the application does not exist in Debian, then the Debian revision is 0 (e.g., `2.1.1-0ubuntu1`).

Now look at the `changelog` for the Ubuntu source package that we downloaded earlier:

    less ../../ubuntu/hello-2.1.1/debian/changelog

Notice that in this case the distribution is unstable (a Debian branch), because the Debian package has not been changed by Ubuntu. Remember to set the distribution to your target distribution release.

A questo punto crea un file `changelog` nella directory `debian`, dove dovresti già essere.

### control

Il file control contiene le informazioni che il gestore di pacchetti (come apt-get, synaptic e aptitude) usa, le dipendenze di compilazioni, le informazioni del manutentore, e molto altro.

For the Ubuntu hello package, the control file looks something like:

    Source: hello
    Section: devel
    Priority: optional
    Maintainer: Captain Packager <packager@coolness.com>
    Standards-Version: 3.6.1

    Package: hello
    Architecture: any
    Depends: ${shlibs:Depends}
    Description: The classic greeting, and a good example
     The GNU hello program produces a familiar, friendly greeting.  It
     allows non-programmers to use a classic computer science tool which
     would otherwise be unavailable to them.
     .
     Seriously, though: this is an example of how to do a Debian
     package.
     It is the Debian version of the GNU Project's `hello world' program
     (which is itself an example for the GNU Project).

Crea il `control` usando le informazioni elencate (accertandoti di fornire i tuoi dati per il campo Maintainer).

Il primo paragrafo fornisce informazioni sul pacchetto sorgente. Analizziamo ogni riga:

- Source: Questo è il nome del pacchetto sorgente, hello, in questo caso.

- Section: I repository di apt sono suddivisi in sezioni per facilitare la consultazione e la catalogazione del software. In questo caso, hello appartiene alla sezione devel.

- Priority: Questo campo assegna l'importanza del pacchetto per gli utenti. Dovrebbe essere una delle seguenti:

  - Required - pacchetti essenziali per il funzionamento del sistema. Se vengono rimossi, è altamente probabile che il tuo sistema verrà danneggiato in maniera irreparabile.

  - Important - un insieme minimale di pacchetti per avere un sistema utilizzabile. Rimuovendo questi pacchetti non causerà un malfunzionamento irreparabile del sistema, ma di solito sono considerati strumenti importanti senza i quali qualsiasi distribuzione GNU/Linux sarebbe incompleta. Nota bene: questa categoria on include pacchetti come Emacs o persino il sistema X Window.

  - Standard - Autoesplicativo.

  - Optional - questa categoria è dedicata in pratica per i pacchetti non richiesti, o per la maggior parte di essi. Comunque, questi pacchetti non devono essere in conflitto tra loro.

  - Extra - pacchetti che possono essere in conflitto con i pacchetti di una delle altre categorie. Viene inoltre usata per pacchetti specifici che potrebbero essere utili a persono che già conoscono l'utilità del pacchetto.

- Maintainer: Il manutentore del pacchetto e l'indirizzo di posta elettronica.

- Standards-Version: La versione della Policy di Debian alla quale il pacchetto è assoggettato (in questo caso, la versione 3.6.1). Un modo rapido per visualizzare la versione corrente è apt-cache show debian-policy | grep Version.

- Build-Depends: Uno dei campi più importanti e spesso causa di bug, questa riga elenca i pacchetti binari (con versione, se necessario) che devono essere installati per creare il pacchetto binario a partire da quello sorgente. I pacchetti essenziali sono richiesti da build-essential e non devono essere inclusi nella riga Build-Depends. Nel caso di hello, tutti i pacchetti che servono fanno parte di build-essential, così la riga Build-Depends non è necessaria. L'elenco dei pacchetti di build-essentiaò può essere reperita in `/usr/share/doc/build-essential/list`.

Il secondo paragrafo è relativo ai pacchetti binari che saranno creati a partire dai sorgenti. Se più pacchetti binari saranno creati dal pacchetto sorgente, dovrebbe esserci una sezione per emphasis>ognuno

- Package: Il nome del pacchetto binario. Il più delle volte per programmi semplici (come hello), il nome dei pacchetti binario e sorgente sono identici.

- Architecture: L'architettura per la quale saranno costruiti i pacchetti binari. Esempi possono essere:

  - all - I sorgenti non dipendono da una specifica architettura. I programmi che usano Python o altri linguaggi interpretati lo usano. Il pachetto binario risultante dovrebbe terminare in `_all.deb`.

  - any - I sorgenti sono dipendono da una specifica architettura e dovrebbero compilarsi su tutte le architetture supportate. Ci sarà un pacchetto .deb per ciascuna architettura ( `_i386.deb` per esempio)

  - A subset of architectures (i386, amd64, ppc, etc.) can be listed to indicate that the source is architecture-dependent and does not work for all architectures supported by Ubuntu.

- Depends: L'elenco dei pacchetti che il pacchetto binario dipende per poter funzionare. Per hello, notiamo `${shlibs:Depends}`, una variabile che sostituisce le necessarie librerie condivise. Si veda la pagina di manuale di `dpkg-source` per maggiori informazioni.

- Recommends: Usato per pacchetti che sono caldamente raccomandati e solitamente sono installati con il pacchetto. Alcuni gestori di pacchetti, più precisamente aptitude, installano automaticamente i pacchetti raccomandati.

- Suggests: Usato per pacchetti simili o utili al pacchetto che deve essere installato.

- Conflicts: Usato per pacchetti che vanno in conflitto con questo pacchetto. Entrambi non possono essere installati contemporaneamente. Se uno di essi sta per essere installato, l'altro verrà rimosso.

- Description: Sia la descrizione breve, sia quella lunga sono usate dai gestori di pacchetti. Il formato è:

      Description: <singola riga>
       <descrizione estesa su più righe>

  Osserva che c'è uno spazio all'inizio di ogni riga della descrizione lunga. Maggiori informazioni su come realizzare una buona descrizione possono essere trovate su http://people.debian.org/~walters/descriptions.html.

### copyright

Questo file elenca le informazioni sul copyright. Di solito, le informazioni sul copyright sono riportate nel file `COPYING` nella directory dei sorgenti del programma. Questo file dovrebbe includere informazioni quali il nome dell'autore e del creatore del pacchetto, l'URL dal quale provengono i sorgenti, una riga Copyright con l'anno e il detentore dei diritti d'autore e il testo del copyright stesso. Un modello d'esempio è simile a:

    This package was debianized by {Il tuo nome} <la tua email>
    {Data}

    It was downloaded from: {URL o pagina Web}

    Upstream Author(s): {Nomi e indirizzi email degli autori}

    Copyright:
    	Copyright (C) {Anno/i} by {Autore} {Indirizzo email}

    License:

As one can imagine, hello is released under the GPL license. In this case it is easiest to just copy the `copyright` file from the Ubuntu package:

    cp ../../ubuntu/hello-2.1.1/debian/copyright .

Devi inserire il copyright completo a meno che non sia GPL, LGPL, BSD o Licenza Artistica, nel qual caso puoi fare riferimento al file corrispondente nella directory `/usr/share/common-licenses/`.

Notice that the Ubuntu package's `copyright` includes a license statement for the manual. It is important that all the files in the source be covered by a license statement.

### rules

The `rules` file is an executable Makefile that has rules for building the binary package from the source packages. For hello, it will be easier to use the `rules` from the Ubuntu package:

    #!/usr/bin/make -f
    # Semplice file debian/rules - for GNU Hello.
    # Copyright 1994,1995 by Ian Jackson.
    # Ti concedo il permesso perpetuo e illimitato di copiare,
    # modificare e modificare la licenza di questo programma,
    # a patto che non rimuova il mio nome dal file medesimo.
    # (Asserisco i miei diritti morali di paternità sotto il decreto
    # Copyright, Designs and Patents Act del 1988.)
    # Questo file può essere modificato pesantemente

    package = hello
    docdir = debian/tmp/usr/share/doc/$(package)

    CC = gcc
    CFLAGS = -g -Wall
    INSTALL_PROGRAM = install

    ifeq (,$(findstring noopt,$(DEB_BUILD_OPTIONS)))
      CFLAGS += -O2
    endif
    ifeq (,$(findstring nostrip,$(DEB_BUILD_OPTIONS)))
      INSTALL_PROGRAM += -s
    endif

    build:
            $(checkdir)
            ./configure --prefix=/usr
            $(MAKE) CC="$(CC)" CFLAGS="$(CFLAGS)"
            touch build

    clean:
            $(checkdir)
            rm -f build
            -$(MAKE) -i distclean
            rm -rf *~ debian/tmp debian/*~ debian/files* debian/substvars

    binary-indep:   checkroot build
            $(checkdir)
    # Non ci sono file dipendenti da una specifica architettura da caricare
    # generati da questo pacchetto. Se ce ne fossero, sarebbero dovuti
    # essere fatti qui

    binary-arch:    checkroot build
            $(checkdir)
            rm -rf debian/tmp
            install -d debian/tmp/DEBIAN $(docdir)
            install -m 755 debian/postinst debian/prerm debian/tmp/DEBIAN
            $(MAKE) INSTALL_PROGRAM="$(INSTALL_PROGRAM)" \
                    prefix=$$(pwd)/debian/tmp/usr install
            cd debian/tmp && mv usr/info usr/man usr/share
            cp -a NEWS debian/copyright $(docdir)
            cp -a debian/changelog $(docdir)/changelog.Debian
            cp -a ChangeLog $(docdir)/changelog
            cd $(docdir) && gzip -9 changelog changelog.Debian
            gzip -r9 debian/tmp/usr/share/man
            gzip -9 debian/tmp/usr/share/info/*
            dpkg-shlibdeps debian/tmp/usr/bin/hello
            dpkg-gencontrol -isp
            chown -R root:root debian/tmp
            chmod -R u+w,go=rX debian/tmp
            dpkg --build debian/tmp ..

    define checkdir
            test -f src/$(package).c -a -f debian/rules
    endef

    binary: binary-indep binary-arch

    checkroot:
            $(checkdir)
            test $$(id -u) = 0

    .PHONY: binary binary-arch binary-indep clean checkroot

Procediamo su questo file in dettaglio. Una delle prime componenti che vedrai è la dichiarazione di alcune variabili:

    package = hello
    docdir = debian/tmp/usr/share/doc/$(package)

    CC = gcc
    CFLAGS = -g -Wall
    INSTALL_PROGRAM = install

    ifeq (,$(findstring noopt,$(DEB_BUILD_OPTIONS)))
      CFLAGS += -O2
    endif
    ifeq (,$(findstring nostrip,$(DEB_BUILD_OPTIONS)))
      INSTALL_PROGRAM += -s
    endif

Questa sezione definisce i CFLAGS per il compilatore e gestisce anche le DEB_BUILD_OPTIONS `noopt` e `nostrip` per il debug.

Poi c'è la regola `build`:

    build:
    	$(checkdir)
    	./configure --prefix=/usr
    	$(MAKE) CC="$(CC)" CFLAGS="$(CFLAGS)"
    	touch build

Questa regola esegue ./configure con il prefix appropriato, esegue make e crea un file `build` che indica il momento in cui è stato creato il pacchetto per prevenire compilazioni multiple errate.

La regola seguente è `clean`, la quale esegue make -i distclean che rimuove i file creati durante il processo di creazione del pacchetto.

    clean:
    	$(checkdir)
    	rm -f build
    	-$(MAKE) -i distclean
    	rm -rf *~ debian/tmp debian/*~ debian/files* debian/substvars

Poi c'è una regola `binary-indep` vuota, dato che non sono stati creati file dipendenti da una specifica architettura in questo pacchetto.

Ci sono, però, diversi file dipendenti da una specifica architettura, quindi viene usata `binary-arch`:

    binary-arch:    checkroot build
    		$(checkdir)
    		rm -rf debian/tmp
    		install -d debian/tmp/DEBIAN $(docdir)
    		install -m 755 debian/postinst debian/prerm debian/tmp/DEBIAN
    		$(MAKE) INSTALL_PROGRAM="$(INSTALL_PROGRAM)" \
    		prefix=$$(pwd)/debian/tmp/usr install
    		cd debian/tmp && mv usr/info usr/man usr/share
    		cp -a NEWS debian/copyright $(docdir)
    		cp -a debian/changelog $(docdir)/changelog.Debian
    		cp -a ChangeLog $(docdir)/changelog
    		cd $(docdir) && gzip -9 changelog changelog.Debian
    		gzip -r9 debian/tmp/usr/share/man
    		gzip -9 debian/tmp/usr/share/info/*
    		dpkg-shlibdeps debian/tmp/usr/bin/hello
    		dpkg-gencontrol -isp
    		chown -R root:root debian/tmp
    		chmod -R u+w,go=rX debian/tmp
    		dpkg --build debian/tmp ..

Per prima cosa, questa regola richiama `checkroot` per assicurarsi che il pacchetto venga costruito come root e richiama la regola `build` per compilare i sorgenti. Quindi vengono creati i file `debian/tmp/DEBIAN` e `debian/tmp/usr/share/doc/hello` e gli script `postinst` e `prerm>` vengono installati in `debian/tmp/DEBIAN`. Quindi viene eseguito make install con un prefix apposito che installa il pacchetto nella directory `debian/tmp/usr`. In seguito i file della documentazione (NEWS, ChangeLog e il changelog di Debian) vengono compressi e installati. Viene invocato dpkg-shlibdeps per trovare le librerie condivise da cui dipende l'eseguibile hello, e ne registra l'elenco nel file `debian/substvars` per la variabile ${shlibs:Depends} in `control`. Quindi viene eseguito dpkg-gencontrol per creare un file di controllo per il pacchetto binario, applicando le modifiche create da dpkg-shlibdeps. Infine, dopo che i permessi di `debian/tmp` sono stati assegnati, viene eseguito dpkg --build per costruire il pacchetto binario .deb che verrà collocato nella directory superiore.

### postinst e prerm

The `postinst` and `prerm` files are examples of maintainer scripts. They are shell scripts that are executed after installation and before removal, respectively, of the package. In the case of the Ubuntu hello package, they are used to install (and remove) the info file. Go ahead and copy them into the current `debian` directory.

    cp ../../ubuntu/hello-2.1.1/debian/postinst .
    cp ../../ubuntu/hello-2.1.1/debian/prerm .

### Creare il pacchetto sorgente

Ora che abbiamo analizzato in dettaglio i file nella directory `debian` per hello, possiamo costruire il pacchetto sorgente (e binario). Per prima cosa entriamo nella directory principale dei sorgenti estratti:

    cd ..

Ora costruiamo il pacchetto sorgente usando dpkg-buildpackage:

    dpkg-buildpackage -S -rfakeroot

Il flag -S flag indica a dpkg-buildpackage di creare un pacchetto sorgente, mentre il flag -r flag gli indica di usare fakeroot per permettergli di avere privilegi di root apparenti durante la creazione del pacchetto. dpkg-buildpackage prenderà il file `.orig.tar.gz` e produrrà un `.diff.gz` (le differenze tra l'archivio originale dell'autore e la directory che abbiamo creato, `debian/` and its contents) e un file `.dsc` che contiene la descrizione e gli hash MD5 del pacchetto sorgente. I file `.dsc` e `*_source.changes` (utilizzato per caricare i pacchetti sorgente) sono firmati usando la tua chiave GPG.

Se non hai una chiave gpg disponibile, otterrai un errore da debuild. Puoi creare sia una chiave gpg. o usare le chiavi -us -uc di debuild per disabilitare la firma. Però non sarai in grado di caricare i tuoi pacchetti in Ubuntu senza firmarli.

Per assicurarti che debuild la chiave gpg corretta, dovresti impostare le veriabili d'ambiente DEBFULLNAME e DEBEMAIL (nel tuo `~/.bashrc` per esempio) con il nome e l'indirizzo di posta elettronica che usi per la tua chiave gpg e in `debian/changelog` Alcune persone hanno riportato che non sono state in grado di far trovare a debuild la loro chiave gpg, anche dopo aver configurato le variabili d'ambiente citate. Per risolvere il problema, puoi indicare a debuild il flag -k<keyid> dove <keyid> è l'ID della tua chiave gpg.

In aggiunta al pacchetto sorgente, possiamo costruire il pacchetto binario con pbuilder:

    sudo pbuilder build ../*.dsc

E' molto importante usare pbuilder per costruire il pacchetto binario. Si assicura che le dipendenze di compilazione siano corrette, dato che pbuilder: prevede solo un ambiente minimale, così tutte le dipendeze di compilazione vengono determinate dal file `control`.

Possiamo controllare il pacchetto sorgente per errori comuni usando lintian:

    cd ..
    lintian -i *.dsc

Capitolo 3. Pacchettizzazione di base |  | Creare pacchetti con Debhelper