Chapitre 3. Modification du code source

# Chapitre 3. Modification du code source

La réécriture de ce tutoriel avec des contenus à jour et des exemples pratiques supplémentaires est disponible sur Guide du responsable Debian. Veuillez utiliser ce nouveau tutoriel comme document principal.

La place manque pour entrer dans tous les détails de modification des sources amont, mais voici quelques étapes basiques et quelques problèmes créant des difficultés.

## 3.1. Configuration de quilt

Le programme quilt fournit une méthode fondamentale pour enregistrer les modifications du code source amont pour l'empaquetage Debian. Il est utile d'avoir de légères personnalisations du paramétrage par défaut, configurez donc un alias dquilt pour l'empaquetage Debian en ajoutant les lignes suivantes à `~/.bashrc`. La deuxième ligne fournit les mêmes fonctionnalités de complétion de l’interpréteur pour la commande dquilt que pour la commande quilt :

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

Ensuite créez `~/.quiltrc-dpkg` comme suit :

    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

Consultez quilt(1) et `/usr/share/doc/quilt/quilt.pdf.gz` pour apprendre à utiliser quilt.

## 3.2. Correction de bogues amont

Si vous trouvez une erreur dans le `Makefile` amont comme suit, où `install: gentoo` aurait dû être `install: gentoo-target` :

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

Corrigez l'erreur et enregistrez-la avec la commande dquilt sous `fix-gentoo-target.patch` : [22]

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

Modifiez le fichier `Makefile` comme suit :

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

Demandez à dquilt de créer `debian/patches/fix-gentoo-target.patch` et ajoutez sa description conformément à DEP-3 : Directives pour l'étiquetage des correctifs :

    $ dquilt refresh
    $ dquilt header -e
    ... description du correctif

## 3.3. Installation des fichiers à leur emplacement

La plupart des logiciels tiers s'installent d'eux-mêmes dans le répertoire `/usr/local`. Dans Debian, il est réservé à l'usage privé de l'administrateur système, les paquets ne doivent donc pas utiliser de répertoires comme `/usr/local/bin`, mais devraient plutôt utiliser les répertoires système comme `/usr/bin`, conformément à la norme de hiérarchie des fichiers (FHS).

Habituellement, make(1) est utilisé pour automatiser la construction du programme et l'exécution de `make install` installe les programmes directement à l'endroit voulu (d'après la cible `install` du `Makefile`). Pour permettre à Debian de fournir des paquets installables préconstruits, il modifie le système de construction pour installer les programmes dans une image de l'arborescence de fichiers créée dans un répertoire temporaire plutôt que dans la destination réelle.

Ces deux différences entre l'installation normale du programme d'un côté et le système d'empaquetage Debian de l'autre peuvent être abordées de façon transparente par le paquet `debhelper` à l'aide des commandes dh_auto_configure et dh_auto_install si les conditions suivantes sont vérifiées :

- le `Makefile` doit suivre les conventions GNU et gérer la variable `$(DESTDIR)` ; [23]

- les sources doivent suivre la norme de hiérarchie des fichiers (« Filesystem Hierarchy Standard » ou FHS).

Les programmes qui utilisent GNU autoconf suivent les conventions GNU automatiquement, de telle sorte qu'ils peuvent être faciles à empaqueter. Sur cette base et d'autres paramètres, on estime que le paquet `debhelper` fonctionnera pour 90 % des paquets sans modification intrusive de leur système de construction. L'empaquetage n'est donc pas aussi compliqué qu'il n'y paraît.

Si vous devez modifier le `Makefile`, vous devriez vous assurer qu'il gère la variable `$(DESTDIR)`. Bien qu'elle ne soit pas configurée par défaut, la variable `$(DESTDIR)` précède chaque chemin de fichier utilisé par le programme d'installation. Le script d'empaquetage configurera `$(DESTDIR)` en tant que répertoire temporaire.

Pour un paquet source créant un seul paquet binaire, le répertoire temporaire utilisé par la commande dh_auto_install sera configuré en `debian/`paquet``. [24] Le contenu du répertoire temporaire sera copié sur le système de l'utilisateur qui installera votre paquet, la seule différence est que dpkg placera ces fichiers dans des chemins relatifs au répertoire racine plutôt qu'au répertoire de travail.

Gardez à l'esprit que même si le programme s'installe dans `debian/`paquet``, il doit continuer à s'exécuter correctement quand il est installé à partir du paquet `.deb` sous le répertoire racine. Vous ne devez donc pas laisser le système de construction coder en dur des chaînes de caractères comme `/home/moi/deb/`paquet`-`version`/usr/share/`paquet`` dans les fichiers du paquet.

Voici les parties concernées du `Makefile` de `gentoo` [25] :

    # Emplacement des commandes exécutables lors de « make install »
    BIN     = /usr/local/bin
    # Emplacement des icônes lors de « make install »
    ICONS   = /usr/local/share/gentoo

Les fichiers sont configurés pour s'installer sous `/usr/local/`. Conformément aux explications précédentes, ce répertoire est réservé pour les utilisations locales de Debian, changez donc ces chemins comme suit :

    # Emplacement des commandes exécutables lors de « make install »
    BIN     = $(DESTDIR)/usr/bin
    # Emplacement des icônes lors de « make install »
    ICONS   = $(DESTDIR)/usr/share/gentoo

Les emplacements exacts qui devraient être utilisés pour les exécutables, icônes, documentation, etc., sont décrits dans la norme de hiérarchie des fichiers (FHS). Vous devriez la consulter et lire les sections relatives à votre paquet.

Dès lors, les commandes exécutables devraient être installées sous `/usr/bin` plutôt que sous `/usr/local/bin`, la page de manuel sous `/usr/share/man/man1` plutôt que sous `/usr/local/man/man1` et ainsi de suite. Remarquez qu'il n'y a pas de page de manuel mentionnée dans le fichier `Makefile` de `gentoo`, mais comme la Charte Debian exige que chaque programme en ait une, il faudra en créer une plus tard et l'installer dans `/usr/share/man/man1`.

Certains programmes n'utilisent pas les variables des fichiers `Makefile` pour définir des chemins comme ci-dessus. Cela signifie que vous risquez de devoir modifier de vrais fichiers sources C pour qu'ils utilisent les emplacements corrects. Mais où, et que chercher exactement ? Vous pouvez le découvrir avec :

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

grep va parcourir récursivement l'arbre des sources et donner le nom des fichiers et le numéro des lignes où il trouve une occurrence.

Modifiez ces fichiers en remplaçant dans ces lignes, `usr/local/lib` par `usr/lib`. Cela peut être automatisé comme suit :

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

Afin de confirmer toutes les substitutions, vous pouvez procéder de façon interactive comme suit :

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

Ensuite, vous devriez trouver la cible `install` (chercher la ligne qui commence par `install:` fonctionne en général) et renommez toutes les références aux répertoires autres que ceux définis au début du `Makefile`.

À l'origine, la cible `install` de `gentoo` était de la forme :

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

Corrigez ce bogue amont et enregistrez la modification avec la commande dquilt sous `debian/patches/install.patch` :

    $ dquilt new install.patch
    $ dquilt add Makefile

Dans votre éditeur, modifiez cela pour le paquet Debian comme suit :

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

Vous aurez remarqué qu'il y a maintenant une commande `install -d` avant les autres dans la règle. Elle n'existait pas dans le `Makefile` d'origine parce qu'habituellement `/usr/local/bin` et les autres répertoires existent déjà sur le système dans lequel `make install` est exécuté. Cependant, puisque dans notre cas l'installation se fait dans une arborescence spécifique nouvellement créée, chacun de ces répertoires doit être créé.

D'autres choses peuvent être ajoutées à la fin de la règle, comme l'installation de la documentation additionnelle que l'auteur amont oublie parfois :

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

Vérifiez soigneusement, et si tout est bon, demandez à dquilt de créer le correctif `debian/patches/install.patch` et ajoutez sa description :

    $ dquilt refresh
    $ dquilt header -e
    ... description du correctif

Vous avez maintenant un ensemble de correctifs.

1. Correction d'un bogue amont : `debian/patches/fix-gentoo-target.patch` ;

2. Modification spécifique à l'empaquetage Debian : `debian/patches/install.patch`.

Chaque fois que vous faites des modifications qui ne sont pas spécifiques à Debian comme `debian/patches/fix-gentoo-target.patch`, envoyez-les au responsable amont pour qu'elles puissent être intégrées dans la version suivante du programme et que tout le monde puisse en profiter. Évitez aussi de faire des corrections spécifiques à Debian ou Linux — ou même UNIX ! Faites-les portables. Cela rendra vos corrections beaucoup plus faciles à appliquer.

Remarquez que vous ne devez pas envoyer les fichiers `debian/*` en amont.

## 3.4. Bibliothèques différentes

Il y a un autre problème courant : les bibliothèques sont souvent différentes d'une plate-forme à l'autre. Par exemple, `Makefile` peut contenir une référence à une bibliothèque qui n'existe pas sur le système Debian. Dans ce cas, remplacez-la par une bibliothèque qui existe dans Debian, et qui sert à la même chose.

Supposons qu'une ligne de `Makefile` (ou `Makefile.in`) du programme comme suit :

    LIBS = -ltruc -lbidule

Si votre programme ne compile pas depuis que la bibliothèque `truc` n'existe plus et que son équivalent est fourni par la bibliothèque `truc2` sur le système Debian, vous pouvez corriger ce problème de construction en `debian/patches/truc2.patch` en modifiant `truc` en `truc2` : [26]

    $ dquilt new truc2.patch
    $ dquilt add Makefile
    $ sed -i -e 's/-ltruc/-ltruc2/g' Makefile
    $ dquilt refresh
    $ dquilt header -e
    ... description du correctif

[22] Le répertoire `debian/patches` devrait maintenant exister si vous avez exécuté dh_make comme décrit auparavant. Cet exemple de manipulation le crée seulement si vous mettez à jour un paquet existant.

[23] Consultez les normes GNU de codage : 7.2.4 DESTDIR : prise en charge des installations détournées.

[24] Pour un paquet source créant plusieurs paquets binaires, la commande dh_auto_install utilise `debian/tmp` comme répertoire temporaire alors que la commande dh_install, à l'aide des fichiers `debian/`paquet-1`.install` et `debian/`paquet-2`.install`, séparera le contenu de `debian/tmp` dans les répertoires temporaires `debian/`paquet-1`` et `debian/`paquet-2`` pour créer les paquets binaires ``paquet-1`_*.deb` et ``paquet-2`_*.deb`

[25] Il s'agit simplement d'un exemple pour montrer à quoi le `Makefile` devrait ressembler. Si le `Makefile` est créé par la commande ./configure, la bonne façon de modifier ce genre de `Makefile` est d'exécuter ./configure à partir de la commande dh_auto_configure avec les options par défaut y compris `--prefix=/usr`.

[26] Si des modifications de l'API existent entre les bibliothèques `truc` et `truc2`, les modifications nécessaires au code source doivent être faites pour correspondre à la nouvelle API.

Chapitre 2. Premiers pas |  | Chapitre 4. Fichiers nécessaires dans le répertoire `debian`