Ce petit manuel vise à donner au lecteur des clés pour mieux comprendre la fabrication des paquets Slackware et pouvoir à son tour en produire. Il aborde une à une les questions liées à cette procédure, de la recherche des sources jusqu'à l'obtention d'un paquet bien formé, cela en essayant de mettre chaque fois en relief leurs tenants et aboutissants.
Si nous avons esquissé une explication de ce qu'étaient les sources, nous n'avons en revanche rien dit sur la manière de les identifier. La plupart du temps les sources se présentent sous formes d'archives compressées par "gzip ou bzip2 : <nom_du_logiciel.tar.gz> [4] ou <nom_du_logiciel.tar.bz2>". Parfois certains projets laissent le choix, si vous avez peu de place sur votre disque dur ou une connexion bas-débit, l'archive compressée par "bzip2" est à préférer car de taille plus réduite.
Une fois l'archive téléchargée, la première chose à faire est de la décompresser en employant la commande "tar" dans votre terminal préféré, la même qui a servi à sa compression.
" mushroom@packman:~$ tar xvfj bluefish-1.0.5.tar.bz2
[…]
bluefish-1.0.5/TODO
bluefish-1.0.5/config.guess
bluefish-1.0.5/AUTHORS
bluefish-1.0.5/Makefile.in
bluefish-1.0.5/NEWS
bluefish-1.0.5/README
bluefish-1.0.5/config.sub
bluefish-1.0.5/INSTALL
bluefish-1.0.5/configure
bluefish-1.0.5/COPYING
bluefish-1.0.5/install-sh
bluefish-1.0.5/aclocal.m4
bluefish-1.0.5/ChangeLog
bluefish-1.0.5/configure.ac
bluefish-1.0.5/INSTALL.Debian
"
Le "x suivant la commande tar indique qu'il faut extraire le contenu de l'archive, le v demande de donner le maximum d'informations via la sortie standard (en l'occurrence la fenêtre du terminal), le f appelle l'archive et le j indique que celle-ci est a été compressée avec bzip2 (si elle l'avait été par gzip, on aurait dû mettre z" à sa place [5]).
Il ne reste plus qu'à entrer dans le dossier généré par la décompression à l'aide de la commande "cd" :
" mushroom@packman:~$ cd bluefish-1.0.5/
mushroom@packman:bluefish-1.0.5$
"
Les sources décompressées, il faut savoir que celles-ci ont toujours besoin de binaires extérieurs pour être compilées. Ces binaires sont ce qu'on appelle des « dépendances » et c'est grâce à leur action ou à leur contenu que la compilation va s'effectuer. La première chose à faire est de les identifier en consultant le fichier "README contenu dans l'archive (parfois francisé en LISEZ-MOI") :
" mushroom@packman:bluefish-1.0.5$ less README
This is the Bluefish HTML editor.
It has (among others) the following major features
Customizable syntax highlighting based on Perl Compatible regular expressions,
Multiple encodings support
Wizards for startup, tables, frames, and others
Dialogs for many HTML tags, with all their attributes
User-customizable toolbar for quick access to often used functions
A custom menu, specify your own tags or sets of code, and define your own dialogs
Custom search and replace pattern support for the Custom menu
Function reference browser, including reference files for PHP, HTML, CSS, PYTHON
User customizable integration of many programs, including weblint, tidy, make
Projects for quick access of frequently used sets of files
Installation:
See INSTALL file for information on how to install Bluefish
[…]
"
La commande "less" a pour effet d'éditer le fichier en paginant la sortie.
Cas fréquent, nous sommes ici renvoyés à un fichier "INSTALL", spécialement dédié aux questions d'installation (et donc de compilation).
" mushroom@packman:bluefish-1.0.5$ less INSTALL
To install Bluefish from source:
1) get the required libraries (You will need the header files for
these packages, usually these are packaged seperately with the prefix
-dev, like libgtk2.0-dev or libpcre-dev):
*libgtk2 (preferrably 2.2.2 or newer)
*libpcre
*gnome-vfs2 (Optional; for remote file handling)
*aspell (Optional; for spell checking)
*grep and find are required to use the Advance Open function
2) run ./configure –help
for information about possible options.
(This step is usually not required)
3) configure and compile
./configure [options-you-like-most-here]
make
4) install everything
su
make install
[…]
"
Nous avons de la chance car l'"INSTALL de Bluefish" est riche en informations. Ainsi nous pouvons connaître les dépendances requises et nous voyons que nous sommes en présence d'une procédure de compilation très classique (quasi-standard) passant par la séquence « "configure/make/make install" ».
La liste des dépendances n'est jamais exhaustive dans la mesure où elles s'étalent sur plusieurs générations [6] : z nécessite que y soit installé, qui nécessite lui même x,… Les ancêtres se situant toujours dans les couches profondes de GNU/Linux, ils sont souvent considérés comme allant de soi. En général ne sont donnés que les parents et (parfois) les grands-parents du logiciel. Il ne faut donc pas s'étonner si même après avoir installé les paquets requis la compilation échoue à trouver certains éléments. Le tout est en fait de savoir comment identifier les dépendances manquantes.
" checking for gnome-vfs >= 2.2… no
checking for gnome-vfs >= 2.6… no
checking for libgnomeui >= 2.6… no
checking for pcre-config… no
configure: error: pcre-config not found please install libpcre3-dev or similar
mushroom@packman:bluefish-1.0.5$
"
Dans l'exemple de sortie en erreur ci-dessus, il nous est demandé "pcre-config (en général, les messages d'erreur contenant <quelque_chose> not found" relèvent d'un problème de dépendance). La première question qui doit venir à l'esprit est « La dépendance manquante est-elle disponible dans la Slackware ? », elle économisera du temps et préviendra pas mal de problèmes. Pour répondre à cette question, deux ressources sont à notre disposition :
Le
gestionnaire de paquets du site Slackware : il suffit de taper le nom de la dépendance dans le moteur de recherche, et celui-ci indiquera dans quel paquet elle se trouve, si toutefois elle est bien disponible dans la Slackware
[7].
Les fichiers "MANIFEST : situés dans les répertoires slackware/ des CD#1 et #2, ils listent le contenu des paquets de leur CD respectif. Ils sont compressés par bzip2. Le mieux est généralement de les copier sur le disque dur (ici nous avons mis le MANIFEST du premier CD dans notre dossier utilisateur). Il vous suffit ensuite d'utiliser la commande suivante où <pattern>" sera le nom de la dépendance recherchée :
bzcat MANIFEST.bz2 | sed "{/<pattern>\|Package:/p}" -n | less
La commande "bzcat affiche le contenu du fichier compressé par bzip2, puis l'envoie à la commande sed. Celle-ci ne retiendra que les lignes contenant <pattern> ou Package: qu'elle transmettra à less que nous venons de voir. Voici un exemple avec pcre-config" :
" mushroom@packman:~$ bzcat MANIFEST.bz2 | sed "{/pcre-config\|Package:/p}" -n | less\\ \\ [...]\\ \\ || Package: ./l/netpbm-10.18.12-i486-1.tgz\\ || Package: ./l/pango-1.8.2-i486-1.tgz\\ || Package: ./l/pcre-6.4-i486-1.tgz\\ -rwxr-xr-x root/bin 1192 2005-09-12 17:25:14 usr/bin/pcre-config\\ || Package: ./l/pilot-link-0.11.8-i486-2.tgz\\ || Package: ./l/popt-1.7-i386-1.tgz\\ \\ [...]\\ "\\
De la présente sortie, nous pouvons conclure que "pcre-config est dans le paquet ./l/pcre-6.4-i486-1.tgz"
Ici nous avons donc trouvé ce que nous cherchions dans le paquet "pcre (répertoire l/" ), il n'en va hélas pas toujours ainsi. Même si la Slackware est plutôt bien pourvue pour satisfaire les dépendances des logiciels hors-distribution, il arrive en effet qu'il faille compiler certaines dépendances. Pour trouver celles-ci, le plus simple est de chercher sur le site du logiciel car il est bien rare qu'il n'y ait pas de lien vers les sites hébergeant le développement de ses dépendances. Si cette voie échoue, il ne restera alors plus qu'à recourir aux moyens que nous avons déjà évoqués (cf. Où trouver les sources ?).
Les questions liées à la préparation de l'archive étant théoriquement réglées nous pouvons aborder celle de la configuration des sources. « Théoriquement » car, limitation de la liste des dépendances annoncées oblige, les deux phases se chevauchent souvent dans les faits.
La configuration des sources, dans la grande majorité des cas, est assurée via un script exécutable nommé "configure". Son rôle est double : d'une part il permet à l'utilisateur de moduler les caractéristiques du binaire final, d'autre part il collecte des informations sur le système pour connaître son type, l'emplacement des binaires requis, le compilateur utilisé, etc… Avec un peu d'expérience, vous remarquerez que certaines options et syntaxes reviennent souvent d'un "configure à l'autre, il n'en demeure pas moins qu'un configure est toujours propre aux sources qu'il configure. Regardons un peu plus en détail celui de Bluefish" dans ses éléments les plus communément rencontrés :
" mushroom@packman:bluefish-1.0.5$ ./configure –help
1 `configure' configures this package to adapt to many kinds of systems.
2
3 Usage: ./configure [OPTION]… [VAR=VALUE]…
4
5 To assign environment variables (e.g., CC, CFLAGS…), specify them as
6 VAR=VALUE. See below for descriptions of some of the useful variables.
7
8 Defaults for the options are specified in brackets.
[…]
20
21 Installation directories:
22 –prefix=PREFIX install architecture-independent files in PREFIX
23 [/usr/local]
24 –exec-prefix=EPREFIX install architecture-dependent files in EPREFIX
25 [PREFIX]
26
27 By default, `make install' will install all the files in
28 `/usr/local/bin', `/usr/local/lib' etc. You can specify
29 an installation prefix other than `/usr/local' using `–prefix',
30 for instance `–prefix=$HOME'.
31
"Les numéros de lignes ont étés ajoutés içi pour des besoins d'explications et n'apparaissent normalement pas à l'écran.
Dans l'invite de commande, "./ indique que le fichier est dans le répertoire courant et l'option –help demande des informations quand à l'usage de ce configure . Cette option fonctionne vraisemblablement avec tous les fichiers de type configure" (et même avec la plupart des commandes).
L'option "–prefix=<répertoire> (l. 22) est sans doute l'option la plus communément utilisée avec les configure". Elle permet de définir dans quel dossier sera installé le binaire final. En règle générale les logiciels sont paramétrés par défaut pour s'installer dans "/usr/local/. C'est un choix compréhensible dans la mesure où /usr/local" est justement prévu pour accueillir les logiciels hors-distribution. Il faut cependant prendre garde car certains éléments ne sont pas toujours localisés par le système lorsqu'ils sont dans ce répertoire. Cela peut poser problème, notamment si ces éléments sont requis en tant que dépendances par d'autres logiciels. C'est pourquoi on peut lui préférer le répertoire "/usr/".
" 32 For better control, use the options below.
33
34 Fine tuning of the installation directories:
35 –bindir=DIR user executables [EPREFIX/bin]
36 –sbindir=DIR system admin executables [EPREFIX/sbin]
37 –libexecdir=DIR program executables [EPREFIX/libexec]
38 –datadir=DIR read-only architecture-independent data [PREFIX/share]
39 –sysconfdir=DIR read-only single-machine data [PREFIX/etc]
40 –sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com]
41 –localstatedir=DIR modifiable single-machine data [PREFIX/var]
42 –libdir=DIR object code libraries [EPREFIX/lib]
43 –includedir=DIR C header files [PREFIX/include]
44 –oldincludedir=DIR C header files for non-gcc [/usr/include]
45 –infodir=DIR info documentation [PREFIX/info]
46 –mandir=DIR man documentation [PREFIX/man]
47
"
Les options de préfixation, lignes 34 à 46, fonctionnent comme "–prefix=<répertoire>", à cette différence qu'elles paramètrent le répertoire d'installation d'un élément précis du logiciel. Par exemple, si le logiciel dans son entier est préfixé pour s'installer dans "/usr/local, –sysconfdir=/etc permet d'installer les élements du logiciel concernant la configuration système dans /etc, la place qui leur est normalement dévolue, au lieu de /usr/local/etc".
" 48 Program names:
49 –program-prefix=PREFIX prepend PREFIX to installed program names
50 –program-suffix=SUFFIX append SUFFIX to installed program names
[…]
53 System types:
54 –build=BUILD configure for building on BUILD [guessed]
55 –host=HOST cross-compile to build programs to run on HOST [BUILD]
56
57 Optional Features:
58 –disable-FEATURE do not include FEATURE (same as –enable-FEATURE=no)
59 –enable-FEATURE[=ARG] include FEATURE [ARG=yes]
[…]
89
90 Optional Packages:
91 –with-PACKAGE[=ARG] use PACKAGE [ARG=yes]
92 –without-PACKAGE do not use PACKAGE (same as –with-PACKAGE=no)
[…]
"
Les options lignes 49 et 50 servent à ajouter du texte avant ou après le nom du programme. Elles sont utiles lorsque, par exemple, on a besoin d'installer sur une machine un même logiciel sous des versions différentes.
L'option "–build=<architecture>" (l. 54) permet d'indiquer l'architecture du système sur lequel est compilé le programme afin que le compilateur puisse optimiser la compilation. L'option "–host=<architecture> (souvent appelée –target=<architecture>), ligne 55, quant à elle, sert à spécifier l'architecture du système de destination du futur binaire
[8]. Il existe beaucoup de configure" qui, à l'instar de celui-ci («
guessed » signifie « déduit »), déterminent automatiquement l'architecture du système sur lequel ils sont lancés et ordonnent une optimisation pour et à partir de celle-ci.
Les options "–disable-<quelque_chose> et –enable-<quelque_chose>" (l. 58-59) sont très communes. Elle servent à désactiver ou à activer le support de certaines options par le logiciel. Cela peut être utilisé lorsqu'on ne veut pas installer certaines dépendances requises du seul fait d'un support.
Les options lignes 91 et 92 sont proches des "–disable/enable-<quelque_chose>" mais elles visent une dépendance plutôt qu'un support. Par exemple, elles sont utiles lorsqu'on a une une dépendance optionnelle installée sur son système mais qu'on ne veut pas que le logiciel en tienne compte (les "configure" ont souvent tendance à utiliser tout ce qui leur tombe sous la main pour paramétrer la compilation).
" 117 Some influential environment variables:
118 CC C compiler command
119 CFLAGS C compiler flags
120 LDFLAGS linker flags, e.g. -L<lib dir> if you have libraries in a
121 nonstandard directory <lib dir>
122 CPPFLAGS C/C preprocessor flags, e.g. -I<include dir> if you have\\ 123 headers in a nonstandard directory <include dir>\\ 124 CPP C preprocessor\\ 125 \\ 126 Use these variables to override the choices made by `configure' or to help\\ 127 it to find libraries and programs with nonstandard names/locations.\\ 128\\ "
* Ces options permettent de préciser les paramètres de compilation. Entre autres, on peut ainsi préciser le compilateur utilisé, le degré, la portée (faire un binaire compatible ou non avec des architectures proches de celle utilisée) et le sens des optimisations (par exemple, faire un binaire le plus petit possible). Pour ce qui est des deux options "LDFLAGS et CPPFLAGS", elles aident le compilateur à s'y retrouver sur des systèmes un peu exotiques.
La liste des options proposées peut paraître à première vue longue et difficile à appréhender. On aurait dans une large mesure tort car il faut bien voir que toutes ces options sont d'abord conçues pour ceux qui maintiennent des distributions. Dans le cadre d'un empaquetage « artisanal » on n'a souvent à manier guère plus que "--prefix=<répertoire>", comme ici :
" mushroom@packman:bluefish-1.0.5$ ./configure --prefix=/usr/local/\\ checking for gcc... gcc\\ checking for C compiler default output file name... a.out\\ \\ [...]\\ \\ checking for a BSD-compatible install... /usr/bin/ginstall -c\\ checking build system type... i686-pc-linux-gnu\\ checking host system type... i686-pc-linux-gnu\\ \\ [...]\\ \\ checking for GNU gettext in libc... yes\\ checking for dcgettext... yes\\ checking for msgfmt... /usr/bin/msgfmt\\ checking for gmsgfmt... /usr/bin/msgfmt 1\\ checking for xgettext... /usr/bin/xgettext\\ checking for bison... no\\ checking for catalogs to be installed... bg cs da de es fi fr hu it ja no pl pt pt_BR ru sr sv ta tr zh_CN zh_TW \\ checking for msgmerge... /usr/bin/msgmerge\\ checking for gettext in -lintl... no\\ configure: creating ./config.status\\ config.status: creating Makefile\\ config.status: creating icons/Makefile\\ config.status: creating src/Makefile 2\\ config.status: creating po/Makefile\\ config.status: creating data/Makefile\\ config.status: creating src/config.h\\ config.status: executing default-1 commands\\ -----------\\ If you like this program, please let me know and send me\\ a postcard and tell me what city/country you're from:\\ \\ Olivier Sessink\\ Thorbeckestraat 470 3\\ 6702 CJ\\ Wageningen\\ The Netherlands\\ -----------\\ "
* Ce "configure teste si les gettext-tools" sont présents. Ceux-ci sont couramment utilisés pour internationnaliser les logiciels. Si vous souhaitez que les logiciels que vous compilez comportent une version française (quand elle est disponible, comme ici où la ligne "checking for catalogs to be installed comporte fr), installez le paquet gettext-tools contenu dans le répertoire d/" de la Slackware.
* Une fois tous les tests effectués, le "configure crée les Makefile", fichiers contenant les instructions pour la compilation.
* Il arrive que certains "configure" se terminent par un petit résumé des options retenues pour la compilation. Ce n'est pas le cas ici mais nous avons tout de même droit à un gentil clin d'oeil.
Soulignons pour finir sur les "configure" qu'il arrive hélas que certaines sources, anciennes ou avec une procédure de compilation inhabituelle, n'en contiennent pas. Dans pareil cas il convient de lire attentivement le "README" pour saisir comment la prise en main par l'utilisateur final a été pensée par les développeurs et agir en conséquence (en général cela passe par l'édition d'un "Makefile", nous présenterons plus tard un mode de gestion pour ce cas, cf. [[#patchdynIntégrer un patch dynamique]]).
=== Compiler et installer le binaire ===
Une fois les sources configurées avec succès, nous pouvons ordonner leur compilation via la commande "make (présente dans le paquet make du répertoire d/") :
" mushroom@packman:bluefish-1.0.5$ make
cd po/ && make all;
make[1]: Entering directory `/home/mushroom/bluefish-1.0.5/po'
[…]
/usr/bin/msgfmt fr.po -o fr.gmo
[…]
make[1]: Leaving directory `/home/mushroom/bluefish-1.0.5/po'
make[1]: Entering directory `/home/mushroom/bluefish-1.0.5/src'
gcc -DLOCALEDIR=\"/usr/local/share/locale\" -DGNULOCALEDIR=\"/usr/local/share/locale\" -DLOCALE_ALIAS_PATH=\"/usr /local/share/locale:.\" -DPKGDATADIR=\"/usr/local/share/bluefish/\" -DHAVE_CONFIG_H -g -O2 -Wall -pipe -DXTHREADS - D_REENTRANT -DXUSE_MTSAFE_API -I/usr/include/gtk-2.0 -I/usr/lib/gtk-2.0/include -I/usr/11R6/include -I/usr/include /atk-1.0 -I/usr/include/pango-1.0 -I/usr/include/freetype2 -I/usr/include/freetype2/config -I/usr/include/glib-2.0 -I /usr/lib/glib2.0/include -c -o about.o about.c
[…]
The bluefish binary is succesfully created
make[1]: Leaving directory `/home/mushroom/bluefish-1.0.5/src'
make[1]: Entering directory `/home/mushroom/bluefish-1.0.5/data
[…]
make[1]: Leaving directory `/home/mushroom/bluefish-1.0.5/data
"
Voici le flux grandement tronqué de ce que vous devriez obtenir avec "Bluefish. À ce stade, si le configure" a oublié de vérifier certains éléments, il peut encore se produire des erreurs liées à des problèmes de dépendances. Si votre système ne fait pas dans le minimalisme, cela est néanmoins assez rare car les éléments alors oubliés sont souvent très courants.
La compilation terminée, il va nous falloir installer le binaire. La commande standard d'installation, "make install, a pour effet de mettre les fichiers compilés dans le répertoire préfixé, pour ce qui nous concerne /usr/local. Outre le fait que nous n'avons pas les droits (seul le superutilisateur peut écrire dans /usr/local"), nous voulons faire un paquet en préalable à toute installation. C'est pourquoi il va d'abord falloir rediriger l'installation vers un dossier temporaire : un dossier différent de la destination finale et sur lequel nous aurons les droits nécessaires. Pour ce, il existe la variable "DESTDIR=<répertoire> [9] qui permet de moduler make install" :
" mushroom@packman:bluefish-1.0.5$ make install DESTDIR=/home/mushroom/bluefish-pkg
/usr/bin/ginstall -c -d -m 755 /home/mushroom/bluefish-pkg/usr/share/pixmaps
/usr/bin/ginstall -c -m 644 inline_images/bluefish_icon1.png /home/mushroom/bluefish-pkg/usr/share/pixmaps/bluefish- icon.png
[…]
make[1]: Entering directory `/home/mushroom/bluefish-1.0.5/src'
/usr/bin/ginstall -c -d -m 755 /home/mushroom/bluefish-pkg/usr/localbin
/usr/bin/ginstall -c -s -m 755 ./bluefish /home/mushroom/bluefish-pkg/usr/localbin/bluefish
[…]
make[1]: Leaving directory `/home/mushroom/bluefish-1.0.5/data'
"
La variable "DESTDIR=<répertoire>" [10] a pour effet de simuler une racine. Elle crée le dossier temporaire demandé avant d'y installer les fichiers comme si celui-ci était leur destination finale. On parle ici de dossier temporaire car lors de la configuration on a indiqué via "–prefix=<répertoire> que le binaire devait fonctionner dans /usr/local. Si vous lancez l'exécutable présent dans le dossier indiqué par DESTDIR, ici /home/mushroom/bluefish-pkg/usr/local/bin/bluefish", il ne fonctionnera donc pas [11].
Notre binaire est à présent prêt à être empaqueté, ce qui marque la fin de cette sous-section consacrée à la méthode de compilation standard. Tout ou presque de ce qui a été vu dans celle-ci est réutilisable sous n'importe quel autre système GNU/Linux. Cela étant dit, il est maintenant temps de commencer notre incursion dans la dimension Slackware à proprement parler en examinant son outil d'empaquetage : "makepkg".
==== L'empaqueteur Slackware : makepkg ====
Comme ses petits frères [12], "makepkg partage l'esprit KISS [13] des pkgtools et demeure un outil fort basique dans son utilisation. Pour s'en rendre compte, nous allons poursuivre notre exemple avec Bluefish" en allant au plus simple, car après tout l'objectif de cette partie est d'obtenir un paquet, pas un beau paquet.
Tout d'abord il faut se placer dans le dossier racine des fichiers à empaqueter, soit le répertoire temporaire d'installation défini par "DESTDIR" :
" mushroom@packman:bluefish-1.0.5$ cd /home/mushroom/bluefish-pkg/
mushroom@packman:bluefish-pkg$
"
Ensuite, nous passons en superutilisateur :
" mushroom@packman:bluefish-pkg$ su
Mot de passe:
root@packman:bluefish-pkg#
"
Enfin, nous lançons "makepkg suivi du <nom>.tgz" que nous souhaitons attribuer au paquet :
" root@packman:bluefish-pkg# makepkg bluefish-1.0.5-mypkg.tgz
Slackware package maker, version 2.1.
Searching for symbolic links:
No symbolic links were found, so we won't make an installation script.
You can make your own later in ./install/doinst.sh and rebuild the
package if you like.
This next step is optional - you can set the directories in your package
to some sane permissions. If any of the directories in your package have
special permissions, then DO NOT reset them here!
Would you like to reset all directory permissions to 755 (drwxr-xr-x) and
directory ownerships to root.root ([y]es, [n]o)?
"
Nous sommes tout d'abord informés qu'aucun lien symbolique n'a été trouvé dans le dossier et qu'il n'y a donc rien à faire les concernant. Autrement, on nous aurait demandé s'il fallait les rétablir après l'installation, ce qui aurait été fait grâce à un script prévu à cet effet, généré par "makepkg" et exécuté après l'installation des fichiers (cf. Utiliser des scripts de d'installation).
On nous demande ensuite si l'on veut formater les permissions des répertoires. Le formatage consiste à attribuer tous les fichiers au superutilisateur et à son groupe en permettant à tous de les voir et de les exécuter mais à lui seul d'écrire dedans (tapez "man chmod", pour un complément d'information). Comme nous n'avons pas de permissions spéciales, nous allons répondre « oui » en appuyant sur [y].
" Le mode d'accès de `.' a été modifié à 0755 (rwxr-xr-x).
Le mode d'accès de `./usr' a été modifié à 0755 (rwxr-xr-x).
Le mode d'accès de `./usr/share' a été modifié à 0755 (rwxr-xr-x).
Le mode d'accès de `./usr/share/pixmaps' a été modifié à 0755 (rwxr-xr-x).
[…]
Changement de propriétaire de `.' vers root:root
Changement de propriétaire de `./usr' vers root:root
Changement de propriétaire de `./usr/share' vers root:root
Changement de propriétaire de `./usr/share/pixmaps' vers root:root
[…]
Creating tar file bluefish-1.0.5-mypkg.tar…
./
usr/
[…]
usr/local/share/bluefish/
usr/local/share/bluefish/bluefish_splash.png
usr/local/share/bluefish/icon_c.png
[…]
usr/local/share/mime/
usr/local/share/mime/packages/
usr/local/share/mime/packages/bluefish.xml
usr/local/share/mime-info/
usr/local/share/mime-info/bluefish.mime
usr/local/share/mime-info/bluefish.keys
usr/local/bin/
usr/local/bin/bluefish
tar-1.13: bluefish-1.0.5-mypkg.tar is the archive; not dumped
Gzipping bluefish-1.0.5-mypkg.tar…
Renaming bluefish-1.0.5-mypkg.tar.gz to bluefish-1.0.5-mypkg.tgz…
Package creation complete.
"
Comme convenu, les permissions sont changées puis les répertoires sont attribués au superutilisateur. Ensuite ceux-ci et leur contenus sont archivés par la commande "tar puis l'archive est à son tour compressée par gzip", exactement de la même manière que pour des sources. Seul petit changement (purement formel), celle-ci troque finalement son extension « tar.gz » contre le « .tgz » caractéristique des paquets de la Slackware [14].
Nous voulions un paquet, et bien nous en avons un, vous pouvez vous en rendre compte de suite via la commande "installpkg bluefish-1.0.5-mypkg.tgz" : l'installation se déroule parfaitement. À tel point d'ailleurs que c'en est déconcertant, car quoi ! Est-ce donc ça l'empaquetage Slackware ? une méthode de compilation des plus banales suivie d'un archivage à la sauvette ? Et bien, oui et non… Oui tout d'abord parce que malgré une procédure rudimentaire notre paquet fonctionne. Non ensuite, car c'est un travail certes fonctionnel mais extrêmement grossier, ce qui sied fort mal à un système Slackware.
En fait, l'esprit Slackware consiste souvent à affiner les techniques tout en les laissant sous le contrôle de l'utilisateur final : permettre à l'humain de bien faire plutôt que laisser la technique le reléguer en bout de chaîne. Il est donc normal que la Slackware autorise des choses aussi inélégantes que ce que nous venons d'installer ("removepkg bluefish-1.0.5-mypkg.tgz" devrait remédier à la chose), il manque juste un humain entre les sources et le paquet. C'est en effet à lui qu'est laissé le soin de donner aux outils leur pleine mesure, et c'est à cet objectif que tentera de contribuer le mieux possible la seconde partie de ce petit manuel.
===== Le conditionnement Slackware =====
Alors que la précédente partie visait à donner des bases pour réussir à construire un binaire, la présente introduit la question des scripts de compilation Slackware. Nous examinerons dans un premier temps comment procède Patrick Volkerding pour compiler les binaires de sa distribution. Ensuite, sur la base de cet examen, nous exposerons différentes personnalisations envisageables.
==== Prendre une leçon de maître… ====
Comme nous l'avons vu dans la précédente section, la qualité des paquets Slackware est totalement liée à la qualité de ce qui est transmis à son empaqueteur. Tous le travail d'affinement et de préparation doit donc être effectué avant qu'un quelconque contenu ne soit fourni à "makepkg". Exposée comme cela, cette perspective apparaît vite aussi vague qu'angoissante, car on voit mal par quel bout aborder la chose et surtout sur quel critère déterminer un chemin un tant soit peu droit. Heureusement, une fois encore nous ne sommes pas laissés à nous-mêmes : « Aide-toi et ta Slack t'aidera ».
Si une personne doit être au fait de ce qu'est un paquet correctement formé, c'est bien le concepteur de la Slackware, Patrick Volkerding. Or, non content de mettre à disposition ses binaires, il nous a également laissé la recette de compilation pour chacun. En effet, si vous jetez un oeil dans les différents dossiers contenant les sources (cf. Où trouver les sources ?), vous verrez qu'ils comportent tous un fichier "<nom_du_logiciel>.SlackBuild". En les éditant, vous constaterez vite qu'ils partagent tous une trame commune, soit une base de travail solide pour nos propres recettes.
Pour la suite de cette partie, nous avons choisi de nous pencher sur le "SlackBuild de sed, un éditeur de flux texte (stream editor). Deux raisons à ce choix : d'une part ce SlackBuild est à peu près générique (pas de patch, ni d'ajouts inhabituels), d'autre part sed" est requis par le système, ce qui garantit une certaine pérennité à l'exemple.
Voici le texte complet du "SlackBuild de sed". Les sous-sections à venir en extrairont des fragments pour les commenter. Cela vous permettra, à l'aide des numéros de ligne, de vous reporter à tout moment au texte complet pour replacer le fragment concerné dans son contexte.
" 1 #!/bin/sh
2 CWD=`pwd`
3 PKG=/tmp/package-sed
4
5 VERSION=4.0.9
6 ARCH=${ARCH:-i486}
7 BUILD=2
8
9 if [ "$ARCH" = "i386" ]; then
10 SLKCFLAGS="-O2 -march=i386 -mcpu=i686"
11 elif [ "$ARCH" = "i486" ]; then
12 SLKCFLAGS="-O2 -march=i486 -mcpu=i686"
13 elif [ "$ARCH" = "s390" ]; then
14 SLKCFLAGS="-O2"
15 elif [ "$ARCH" = "x86_64" ]; then
16 SLKCFLAGS="-O2"
17 fi
18
19 rm -rf $PKG
20 mkdir -p $PKG
21 cd /tmp
22 rm -rf sed-$VERSION
23 tar xzvf $CWD/sed-$VERSION.tar.gz
24 cd sed-$VERSION
25 chown -R root.root
. 26 find . -perm 777 -exec chmod 755 {} \;
27 find . -perm 664 -exec chmod 644 {} \;
28 CFLAGS="$SLKCFLAGS" \
29 ./configure \
30 –prefix=/usr \
31 $ARCH-slackware-linux
32 make
33 make install DESTDIR=$PKG
34 mkdir -p $PKG/bin
35 mv $PKG/usr/bin/sed $PKG/bin
36 ( cd $PKG/usr/bin ; ln -sf /bin/sed . )
37 chown -R root.bin $PKG/usr/bin $PKG/bin
38 ( cd $PKG
39 find . | xargs file | grep "executable" | grep ELF | cut -f 1 -d : | xargs strip –strip-unneeded 2> /dev/null
40 find . | xargs file | grep "shared object" | grep ELF | cut -f 1 -d : | xargs strip –strip-unneeded 2> /dev/null
41 )
42 mkdir -p $PKG/usr/doc/sed-$VERSION
43 cp -a \
44 ANNOUNCE AUTHORS BUGS COPYING* INSTALL NEWS README README.boot THANKS TODO \
45 $PKG/usr/doc/sed-$VERSION
46 gzip -9 $PKG/usr/man/man?/*.?
47 rm -f $PKG/usr/info/dir
48 gzip -9 $PKG/usr/info/*
49 mkdir -p $PKG/install
50 cat $CWD/slack-desc > $PKG/install/slack-desc
51
52 cd $PKG
53 makepkg -l y -c n ../sed-$VERSION-$ARCH-$BUILD.tgz
"
=== Préambule : Qu'est-ce qu'un SlackBuild ? ===
Un "SlackBuild" n'est rien d'autre qu'un script, certes appliqué à la compilation, mais ne se différenciant pas fondamentalement des autres scripts. C'est à dire, hormis quelques fonctionnalités très spécifiques, qu'il ne fait que passer les commandes qu'il contient au système, comme le ferait l'utilisateur via son terminal. Vous pourriez donc, moyennant quelques remaniements mineurs, donner ces commandes une à une dans un terminal, vous obtiendriez au final le même résultat.
Nous allons tenter dans ce qui suit de découper ce "SlackBuild en mettant en évidence ses différentes phases. Nous ne nous attarderons donc pas sur les questions de syntaxe bash", sauf pour ce qui apparaît comme fondamental. Pour le lecteur peu familier avec cette syntaxe, nous avons mis en place un petit appendice (cf. Ration de survie **bash**) où il pourra trouver, nous l'espérons, le nécessaire pour suivre.
=== En tête : définition des variables ===
" 1 #!/bin/sh
2 CWD=`pwd`
3 PKG=/tmp/package-sed
4
5 VERSION=4.0.9
6 ARCH=${ARCH:-i486}
7 BUILD=2
8
9 if [ "$ARCH" = "i386" ]; then
10 SLKCFLAGS="-O2 -march=i386 -mcpu=i686"
11 elif [ "$ARCH" = "i486" ]; then
12 SLKCFLAGS="-O2 -march=i486 -mcpu=i686"
13 elif [ "$ARCH" = "s390" ]; then
14 SLKCFLAGS="-O2"
15 elif [ "$ARCH" = "x86_64" ]; then
16 SLKCFLAGS="-O2"
17 fi
"
La première ligne du script [15] indique le shell [16], l'interpréteur de commande, dans lequel doit être exécuté le script. Elle est présente sur tout script destiné à être exécutable [17]. Dans le cas présent il s'agit du Bourne Again Shell, appelé par le "#!/bin/sh (cela aurait pu être #!/bin/bash").
En "bash une variable se définit comme suit : <nom_de_la_variable>=<définition>. Pour l'appeler on utilise le symbole « $ » accolé au début son nom : $<nom_de_la_variable> (ou ${<nom_de_la_variable>}" dans sa version étendue). Elle est alors immédiatement remplacée par sa définition (on dit qu'elle est « expansée »). Nous avons ici, lignes 2 à 7, cinq variables de définies.
* "CWD qui récupère via la commande pwd" le chemin (absolu) du répertoire où est exécuté le script.
* "VERSION" qui définit la version du logiciel qu'on veut compiler.
* "PKG" qui indique le répertoire temporaire où mettre le binaire avant de l'empaqueter (cf. Compiler et installer le binaire).
* "ARCH" qui donne l'architecture pour lequel est compilé le paquet. Par défaut Patrick Volkerding optimise les paquets pour une construction sur un 486.
* "BUILD" qui correspond au numéro de compilation. Ici c'est la deuxième fois que le paquet a été compilé. Cela est utile lorsqu'on modifie un paquet sans que le logiciel compilé ait changé de version.
Lignes 9 à 17 suit une série de tests qui va déterminer les "FLAGS d'optimisation (cf. Configurer les sources). Dans notre cas $ARCH renvoie "i486", la série de test s'arrêtera par conséquent au deuxième test (l. 11). SLKCFLAGS, sixième variable définie ici, prendra donc la valeur -O2 -march=i486 -mcpu=i686 [18], soit une optimisation de niveau 2 (-O2) à partir d'un 486 pour une architecture i686" (regroupant, notamment, la série maintenant très courante des pentium4 et assimilés).
=== Initialisation et compilation ===
" 19 rm -rf $PKG
20 mkdir -p $PKG
21 cd /tmp
22 rm -rf sed-$VERSION
23 tar xzvf $CWD/sed-$VERSION.tar.gz
24 cd sed-$VERSION
25 chown -R root.root .
26 find . -perm 777 -exec chmod 755 {} \;
27 find . -perm 664 -exec chmod 644 {} \;
28 CFLAGS="$SLKCFLAGS" \
29 ./configure \
30 –prefix=/usr \
31 $ARCH-slackware-linux
32 make
33 make install DESTDIR=$PKG
"
On initialise en ordonnant la suppression du répertoire d'installation temporaire (l. 19). L'argument "-f (« force ») passé à la commande rm" fera qu'aucune erreur ne sera retournée si le répertoire n'existe pas. Initialiser de la sorte permet de s'assurer, entre autres, que le répertoire ne contiendra rien d'autre que ce qui sera généré par le script. Cela fait, on crée le répertoire temporaire avec la commande "mkdir (l. 20). Le -p" placé en argument demande de créer tous les répertoires indiqués dans le chemin s'ils n'existent pas déjà.
On passe dans le répertoire "/tmp (dédié, comme son nom l'indique plus ou moins, à ce qui est temporaire) à l'aide de la commande cd". On initialise à nouveau (l. 21), mais cette fois c'est le répertoire des sources qui est visé. Ensuite on décompacte l'archive en partant du principe que celle-ci est dans le répertoire courant : souvenez-vous de ce à quoi correspond "$CWD (pour les options de tar", cf. Récupérer et préparer l'archive). Cela fait, on entre dans le dossier ainsi généré [19] (l. 24).
Un fois dans le répertoire source, on initialise les permissions [20]. Le dossier entier est attribué au superutilisateur et à son groupe via la commande "chown (l. 25). Le -R" en argument indique que la commande est récursive : tout le contenu du dossier sera modifié. Ensuite on ordonne à la commande "find (l. 26-27) de rechercher tout ce qui est en permission 777 (droit de lecture, d'écriture et d'exécution pour tous) pour le transformer en 755 (droit d'écriture uniquement pour l'utilisateur, en l'occurence root), et tout ce qui est en 664 (droits de lecture et d'écriture pour l'utilisateur et le groupe, lecture seule pour les autres) en 644" (lecture seule pour tous hormis l'utilisateur). Cela tient au fait que le dossier source ne sera pas forcément détruit après la compilation (pas par le script en tout cas), il est donc bon que seul le superutilisateur soit autorisé à y écrire.
On affecte aux "CFLAGS le contenu de la variable SLKCFLAGS (l. 28), puis on passe les paramètres au configure (l. 29-31). La ligne $ARCH-slackware-linux" ne correspond pas à une commande, elle fournit juste une information sur la distribution et l'architecture de compilation, information que le binaire portera en lui (pour les autres lignes, cf. Configurer les sources).
Lignes 32-33, on procède à la compilation et à l'installation temporaire (cf. Compiler et installer le binaire).
=== Remaniements et affinements ===
" 34 mkdir -p $PKG/bin
35 mv $PKG/usr/bin/sed $PKG/bin
36 ( cd $PKG/usr/bin ; ln -sf /bin/sed . )
37 chown -R root.bin $PKG/usr/bin $PKG/bin
38 ( cd $PKG
39 find . | xargs file | grep "executable" | grep ELF | cut -f 1 -d : | xargs strip –strip-unneeded 2> /dev/null
40 find . | xargs file | grep "shared object" | grep ELF | cut -f 1 -d : | xargs strip –strip-unneeded 2> /dev/null
41 )
42 mkdir -p $PKG/usr/doc/sed-$VERSION
43 cp -a \
44 ANNOUNCE AUTHORS BUGS COPYING* INSTALL NEWS README README.boot THANKS TODO \
45 $PKG/usr/doc/sed-$VERSION
46 gzip -9 $PKG/usr/man/man?/*.?
47 rm -f $PKG/usr/info/dir
48 gzip -9 $PKG/usr/info/*
"
Une fois l'installation temporaire effectuée, on crée un répertoire "/bin dans le dossier temporaire (l. 34). Puis on déplace l'exécutable sed dans ce dossier [21] (l. 35). Ensuite, dans un sous-shell, on entre dans le dossier en question puis on crée avec la commande ln un lien symbolique de l'exécutable sed vers celui-ci (l. 35). La nature du lien est ici déterminée grâce à l'argument -s passé à ln, -f" commandant pour sa part l'écrasement d'un éventuel lien préexistant. Lier de la sorte évitera d'éventuels désagréments conséquents au changement de répertoire. Enfin, ligne 37, on affecte via "chown le propriétaire root et le groupe bin aux deux dossiers et à leur contenu [22] (-R" indique ici encore la récursivité).
Dans un sous-shell (l. 38-41), on entre dans le dossier temporaire puis on procède au stripping : l'affinement des exécutables et des bibliothèques dynamiques. On pratique cette opération car la compilation introduit dans les objets qu'elle génère des informations nécessaires à sa bonne conduite et au débogage mais ne jouant aucun rôle dans l'usage de son résultat. Ces informations pouvant doubler voir tripler la taille d'un binaire, une petite toilette s'impose donc, ce qui est la précisément mission du stripping. La commande utilisée ici use de nombreux tuyaux [23], il convient donc de distinguer chaque membre pour mieux comprendre le fonctionnement de l'ensemble. Nous nous référons à la première instance (l. 39), la seconde fonctionnant de la même manière mais avec pour objet les bibliothèques dynamiques au lieu des exécutables.
* "find ." va lister récursivement tous les fichiers présents dans le répertoire. Il a l'avantage de restituer cette liste ligne par ligne en donnant le chemin absolu de chaque dossier ou fichier. Cela le rend très pratique lorsqu'il est connecté à un tuyau (comparé à "ls" notamment).
* "xargs file est un composé de deux commandes : xargs qui sert à exécuter des commandes à partir de l'entrée standard et file qui retourne des informations sur la nature des fichiers. Ici xargs exécute file sur tous les fichiers envoyés par find".
* "grep" sert à extraire (et traiter) des chaînes de caractères à partir d'un fichier ou de l'entrée standard. Ici on lui ordonne d'extraire tous les résultats de "file qui contiennent "executable" puis de ne retenir parmi ceux-ci que ceux qui contiennent "ELF"" [24]. Cela a pour but de trier les fichiers concernés par le stripping car affiner un fichier en texte brut, par exemple, ne rime à rien.
* Si vous vous aventurez à tester "file sur un exécutable (ex. file /bin/bash"), vous vous apercevrez qu'il y a beaucoup d'informations. Or la seule qui nous intéresse, à présent que le tri est fait, c'est le chemin des fichiers retenus. C'est là qu'intervient "cut qui comme son nom l'indique sert à opérer des coupes. L'argument -f 1" lui ordonne de couper le premier champs de l'entrée standard, avec pour délimiteur de champs le caractère ":" indiqué par l'argument "-d . Appliqué au résutat d'une commande file" cela retourne juste ce que nous voulons : le chemin absolu des fichiers.
* Arrivés à la dernière extrêmité de notre commande, nous avons donc une série de fichiers affinables, ne reste plus qu'à les affiner effectivement. Pour ce, on ordonne à "xargs d'appliquer sur eux la commande strip. L'argument –strip-unneeded" évite un nettoyage trop abrasif qui détruirait des choses utiles : seul le superflux est enlevé. On remarquera au passage que les messages d'erreur et les avertissements qui auraient pu intervenir dans cette longue chaîne de commande sont tous envoyés vers "/dev/null" (l'équivalent de « nulle-part » pour le système).
Après l'affinement, on procède à la création du répertoire où l'on va stocker les « docs » (l. 42). Celles-ci correspondent aux fichiers informatifs contenu dans l'archive des sources ("README, INSTALL, NEWS, licences, etc… ). Tous les fichiers ainsi copiés (l. 43-45) sont propres au logiciel compilé, chaque Slackbuild a par conséquent une liste différente. Bien sûr il existe en la matière des noms de fichier standards (README et INSTALL" en sont), mais il y a toujours un certain flou dans ce qu'il convient d'intégrer ou non aux docs.
Lignes 46 à 49 intervient le traitement des man-pages et des info-pages. Celles-ci correspondent à deux formats de documentation. Le premier est lu via la commande "man, le second via la commande info. L'usage veut que toutes les man-pages soient compressées (l. 46) par gzip avec un taux de compression maximum (-9 en argument). On procède de même avec les info-pages (l. 48), à cette petite nuance que pour elles on prend soin de supprimer le fichier dir (l. 47). Celui-ci correspond à l'index général des info-pages, il est présent dans le paquet texinfo (répertoire ap/") et ne doit par conséquent pas être réécrit. Là encore les informations traitées ne le sont pas de manière générique mais de manière propre au logiciel empaqueté. Si par exemple "sed avait eu une man-page française, celle-ci n'aurait pas été compressée (elle aurait été dans $PKG/usr/man/fr/man?/").
=== Le fichier slack-desc ===
" 49 mkdir -p $PKG/install
50 cat $CWD/slack-desc > $PKG/install/slack-desc
"
Ligne 49 est créé un répertoire "install/". Celui-ci est un peu spécial en ce qu'il ne sera pas intégré dans le système de fichiers une fois le paquet installé. En fait il contient des informations sur le paquet et, le cas échéant, des scripts d'installation (cf. Utiliser des scripts de d'installation). Les informations sur le paquet sont contenues dans un fichier "slack-desc. C'est lui que la commande cat édite puis redirige dans install/ (l. 50). Avec les Slackbuild de Patrick, il est toujours mis à part dans le répertoire d'exécution du script. Un slack-desc" obéissant à des règles de rédaction précises, il convient de se pencher un peu sur ce fichier.
Voici reproduit le contenu du "slack-desc de sed" :
" # HOW TO EDIT THIS FILE:
# The "handy ruler" below makes it easier to edit a package description. Line
# up the first '|' above the ':' following the base package name, and the '|'
# on the right side marks the last column you can put a character in. You must
# make exactly 11 lines for the formatting to be correct. It's also
# customary to leave one space after the ':'.
|—–handy-ruler——————————————————|
sed: sed (stream editor)
sed:
sed: This is the GNU version of sed, a stream editor. A stream editor is
sed: used to perform basic text transformations on an input stream (a file
sed: or input from a pipeline). It is sed's ability to filter text in a
sed: pipeline which distinguishes it from other types of editors.
sed:
sed: sed is a required package (it is needed by many system scripts).
sed:
sed:
sed:
"
Comme on peut le voir, un "slack-desc" orthodoxe suit cinq règles :
* Il doit faire 11 lignes ni plus ni moins, chacune débutant par le nom du logiciel décrit.
* De la fin du nom du logiciel jusqu'à la fin d'une ligne, il y a 70 caractères maximum (ponctuations et blancs inclus), le "handy-ruler" montre d'ailleurs bien la limite.
* Le nom du logiciel débutant une ligne est toujours suivi de « : » puis d'un espace.
* La première ligne contient le nom du logiciel suivi entre parenthèses d'une brève définition de celui-ci.
* Le corps du "slack-desc" contient une description plus précise de ce qui caractérise le logiciel.
=== Empaquetage final ===
" 52 cd $PKG
53 makepkg -l y -c n ../sed-$VERSION-$ARCH-$BUILD.tgz
"
"Le slack-desc" en place, on entre dans la racine du répertoire d'installation temporaire (l. 51) pour procéder à l'empaquetage. Les arguments passés à "makepkg servent à répondre aux questions posées sans entrer dans le mode interactif (cf. L'empaqueteur Slackware : makepkg). Les liens symboliques seront donc conservés (-l y) et les permissions ne seront pas initialisées (-c n). Cette dernière opération est en effet inutile puisque le Slackbuild" s'en est déjà chargé, et de manière beaucoup plus fine.
Le paquet sera créé dans le répertoire parent de celui de l'installation temporaire (en l'occurence "/tmp) et il prendra la forme de <nom_du_logiciel>-<version>-<architecture>-<version_du paquet>.tgz (dans le cas qui nous occupe : sed-4.0.9-i486-2.tgz). Il est important pour un paquet de respecter cette structure de dénomination, autrement le slack-desc" ne sera pas affiché lors de l'installation, et cela risque de générer des ambiguïtés lors des mises à jour.
=== Conclusion : Que retenir ? ===
Après analyse d'un "Slackbuild" de Patrick Volkerding, il est possible de définir un cahier des charges auquel nos propres scripts de compilation devront se plier :
- Les exécutables doivent être installés dans le bon dossier selon leur importance pour le système.
- La propriété du paquet doit être accodée au superutilisateur et à son groupe.
- Les exécutables et bibliothèques dynamiques doivent être affinés [25].
- Les « docs » doivent être récupérées et stockées dans "/usr/doc/<nom_du_paquet>-<version>" [26].
- Les man-pages doivent être compressées par "gzip" avec un taux de compression maximum. De même pour les info-pages pour lesquelles il faut en plus prendre soin de supprimer l'index.
- Le "slack-desc doit être rédigé comme il se doit et copié dans install/".
- Le nom du paquet doit respecter la forme "<nom_du_logiciel>-<version>-<architecture>-<version_du paquet>.tgz".
Une fois n'est pas coutume, on peut constater que la Slackware base sa construction de paquet sur un fondement relativement simple à respecter. C'est précisément en tirant parti de cette simplicité et de son potentiel en variations que nous allons maintenant examiner quelques clés pour bâtir des recettes personnelles.
==== …pour aller son chemin ====
Nous avons achevé la précédente étude d'un script de compilation Slackware par l'établissement d'un cahier des charges. Tout ce qui va suivre se borne à présenter différentes options pour s'y conformer. Il n'y a donc aucune obligation d'aucune sorte à utiliser le matériel donné : c'est à vous et à vous seul d'estimer s'il vous est plus pratique ou non d'adopter ces manières de faire.
Pour éviter de trop surcharger les codes en déclaration de variables, nous mettrons ici une en-tête que vous devrez considérer comme débutant chacun d'eux [27] :
" #!/bin/sh
### Informations sur le paquet
PKG_NAME="paquet"
# nom du paquet.
PKG_VERSION="version"
# version du paquet.
PKG_BUILD="1"
# version de la compilation du paquet.
PKG_ARCH=i486
# architecture du paquet
### Paramètres de construction du paquet
FINAL_DIR="/usr/local"
# dossier où sera installé le paquet.
CONF_OPT="–prefix=${FINAL_DIR}"
# options à passer au configure.
TMP_DIR="/tmp/${PKG_NAME}_tmp"
# dossier d'installation temporaire.
BUILD_DIR="/var/log/manufacture"
# dossier où sera placée la copie verbatim du script.
ADD_FILES=${HOME}/add2package.tar.gz
# archive contenant les fichiers supplémentaires.
MK_INSTALL="make install DESTDIR=${TMP_DIR}"
# commande pour l'installation temporaire.
"
=== Intégrer le slack-desc ===
Nous avons vu que les "Slackbuild de Patrick Volkerding allaient chercher leur slack-desc" à l'extérieur (cf. Le fichier slack-desc). Il peut sembler plus commode à certains d'intégrer celui-ci directement dans le corps du script, histoire de n'avoir qu'un seul fichier à manier. Une simple exploitation de la commande "cat" peut donner satisfaction :
" 1 cat > ${TMP_DIR}/install/slack-desc << D3SC3ND
2
3 ${PKG_NAME}: ${PKG_NAME} (brève description)
4 ${PKG_NAME}:
5 ${PKG_NAME}: Ceci est un super programme que je fais semblant d'empaqueter pour
6 ${PKG_NAME}: exposer comment on peut intégrer le slack-desc au script de
7 ${PKG_NAME}: compilation.
8 ${PKG_NAME}:
9 ${PKG_NAME}:
10 ${PKG_NAME}:
11 ${PKG_NAME}:
12 ${PKG_NAME}:
13 ${PKG_NAME}:
14 D3SC3ND
15 # |—–handy-ruler——————————————————|
16
"
La commande "cat (l. 1) va éditer le texte du fichier jusqu'à ce qu'elle rencontre le terme « D3SC3ND" » [28] (l. 14).
Toutes les variables seront expansées puis le résultat sera écrit dans le "slack-desc" créé dans le répertoire approprié.
=== Partager les rôles entre utilisateur et superutilisateur ===
La compilation en superutilisateur est généralement considérée comme une hérésie de premier ordre. Cela est a priori tout à fait fondé, puisqu'un "Makefile" exécuté avec les droits administrateur peut potentiellement écrire n'importe où et n'importe quoi sur le système. Il faut toutefois rationnaliser la chose lorsqu'on se contente d'exécuter un "Slackbuild" sur une source issue d'un miroir Slackware officiel :
* si on en est à se méfier de Patrick Volkerding, autant changer de distribution;
* les logiciels proposés par la Slackware ne sont pas vraiment d'obscurs petits logiciels sortis d'on ne sait où, mais très souvent des standards;
* le résultat de ces compilations est soumis au regard de nombreux utilisateurs, si bien qu'un hypothétique vice de forme a peu de chances de rester longtemps inaperçu.
Travailler avec du matériel officiel Slackware offre donc quelques sécurités rendant la compilation en superutilisateur acceptable. Ces sécurités sont cependant moins pertinentes pour un empaquetage personnel. En effet, sans aller jusqu'à soupçonner une volonté de nuire, il arrive que les "Makefile ne soient pas toujours très au point, surtout sur les projets un peu jeunes. Une mauvaise gestion de la préfixation via DESTDIR", par exemple, et nous nous retrouvons avec des fichiers installés dans le système sans dispositif de désinstallation. C'est pour cela qu'il peut sembler souhaitable de ne réserver au superutilisateur que les tâches le requierant, à savoir le changement final des droits et l'empaquetage.
" 1 cat > r00t-3x3c << R00T3ND
2
3 chown -R root:root ${TMP_DIR}
4
5 cd ${TMP_DIR}
6 makepkg -l y -c n ../${PKG_NAME}-${PKG_VERS}-${PKG_ARCH}-${PKG_BUILD}sbb.tgz
7
8 R00T3ND
9
10 DONE="KO"
11 while [ ! ${DONE} == "OK" ]; do
12
13 su -c 'source r00t-3x3c' && DONE="OK"
14
15 done
26
"
Nous allons employer la technique impliquant "cat vue avec l'intégration du slack-desc. Celle-ci s'arrêtera ici à « R00T3ND » (l. 8) et écrira dans r00t-3x3c".
Nous commençons par initialiser le propriétaire et le groupe des fichiers (l. 3), comme dans le "Slackbuild" (cf. Remaniements et affinements).
Nous nous plaçons à la racine du dossier d'installation temporaire (l. 5), puis nous procédons à l'empaquetage (l. 6). Le paquet sera créé dans le répertoire père de celui-ci.
À ce stade (l. 9), ce que nous avons décrit dans les deux points précédents attend dans un fichier d'être exécuté. C'est donc ici qu'il nous faut négocier notre passage en superutilisateur.
Dans une boucle "while (l. 11-15), nous plaçons la commande su (l. 13) qui sert à changer d'utilisateur [29]. Sans autre argument elle provoque un passage en superutilisateur. L'argument -c" qui suit sert à exécuter une commande unique avec l'utilisateur en question avant de reprendre l'utilisateur initial. La commande que nous avons donnée ici est "source" qui intègre un fichier extérieur comme s'il faisait partie du script courant. Autrement dit nous allons ici exécuter tout ce que nous avons envoyé dans le fichier "r00t-3x3c" avec les droits du superutilisateur, soit exactement le but recherché.
La boucle "while" sert dans ce cadre de filet de secours. En effet il serait très gênant d'être contraint de réexécuter entièrement le script suite à un cafouillage dans le mot de passe, ce d'autant que le superutilisateur n'intervient normalement qu'à la toute fin. La boucle garantit donc une certaine solidité à la procédure : "su" sera répétée tant qu'elle n'aura pas été exécutée avec succès.
=== Rendre la compression des man-pages générique ===
Selon que le logiciel est ou non internationalisé, les man-pages peuvent se situer en diverses arborescences, ce qui oblige normalement à vérifier cela systématiquement. Aussi, afin de ne pas toujours devoir y prendre garde, il peut être utile d'utiliser une procédure qui recherchera et compressera automatiquement celles-ci où qu'elles soient. Voici comment faire :
" 1 TARGET=( $(find ${TMP_DIR} -type d -iname man) )
2
3 for ITEM in ${TARGET[@]}; do
4
5 gzip -9 ${ITEM}/man?/*.? 2>/dev/null
6 gzip -9 ${ITEM}/*/man?/*.? 2>/dev/null
7
8 done
9
10 TARGET=( $(find ${TMP_DIR} -type d -iname info) )
11
12 for ITEM in ${TARGET[@]}; do
13
14 rm -f ${ITEM}/dir
15 gzip -9 ${ITEM}/*.info* 2>/dev/null
16
17 done
18
"
On commence par récupérer dans une liste le résultat de la commande "find recherchant dans le dossier temporaire tous les répertoires ( argument -type d) nommés « man" » (l. 1).
Lignes 3 à 8, pour chaque répertoire dans la liste on donne un premier patron de chemin. Ainsi tout ce qui appartient à un sous-répertoire "man" suivi d'un caractère et possède une extension d'un caractère, indice de man-page [30] sera compressé (l. 5). Il en résultera une compression de toutes les man-pages anglaises.
Pour les pages internationalisées, il y a un répertoire supplémentaire dans le chemin. Ainsi la man-page française de "su se situe-t-elle dans /usr/man/fr/man1/. C'est pourquoi on soumet chaque répertoire à un deuxième patron (l. 6) qui permettra de compresser toutes les man-pages internationalisées. Pour chacun des patrons, notez qu'on a rejeté vers /dev/null" les erreurs qui surviendront si rien n'est trouvé qui y corresponde. Cela est en effet ici sans importance.
Lignes 10 à 17, on répète la même opération pour les info-pages dans chaque dossier "info/ trouvé. On prend soin cette fois de supprimer le fichier dir éventuellement présent puis on ordonne la compression de tous les fichiers ayant une extension .info".
=== Intégrer une copie du script de compilation dans le paquet ===
Lorsqu'on opère souvent des changements sur ses scripts de compilation, il peut s'avérer intéressant de conserver dans chaque paquet une copie du script qui l'a compilé. Cela afin de pouvoir évaluer le traitement que celui-ci a ou non subi et ainsi décider de l'opportunité d'une recompilation. On peut également vouloir le faire à des fins d'information pour les destinataires du paquet. Quelqu'en soit le motif, la réalisation en est très basique :
" 1 mkdir -p ${TMP_DIR}/${BUILD_DIR}
2
3 cat ${0} >${TMP_DIR}/${BUILD_DIR}/${PKG_NAME}
4
5 chmod 644 ${TMP_DIR}/${BUILD_DIR}/${PKG_NAME}
6
"
On crée le répertoire de destination avec "mkdir" (l. 1).
On envoie avec cat le contenu du fichier que l'on est en train d'exécuter, à savoir notre script d'empaquetage, vers un fichier situé dans le répertoire de destination qui portera le même nom que le paquet (l. 3).
On attribue avec "chmod" au fichier ainsi généré le droit de lecture pour tout le monde et les droits d'écriture et de lecture pour le propriétaire (l. 5). Il en résultera à la fin de l'empaquetage que seul le superutilisateur pourra le modifier (cf. Initialisation et compilation) et que nul ne pourra l'exécuter. Cela est une bonne politique puisque, rappelons-le, ce fichier est là uniquement à des fins d'information.
=== Intégrer un patch dynamique ===
Commençons par expliquer rapidement en quoi consiste un patch. Un patch consiste à retenir en un fichier C les différences entre un fichier A et un fichier B. Celui-ci est ensuite donné en argument à la commande "patch" qui l'appliquera au fichier A pour le rendre absolument identique au fichier B.
Cette technique est très utilisée pour diffuser des correctifs de logiciels et ainsi permettre à tout le monde de bénéficier des débogues dans pour autant retélécharger une version complète du logiciel à problème. Dans le cadre de ce petit manuel, vous pouvez bien entendu employer cette technique à des fins correctrices, néanmoins il y a pour nous un autre intérêt à "patch".
Nous avons en effet évoqué plus haut le cas de certains logiciels ne proposant pas de "configure et nécessitant en conséquence une édition manuelle de leur Makefile (cf. Configurer les sources). Grâce à patch nous pouvons élaborer une solution pour qu'un Makefile" soit automatiquement modifié selon nos paramètres :
" #
# Makefile - Un faux Makefile.
#
PREFIX=/usr
BINDIR=${PREFIX}/bin
DESTDIR=
MANDIR=${PREFIX}/man
# fin_de_fichier
"
Voici un "Makefile imaginaire [31]. Nous avons ici deux variables intéressantes à traiter : d'une part la variable PREFIX, qui nous permettra de déterminer où installer finalement notre logiciel, d'autre part la variable DESTDIR", requise pour l'installation temporaire préalable à l'empaquetage.
" mushroom@packman:~$ cat Makefile > Makefile_ok
"
Nous réalisons via cat une copie du "Makefile vers un fichier Makefile_ok, qui correspondra au Makefile" tel que nous le voulons.
" #
# Makefile - Un faux Makefile.
#
PREFIX=${FINAL_DIR}
BINDIR=${PREFIX}/bin
DESTDIR=${TMP_DIR}
MANDIR=${PREFIX}/man
# fin_de_fichier
"
Dans "Makefile_ok", nous souhaitons que les variables soit attribuées conformément aux définitions de l'en-tête de notre script. Aussi c'est tout naturellement que nous attribuons à "PREFIX la valeur de FINAL_DIR, et à DESTDIR la valeur de TMP_DIR". Une fois cela effectué, nous sauvegardons le fichier.
" mushroom@packman:~$ diff -au Makefile Makefile_ok >correctif
"
Il nous faut maintenant obtenir le différentiel entre les deux fichiers, c'est le travail de la commande "diff [32]. Nous lui ordonnons de stocker dans le fichier correctif le différentiel permettant d'obtenir Makefile_ok à partir de Makefile. Les arguments a et u" indiquent respectivement que les fichiers sont à traiter comme du texte et qu'il faut employer le format unifié pour le différentiel, format préféré pour les petites modifications.
" — Makefile 2006-01-23 22:50:48.000000000 +0100
+ Makefile_ok 2006-01-23 22:51:06.000000000 +0100
@@ -2,9 +2,9 @@
# Makefile - Un faux Makefile.
#
-PREFIX=/usr
+PREFIX=${FINAL_DIR}
BINDIR=${PREFIX}/bin
-DESTDIR=
+DESTDIR=${TMP_DIR}
MANDIR=${PREFIX}/man
# fin_de_fichier
"
Voici à quoi ressemble le contenu de notre fichier correctif au format unifié. Le principe en est en fait très simple : il indique que chaque ligne commençant par un "- sera remplacée par la ligne suivante commençant par un +", les lignes sans marques servant à évaluer le contexte de chaque changement.
On remarque également en haut, précédés de "— et de + le nom des fichiers concernés. Cela est important car patch" en tirera deux informations : d'une part que les fichiers sont dans un même répertoire, d'autre part que le fichier cible se nomme "Makefile".
" patch -sp0 << P4TCH_F1N\\ --- Makefile 2006-01-23 22:50:48.000000000 +0100\\ +++ Makefile_ok 2006-01-23 22:51:06.000000000 +0100\\ @@ -2,9 +2,9 @@\\ # Makefile - Un faux Makefile.\\ #\\ -PREFIX=/usr\\ +PREFIX=${FINAL_DIR}\\ BINDIR=\${PREFIX}/bin\\ -DESTDIR=\\ +DESTDIR=${TMP_DIR}\\ MANDIR=\${PREFIX}/man\\ \\ # fin_de_fichier\\ \\ P4TCH_F1N\\ "
À présent, il ne nous reste plus qu'à embarquer notre patch dans notre script. Nous procédons pour ce faire comme précédemment avec "cat. Tout ce qui est compris entre la commande patch et P4TCH_F1N lui sera passé. L'argument s indique de ne pas imprimer le rapport d'exécution sur la sortie standard. L'argument p0, pour sa part, demande de conserver les chemins indiqués en haut du différentiel. Ainsi le fichier Makefile" ne sera recherché que dans le répertoire courant, ce qui implique que la commande soit exécutée à partir du répertoire des sources [[#note_33[33]]].
Dernière petite opération, on ajoute des « "\ » devant ${PREFIX}. En effet, celle-ci est signifiante pour le Makefile mais pas pour notre script. Or comme pour la commande cat, toutes les variables passées à patch seront préalablement expansées [34]. Il nous faut donc protéger ${PREFIX} afin qu'elle ne soit pas interprétée, ce que nous faisons en indiquant grâce à « \ » que « $" » doit être traité comme un caractère normal et non comme l'introduction d'un variable.
=== Traiter une archive de manière indifférenciée ===
Il arrive que les sources des logiciels soient proposées en plusieurs formats de compression (cf. Récupérer et préparer l'archive), ce qui oblige logiquement à changer les commandes de décompression du script selon qu'on opte pour l'un où l'autre. On peut aussi choisir d'automatiser cette phase afin que le script se débrouille seul avec ce qui lui est donné :
" 1 TARGET="$(file -z ${1} | grep "tar archive" | cut -f 2 -d "(" | cut -f 1 -d "," | sed s/" "*)"
2
3 case ${TARGET} in
4
5 'bzip2 compressed data')
6
7 tar xfj ${1} -C /tmp
8 TARGET=$(tar tf ${1} | sed -n 1p | cut -f 1 -d /)
9 cd /tmp/${TARGET}
10 ;;
11
12
13 'gzip compressed data')
14
15 tar xfz ${1} -C /tmp
16 TARGET=$(tar tf ${1} | sed -n 1p | cut -f 1 -d /)
17 cd /tmp/${TARGET}
18 ;;
19
20 *)
21
22 echo "Type d'archive inconnu : arrêt."
23 exit 1
24
25 esac
26
"
On part ici du principe que le script est exécuté avec en premier argument le nom de l'archive à traiter (ex. "script.sh toto-9.99.tar.gz). La première ligne va récupérer le type de compression de l'archive. Celle-ci est d'abord soumise à la commande file" [35] qui envoie en sortie des informations sur sa nature, notamment son type de compression :
" toto-9.99.tar.gz: POSIX tar archive (gzip compressed data, from […]
"
La commande "grep récupère alors cette sortie si celle-ci est bien une archive de type tar, puis passe le résultat de ses recherches à deux commandes cut" successives. La première isole la chaîne de caractères qui est derrière la première parenthèse, la seconde celle qui est avant la première virgule. Enfin le tout est passé à "sed" qui supprimera les espaces consécutifs afin d'éliminer toute ambiguïté dans la chaîne.
Lignes 3 à 25, il ne reste plus qu'à évaluer la chaîne récupérée. Si celle-ci est égale à "bzip2 compressed data (l. 5), alors l'archive est décompressée en conséquence par la commande tar (argument j) et le résultat de la décompression est envoyé vers le dossier /tmp/ (l. 7) indiqué après l'argument -C".
On récupère alors la racine de l'archive (l. 8) en ordonnant à "tar de lister le contenu de l'archive puis en passant sa sortie à sed" qui n'en retiendra que la première ligne. Pour être sûr qu'il s'agit bien de la racine, on passera ensuite cette première ligne à "cut qui isolera la chaîne avant le premier « / ». Le résultat de cette séquence sera récupéré dans la variable TARGET", écrasant son ancienne valeur désormais inutile.
Ligne 9, on se place grâce à "cd dans le répertoire des sources que l'on a envoyé dans /tmp/ : on forme le chemin en ajoutant à /tmp/" le nom du répertoire racine de l'archive source. Nous voici prêts à procéder à la compilation. Cette méthode permet donc non seulement de ne pas se soucier de la décompression, mais en plus de ne pas connaître le nom du dossier généré par la décompression de l'archive. Quelque soit l'archive qui est passée en argument, il est donc probable que cette procédure fonctionnera sans qu'il n'y ait rien à toucher.
Lignes 13 à 18, on répète la procédure précédemment décrite si la chaîne est égale à "gzip compressed data, avec cette seule différence que tar aura z au lieu de j" en argument.
Lignes 20 à 25, si jamais cette chaîne ne correspond ni à "gzip compressed data ni à bzip2 compressed data", alors le script retourne qu'il ne reconnaît pas l'archive et provoque une sortie en erreur [36].
=== Gérer l'ajout de fichiers supplémentaires avec fluidité ===
Il peut arriver qu'on souhaite embarquer dans le paquet final certains fichiers utiles en plus de ceux fournis par les sources. Cela peut facilement être obtenu en mettant ces fichiers dans l'arborescence voulue à l'intérieur d'une archive tar qu'on décompressera ensuite dans le répertoire d'installation temporaire.
Un problème reste cependant, car il faudra pour ce faire connaître le répertoire d'installation final du logiciel, celui préfixé lors de la configuration des sources (cf. Configurer les sources). En effet, en admettant que nous voulions placer une icone dans le répertoire "share/ de notre logiciel, il faudra savoir si le chemin de celui-ci est /usr/share/ ou /usr/local/share/".
L'équation se complique encore lorsqu'on considère que si certains fichiers sont relatifs à notre chemin d'installation final, d'autres demeurent quoiqu'il arrive. Par exemple un fichier de configuration placé dans "/etc/" n'a pas vraiment de raison de changer de chemin.
Deux solutions se présentent à nous pour surmonter ces difficultés. La première consiste à refaire l'archive des fichiers supplémentaires à chaque fois que le chemin de destination finale change, soit une solution assez contraignante. La seconde passe par la séparation au sein de notre archive de ce qui est relatif à notre chemin d'avec ce qui est absolu. C'est celle-ci que nous allons exposer. Commençons par constituer notre archive :
" mushroom@packman:~$ mkdir -p absolute/etc/
mushroom@packman:~$ cp soft.conf absolute/etc/
mushroom@packman:~$ mkdir -p relative/share/soft/
mushroom@packman:~$ cp icon.png relative/share/soft/
mushroom@packman:~$ tar vcfz add2package.tar.gz absolute/ relative/
absolute/
absolute/etc/
absolute/etc/soft.conf
relative/
relative/share/
relative/share/soft/
relative/share/soft/icon.png
mushroom@packman:~$
"
Notre but est ici de créer une archive qui, une fois décompressée, ajoutera un fichier de configuration dans "/etc/ et une icone dans le répertoire share/ du répertoire d'installation de notre logiciel. Nous donnons pour cela à notre archive deux racines distinctes : dans absolute/ nous plaçons tous les fichiers qui ne doivent pas changer de chemin, dans relative/ tous ceux qui suivront la préfixation du configure".
Avec "mkdir, nous créeons les dossiers du chemin absolute/etc/ puis nous y copions grâce à cp notre fichier soft.conf. Nous faisons de même avec les dossiers du chemin relative/share/soft/ [37] au bout duquel nous plaçons icon.png".
Une fois que nous avons nos deux dossiers complets, nous les mettons tous deux dans une archive "tar nommée add2package.tar.gz et compressée par gzip. L'argument c indique ici à tar" de créer une archive, son nom étant indiqué immédiatemment après la série d'arguments (pour les autres arguments cf. Récupérer et préparer l'archive). La sortie de la commande montre l'arborescence contenue dans l'archive. Ne reste plus qu'à gérer cela dans le script d'empaquetage.
" 1 ABS_ADD=/tmp/absolute
2 REL_ADD=/tmp/relative
3
4 cd ${TMP_DIR}
5
6 rm -fr ${ABS_ADD}
7 rm -fr ${REL_ADD}
8
9 tar xfz ${ADD_FILES} -C /tmp
10
11 if [ -d ${ABS_ADD} ]; then
12
13 (
14 cd ${ABS_ADD}
15 tar cf /tmp/tampon ./*
16 )
17
18 tar xf /tmp/tampon -C ./
19
20 fi
21
22 if [ -d ${REL_ADD} ]; then
23
24 (
25 cd ${REL_ADD}
26 tar cf /tmp/tampon ./*
27 )
28
29 tar xf /tmp/tampon -C ./${FINAL_DIR}
30
31 fi
32
"
Lignes 1 à 8, nous initialisons la procédure. Nous déclarons les variables "ABS_ADD et REL_ADD (l. 1-2) qui correspondront aux dossiers de notre archive une fois ceux-ci décompressés dans /tmp/". Après quoi nous nous plaçons dans le dossier d'installation temporaire (l. 4), puis nous ordonnons la suppression des dossiers précédemment déclarés (l. 6-7) [38].
Ligne 9, nous décompressons l'archive des fichiers supplémentaires vers "/tmp/ grâce à l'option -C de tar".
Lignes 11 à 20, nous testons si le dossier "/tmp/absolute existe. Si c'est le cas, dans un sous-shell nous nous plaçons dans celui-ci puis nous générons une archive tampon" à partir de son contenu (l. 15) [39]. De retour à la racine de notre dossier temporaire (l. 18), nous décompressons cette archive dans le répertoire courant, faisant ainsi concorder la racine du dossier "absolute/" avec celle de notre futur paquet.
Lignes 22 à 31, nous répétons la même procédure [40] avec le dossier "/tmp/relative, à cette différence que l'archive tampon ne sera pas décompressée dans le répertoire courant mais dans FINAL_DIR à partir du répertoire courant. Cela permet ainsi de faire suivre dynamiquement aux fichiers de notre dossier relative/ le même chemin qu'indiqué dans FINAL_DIR", ce sans avoir à restructurer l'archive de nos fichiers supplémentaires.
=== Utiliser des scripts de d'installation ===
L'utilisation de scripts d'installation n'est pas à proprement parler une personnalisation, mais plutôt l'exploitation de certaines fonctionnalités du gestionnaire de paquet de la Slackware.
Le but d'un script d'installation est tout simplement d'exécuter certaines commandes une fois le paquet installé, en général pour parfaire leur intégration au système.
Leur mise en oeuvre dans un script d'empaquetage est identique à celle du "slack-desc" (cf. Intégrer le slack-desc), exception faite de la cible. Pour définir celle-ci, il faut tout d'abord savoir quel type de script vous voulez utiliser car il en existe en effet plusieurs.
Plutôt que de nous lancer dans de longues explications, nous proposons ici une traduction commentée de la section « INSTALLATION SCRIPTS » rédigée par Patrick Volkerding dans la man-page de "makepkg" :
« Il y a 3 types de scripts d'installation supportés par le système de paquet Slackware.
Le premier type regroupe les script d'installation primaires. Ils se trouvent dans "./install" et doivent se nommer doinst.sh pour être reconnus. Il doivent également (eux et les autres scripts d'installation) être écrits conformément à la syntaxe du Bourne shell de base telle que reconnue par le Ash shell, car c'est ce shell qui sera utilisé pour exécuter ces scripts si vous faites une installation à partir d'une disquette d'installation Slackware. C'est un piège courant, prenez garde à ne pas utiliser la syntaxe "bash", car les scripts fonctionneront bien s'ils sont installés à partir du disque dur mais planteront s'ils sont installés à partir d'une disquette. Lorsque le paquet est destiné à un usage personnel, cela n'est pas un problème. Attention, cependant, si vous comptez partager votre paquet avec d'autres utilisateurs. Les script d'installation primaires sont exécutés immédiatement après l'installation du paquet par "installpkg, pkgtool, ou setup". »
* Si jamais vous êtes amené à inclure un script d'installation dans vos paquets, c'est probablement ce type de script que vous utiliserez. Il doit être stocké [41] dans "install/doinst.sh" et est exécuté immédiatement après l'installation du paquet . Voici un exemple basique de ce que pourrait être un tel script [42] intégré dans notre script d'empaquetage : " cat >${TMP_DIR}/install/doinst.sh<<TH33ND
update-mime-database ${FINALDIR}/share/mime
TH33ND
"
Ici, il servirait à mettre automatiquement à jour la base de donnée de "shared-mime-info" [43] employée par certains logiciels pour partager leurs fichiers mime [44].
* Le Ash shell a pour vocation de rester le plus proche possible du Bourne shell, le shell UNIX historique. Le shell bash (Bourne Again SHell) étant un Bourne shell revu et augmenté , il se peut que sa syntaxe pose problème au Ash shell. Il est par conséquent conseillé soit d'installer ce dernier pour tester les scripts [45], soit de travailler à faire des scripts les plus simples possibles au niveau de la syntaxe [46].
« Le second regroupe les scripts de configuration. Ils se situent dans le sous-répertoire "./var/log/setup" et doivent porter un nom commençant par « setup » pour être reconnus. Un exemple en est le script de fuseau horaire : "/var/log/setup/setup.timeconfig. Ces scripts sont exécutés pendant la phase CONFIGURE du setup et sont ré-exécutés à chaque fois que l'utilisateur lance l'option CONFIGURE à partir de setup" lorsqu'arrivera la dite phase. En règle générale, l'utilisateur passera au travers de cette phase du setup, poursuivant l'installation de tous les paquets. Tout ce qui a besoin d'être interactif devrait être contenu dans un de ces scripts afin d'éviter de suspendre la procédure d'installation du paquet au cours du setup. »
* Il est peu vraisemblable que vous ayez jamais à manipuler de tels scripts. En effet, ils ne servent que durant la phase "SETUP de l'installation Slackware ou via l'option du même nom proposée par la commande pkgtool" [47]. Autant dire qu'ils ne sont utiles que pour des paquets susceptibles d'être appelés durant l'installation initiale.
* Ces scripts servent généralement pour la détection du matériel et la configuration de certains services : "netconfig ou xwmconfig" en sont de bons exemples. Comme ils ne sont pas automatiquement exécutés lors de l'installation du paquet, vous pouvez toujours, si vraiment vous devez les utiliser, faire un script d'installation primaire prévenant l'utilisateur de la nécessité de les lancer et appelant "pkgtool" :
" cat >${TMP_DIR}/install/doinst.sh<<TH33ND
echo "Ce paquet contient un script de configuration 'totoconfig' \
qui doit être exécuté via l'option SETUP de 'pkgtool'."
echo "Lancement de 'pkgtool' dans 5 secondes…"
sleep 5s
pkgtool
TH33ND
"
Les messages seront affichés après l'installation du paquet, puis la commande "sleep marquera une pause de cinq secondes avant de lancer pkgtool". Gardez cependant à l'esprit que, comme indiqué, ces scripts ne devraient être mis en oeuvre que pour ce qui nécessite l'entrée d'informations de la part de l'utilisateur. Dans tous les autres cas, préférez les scripts d'installation primaires.
« Le troisième regroupe les scripts onlyonce [48]. Comme l'indique leur nom et à la différence des scripts de configuration standards, ils sont exécutés seulement une fois après l'installation du paquet. Ces scripts se situent également dans le sous-répertoire "./var/log/setup" et leurs noms, en plus commencer par « setup », doivent également contenir la chaîne « onlyonce ». À titre d'exemple, on pourrait imaginer un script portant le nom "/var/log/setup/setup.onlyonce.testscript". »
* Cette famille de scripts se comporte en fait exactement comme celle des scripts d'installation secondaires. La distinction dont il est question ici n'avait en effet de sens qu'avec l'ancienne commande "setup" [49].
===== Conclusion =====
Tout en se basant sur des techniques éprouvées, l'empaquetage façon Slackware ouvre néanmoins de larges perspectives de raffinement.
Rien de bien nouveau n'est en effet introduit dans la manière de faire elle-même : la procédure de compilation employée est tout ce qu'il y a de plus habituelle, et la qualité du paquet repose entièrement sur celle du code de l'empaqueteur.
Au final cependant, c'est peut-être bien là qu'il faut chercher le trait distinctif de l'empaquetage Slackware par rapport à ce qu'on trouve ailleurs. En ne proposant aucun outil d'automatisation, celui-ci laisse de ce fait au jour chacune des étapes simples qui le composent. Il en résulte qu'une étude détaillée de celles-ci permet de maîtriser doucement mais sûrement l'ensemble de la procédure.
C'est ce que ce manuel a essayé de mettre en évidence et en pratique. J'espère qu'il y a réussi ou que du moins vous ne parvenez pas à ce point en ayant l'impression d'avoir perdu votre temps, car le plus important est là. Aussi, dites-vous bien que le principal dans tout cela n'est pas tant d'en retenir le contenu que d'y trouver matière à stimulation.
Si donc vous êtes en marche au terme de ce manuel, vous m'en voyez comblé. Pour le reste, c'est à présent votre chemin, et je vous souhaite bonne route.
===== Ration de survie bash =====
Le projet de cet appendice est indiqué dans le titre : donner au lecteur le minimum en "bash" pour pouvoir suivre le propos de ce petit manuel. Il en résulte que ceci n'est aucunement exhaustif et ne remplace pas la lecture des documentations appropriées (notamment celle du Manuel GNU ou de la traduction française de la man-page de bash).
Le rédibitoire sermon d'usage étant fait, entrons dans le vif du sujet. Cette aide est organisée en une sorte de glossaire, chaque entrée expliquant une composante syntaxique. Il est conseillé de la lire une fois en entier avant de replonger dans le manuel. Cela permettra de retrouver les passages utiles au fil de la lecture plus rapidement.
* * : ce caractère remplace n'importe quelle chaîne de caractères, y compris une chaîne vide. Ainsi "find . -iname toto* renverra une liste de tous les dossiers ou fichiers commençant par « toto », y compris ceux dont le nom est « toto" ».
* ? : ce caractère remplace n'importe quel caractère, mais seulement si celui-ci existe. Ainsi "find . -iname toto? renverra une liste de dossiers ou de fichiers dont le nom est équivalent à « toto » suivi d'un caractère, mais pas ceux dont le nom est simplement « toto" ».
* ; : ce caractère indique la fin d'une commande. Il sert généralement lorsqu'on place plusieurs commandes sur une seule ligne. Ainsi la ligne "cp toto titi/ ; mv titi/ tata/ copiera d'abord toto dans titi/ avant de déplacer titi/ dans tata/", exactement comme si on avait placé les commandes l'une en dessous de l'autre.
* \ : ce caractère indique qu'une ligne n'est pas finie et qu'elle se poursuit sur la ligne suivante. Ainsi :
" cp toto tata tutu \
titi/
"
sera équivalent à "cp toto tata tutu titi/ et copiera toto, tata et tutu dans titi/". Cela est généralement utilisé pour maintenir la lisibilité du code lorsqu'on a de longues commandes à écrire [50].
* | : ce caractère indique un « tuyau » [51]. Un tuyau consiste à tranférer le résultat d'une commande à une autre. Ainsi :
echo "totem" | cut -c 2
renverra « "o ». En effet, la commande echo "totem" a pour sortie la chaîne de caractères « totem », mais au lieu d'être envoyé sur la sortie standard ce résultat est passé via le tuyau à la commande cut -c 2". Celle-ci ayant pour sortie le deuxième caractère de ce qui lui est donné en entrée, le résultat finalement imprimé sur la sortie standard est « "o" ».
* > : ce caractère indique une redirection de sortie. Ainsi la commande "echo "toto" >fichier.txt n'inscrira rien sur la sortie standard, mais stockera le résultat de echo, à savoir la chaîne de caractères « toto », dans le fichier fichier.txt. Il existe deux types de sortie, la sortie normale notée > ou 1>, et la sortie en erreur notée 2>". Ainsi on peut choisir de ne rediriger que les messages d'erreurs ou que les messages normaux [52].
* && : désigne un « et » logique entre deux commandes, la première étant éxécutée seulement si la deuxième l'a été avec succès. Ainsi, en supposant l'existence de "toto et titi/" :
" cp toto titi/ && echo "ok"
"
renverra "ok", alors que :
cp toto && echo "ok"
ne renverra qu'une erreur indiquant qu'il manque une cible à "cp, sans chercher à exécuter echo "ok"".
* (bloc de commandes) : un bloc de commandes cerné par des parenthèses signifie que celles-ci sont exécutées dans un sous-shell. Tout ce qui se produit dans un sous-shell n'est effectif que dans celui-ci. Soit le code suivant :
" TEXTE_1="toto"
TEXTE_2="tata"
echo ${TEXTE_1}
(
TEXTE_1="titi"
echo ${TEXTE_1}
echo ${TEXTE_2}
)
echo ${TEXTE_1}
"
celui-ci renverra la sortie suivante :
" toto
titi
tata
toto
"
En effet, la redéfinition de la variable "TEXTE_1 au sein du sous-shell n'est valable que pour lui. Aussi dès que celui-ci est refermé [53], c'est la première définition qui est reprise. À l'inverse, la variable TEXTE_2" conserve la même valeur aussi bien hors que dans le sous-shell. On parle alors de shell-père et de shell-fils, le fils héritant toutes les définitions [54] du père, le père ignorant toutes les définitions du fils.
* "chaîne" : les guillemets doubles servent à désigner une chaîne de caractères. Soit le code suivant :
" echo "cp toto titi/"
"
il renverra la chaîne « "cp toto titi/ ». Les guillemets sont surtout employés pour éviter les ambiguïtés, dans le cas présent ils empêchent que « cp" » soit interprété comme une commande [55], ce qui provoquerait une erreur. Les guillemets doubles laissent cependant les variables s'expanser. Ainsi :
" NOMBRE=3
echo "Il y a ${NOMBRE} oeufs dans cette omelette."
"
renverra la chaîne « "Il y a 3 oeufs dans cette omelette." ».
* 'chaîne' : les guillemets simples, comme les guillemets doubles, servent à désigner une chaîne de caractères. Cependant, contrairement à ces derniers, ils ne laissent pas les variables s'expanser. Ainsi :
" NOMBRE=3
echo 'Il y a ${NOMBRE} oeufs dans cette omelette.'
"
renverra la chaîne « "Il y a ${NOMBRE} oeufs dans cette omelette." ».
* ${NOM} : ordonne l'expansion d'une variable. Une variable est un nom auquel on attribue une valeur à l'aide du signe « "=" ». Soit le code suivant :
" TOTO=champignon
echo ${TOTO}
"
il renverra « "champignon », car la variable TOTO sera d'abord remplacée par sa valeur, puis celle-ci sera donnée en argument à la commande echo" [56].
* $(commande) : renvoie le résultat de la commande contenue. Cela est principalement utilisé pour récupérer ce résultat dans une variable. Ainsi :
" CHAR=$(echo "totem" | cut -c 2)
echo ${CHAR}
"
renverra « "o ». En effet, le résultat de la commande echo "totem" | cut -c 2 est le deuxième caractère de la chaîne « totem », soit « o », qui deviendra la valeur de la variable CHAR" [57].
* ${NOM:-valeur} : définit une valeur par défaut pour une variable. Ainsi :
" TOTO=${TOTO:-totem}
echo ${TOTO}
"
renverra « "totem », car la variable TOTO" n'ayant aucune définition, celle-ci prend sa valeur par défaut. À l'inverse :
" TOTO=sachem
TOTO=${TOTO:-totem}
echo ${TOTO}
"
renverra « "sachem », car la variable TOTO" étant déjà attribuée, sa valeur par défaut est ignorée [58].
* ${NOM[@]} : correspond à l'expansion d'une liste. Une liste se définit comme une variable en liant, à l'aide du signe « "=" », son nom avec la collection de ses valeurs entre parenthèses. Soit le code :
" MA_LISTE=( titi toto tutu )
echo ${MA_LISTE[0]}
echo ${MA_LISTE[1]}
echo ${MA_LISTE[2]}
echo ${MA_LISTE[@]}
"
il renverra :
" titi
toto
tutu
titi toto tutu
"
En effet, la valeur entre crochets indique ce qu'il faut expanser dans la liste, la première valeur de celle-ci étant à la position "0. Le symbole « @" », quant à lui, veut dire « toutes les valeurs » et provoque donc l'expansion de la liste complète.
* ${nombre} : ordonne l'expansion d'un paramètre positionnel. Un paramètre positionnel correspond à une chaîne de caractères dans la ligne de commande lançant un script. Soit le script parapos.sh défini comme suit :
" #!/bin/sh
#
# PARAPOS - exemple sur les paramètres positionnels.
#
echo ${0}
echo ${1}
echo ${2}
# Fin de fichier
"
en le lançant avec cette ligne :
" sh parapos.sh toto titi
"
on obtiendra le résultat suivant :
" parapos.sh
toto
titi
"
En effet, le paramètre positionnel "0 correspond au nom du script, le 1 à la première chaîne de caractères située à la suite de ce nom, et le 2" à la seconde.
* case/in/esac : fonction déclinant les valeurs possibles d'un paramètre et exécutant la liste de commandes associée à la première concordant [59]. Soit le code suivant :
" case 'toto' in
'titi')
echo "Concorde avec la première valeur."
;;
'toto')
echo "Concorde avec la deuxième valeur."
;;
'toto')
echo "Concorde avec la troisième valeur."
;;
*)
echo "Ne concorde avec aucune valeur."
esac
"
il renverra « "Concorde avec la deuxième valeur." », car la recherche s'arrête une fois la première concordance trouvée [60].
* for/do/in/done : fonction exécutant une liste de commandes pour chaque paramètre donné [61]. Soit le code suivant :
" for WHO_IS in toto tata tutu; do
echo ${WHO_IS}
done
"
il aura pour résultat :
" toto
tata
tutu
"
En effet, la variable "WHO_IS va prendre successivement pour valeur « toto », « tata » et « tutu », en étant passé en argument à echo" après chaque changement.
* if/then/fi : fonction exécutant une liste de commandes si un test est passé avec succès [62]. Ainsi :
" if [ "titi" = "titi" ]; then
echo "ok."
fi
"
renverra "ok., car le test qui vérifie si la chaîne « titi » est identique avec elle-même sera fatalement vrai. Si une autre chaîne que « titi" » avait été testée, le test aurait été faux et rien aucun message d'erreur ne se serait produit [63].
* while/do/done : fonction exécutant une liste de commandes tant qu'un test est vérifié [64]. Soit le code qui suit :
" REPLY=oui
while [ "${REPLY}" = "oui" ]; do
read -p "Tapez 'oui' pour continuer… "
done
"
tant que l'utilisateur entrera « "oui" », le test conditionnant la boucle sera vrai et celle-ci se poursuivra [65]. Toute autre réponse, à l'inverse, provoquera la fin de la boucle.
===== Licences de ce document =====
Le texte du présent manuel est couvert par la Licence Microbe, telle qu'énoncée ci-après :
=== LICENCE MICROBE ===
Version 1.0 du 25 Avril 2006.
Tous droits réservés. Pour toute la durée des droits patrimoniaux courant sur celui-ci vous sont cédés, en tant que personne physique ou morale, les droits suivants :
- droit de reproduire et diffuser ce document sans restriction de nombre : ce sur tous supports, en tous formats, à titre onéreux ou gratuit ;
- droit de modifier (terme couvrant ici la traduction, l'adaptation ou la transformation, l'arrangement ou la reproduction par un art ou un procédé quelconque) le présent document.
En contre-partie, vous vous engagez dès l'exercice d'un des droits précédemment cédés à satisfaire toutes les conditions suivantes :
- diffuser toute copie de ce document, modifiée ou non, accompagnée manifestement de la présente licence (en incluant celle-ci dans le corps du document quand c'est possible) ;
- reproduire manifestement toutes les mentions légales et exonérations de garantie et/ou de responsabilité apposées sur ce document ;
- le cas échéant, diffuser vos versions modifiées selon les termes exacts de la présente licence : ni plus, ni moins ;
- le cas échéant, entre parenthèses à droite du numéro de version, attribuer à vos version modifiées un nom de branche autre que ceux indiqués dans les mentions légales presentes ou supprimer celui présent ;
- reproduire les historiques des modifications présents et, le cas échéant, tenir celui de vos propres modifications ;
- le cas échéant, si une version modifiée diffusée par vous ne remplit pas déjà les critères suivants, fournir sur simple demande cette dernière sous une forme numérique compatible avec le plein exercice des droits cédés par cette licence et n'induisant pas l'achat de licences d'utilisation supplémentaires. Cela pour un prix n'excédant pas le coût du support et de l'envoi.
=================
Copyright © 2006 Sébastien Boillod – Tous droits réservés, vous êtes autorisé à reproduire et diffuser des versions intégrales de cette licence. Vous pouvez également en élaborer des traductions : à titre strictement informatif toutefois, seul le texte français faisant foi.
NB. Pour ce qui est de reprendre le code contenu dans la partie « …pour aller son chemin », n'encombrez pas vos scripts d'une licence, volez-le ! un petit merci en commentaire à la limite, si votre conscience vous titille trop. ;)
Le matériel emprunté à Patrick Volkerding est couvert par les termes suivants :
Copyright 1993, 1994, 1995, 1996, 1997, 1998, 1999 Patrick Volkerding, Moorhead, Minnesota, USA. Copyright 2001, 2002, 2003, 2004 Slackware Linux, Inc. Concord, CA, USA. All rights reserved.
Redistribution and use of this software, with or without modification, is permitted provided that the following conditions are met:
- Redistributions of this software must retain the above copyright notice, this list of conditions and the following disclaimer.
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
1. Il faut savoir que le libre est en fait entièrement basé sur l'échange des sources.2. GNU's Not Unix, projet fournissant au noyau Linux les programmes et bibliothèques nécessaires pour faire un système d'exploitation opérationnel.3. Installer "gcc-g++" pour avoir un support du C++ peut aussi se révéler une bonne idée, d'autant qu'il est un paquet requis par certaines applications.4. Il arrive que certaines archives compressées par "gzip prennent la forme de <nom_du_logiciel.tgz>". Prenez garde à ne pas les confondre avec un binaire Slackware.5. Les versions modernes de "tar", toutefois, semblent capables de détecter automatiquement le format de compression.6. L'image des générations est pertinente la plupart du temps, mais pas toujours, car il existe des dépendances dites « circulaires » s'engendrant l'une l'autre. Un compilateur, par exemple, a besoin d'un compilateur pour être compilé.7. Indiquez bien « file name » dans le deuxième champs de recherche, autrement celle-ci ne portera que sur les noms des paquets.8. Comme nous le verrons plus tard, ces variables peuvent être réglées directement auprès du compilateur, cf. En tête : définition des variables.9. Le nom de variable "DESTDIR" est un nom standard qui devrait être reconnu la plupart du temps. Cependant rien n'empêche que la variable porte un autre nom.10. Certains logiciels paramètrent "make install avec prefix=<répertoire> au lieu de DESTDIR=<répertoire>. À la différence de cette dernière méthode, la méthode prefix=<répertoire>" ne créé pas l'arborescence, il faut donc veiller à ce que le dossier temporaire et ses sous-dossiers existent. Dans notre exemple, il faudrait taper "mkdir -p /home/mushroom/bluefish-pkg/usr/local/ avant de lancer make install".11. Sauf cas particulier ou présence d'une version antérieure du logiciel dans "/usr/local".12. À savoir "installpkg, upgradepkg, removepkg et explodepkg".13. Keep It Simple, Stupid ! : « Fais-donc simple, idiot ! »14. Vous aurez sans doute remarqué que le contenu de l'archive ne comporte pas le dossier d'installation temporaire, juste l'arborescence finale. C'est pourquoi nous avons parlé de simulation de racine concernant la variable "DESTDIR=<répertoire>", l'arborescence que vous voyez sera celle dans laquelle s'installeront les fichiers.15. On appelle aussi cela le « shebang ! ».16. « coquille » en anglais.17. Notons qu'il existe deux manières d'exécuter un script. Soit en le rendant exécutable ("chmod u+x <script>), puis en entrant son nom dans le terminal. Soit en le donnant en argument à l'interpréteur de commandes : sh <script>".18. Cette ligne fonctionne avec la branche 3.3.x de "gcc. Pour la branche 3.4.x, adoptée depuis, -mcpu=i686 a été remplacé par -mtune=i686".19. Patrick Volkerding part du principe que le dossier résultant de l'archive contenant les sources sera de la forme "<logiciel>-<version>". Cela est (très) généralement le cas, néanmoins techniquement rien n'interdit qu'il en soit autrement, même quand le nom de l'archive respecte cette forme standard.20. Si vous éditez d'autres "SlackBuild, vous verrez qui les permissions recherchées ne sont pas toujours les mêmes. Cela vient du fait que les SlackBuild de Patrick Volkerding ne sont pas vraiment pensés pour être génériques. En conséquence un SlackBuild" est toujours plus ou moins adapté au logiciel qu'il compile.21. Cette manoeuvre est destinée à mettre l'exécutable de "sed" dans le bon dossier car tout exécutable requis par un système GNU/Linux non spécifique au superutilisateur doit se trouver dans "/bin. Pour ce qui est des autres, ils sont généralement installés dans /usr/bin ou /usr/local/bin".22. Ce changement de groupe est depuis peu abandonné : tout doit désormais être attribué au groupe "root".23. « pipe » en anglais24. « Executable and Linking Format »25. Il peut arriver dans de rares cas que l'affinement des bibliothèques dynamiques pose problème. Explorez cette piste si vous constatez une instabilité du programme à l'usage.26. Ou "/usr/local/doc/<nom_du_paquet>-<version> si vous optez pour cette arborescence. Prenez garde toutefois : certains logiciels installent des docs dans /usr/share/doc/. Cela n'est pas grave car ce dossier est en fait un lien symbolique vers /usr/doc/. Il n'en va cependant pas de même pour /usr/local/share/doc/, veillez-donc à créer le lien symbolique entre /usr/local/share/doc/ et /usr/local/doc/ avant d'y installer des paquets : cd /usr/local/share ; mv doc/* ../doc; rm -R doc/ ; ln -s ../doc".27. Si vous souhaitez récupérer le code des scripts, faites-en une capture à la souris vers un fichier. Ensuite, pour ôter la numérotation appliquez à celui-ci la commande suivante : "sed "{s/[0-9]{1,3}; s/ *//}" -i <fichier>". Il ne vous restera qu'à réindenter le code comme il faut avec [TAB].28. Le mélange lettres/chiffes, ici comme ailleurs, n'est absolument pas requis, c'est juste une manière d'éviter toute ambiguïté avec le reste du script. Veillez cependant bien à ce qu'il débute toujours une ligne (ie. aucun espace avant).29. « Switch User »30. C'est une sécurité supplémentaire car un sous-dossier "man<un_caractère"/> n'est pas censé contenir autre chose que des man-pages. Retirez ce critère si vous constatez des problèmes.31. Pensez à conserver une ligne vide à la fin du fichier. Cela est valable pour tout fichier, c'est pourquoi on note souvent en commentaire la fin du fichier, suivi d'une ligne vide, afin d'être sûr de ne rien écrire après.32. Présente dans le paquet "diffutils, répertoire ap/" de la Slackware.33. Ici l'argument n'est que peu utile, mais il peut l'être vraiment lorsqu'on a plusieurs fichiers à patcher dans différents répertoires et qu'on ne veut pas devoir jouer de la commande "cd à chaque fois. Pour plus d'informations consultez man patch".34. C'est d'ailleurs pour cela que ce patch sera dynamique : parce qu'une fois écrit il se conformera aux variables du script sans qu'il n'y ait rien à y changer.35. L'argument "-z" n'est pas signifiant ici, c'est juste qu'avec lui la sortie de file est plus structurée.36. En shell, "exit 0 est une sortie normale, alors que exit 1" corespond à une sortie en erreur.37. « "soft" » doit normalement correspondre au nom du logiciel que vous empaquetez.38. Il est recommandé de le faire, autrement si les dossiers existent déjà "tar" se contentera d'ajouter les fichiers de la nouvelle archive à ceux de l'ancienne.39. Cela pour avoir le contenu du dossier, sans le dossier même.40. Il n'est pas besoin de supprimer l'archive "tampon, car tar" écrasera celle-ci lorsqu'il générera la nouvelle.41. Nous disons « stocké », car le fichier "doinst.sh" contient également les commandes permettant la restitution des liens symboliques lorsque leur conservation est ordonnée (cf. L'empaqueteur Slackware : makepkg). Normalement ces commandes seront ajoutées à la suite des vôtres. Si toutefois ces dernières requièrent que les liens symboliques soient réstitués avant leur exécution, vous pouvez demander à "makepkg de mettre les premières au début du script en lui passant l'argument -p lors de la génération du paquet. Pour plus d'informations consultez la man-page de makepkg".42. Ce script étant stocké, il ne contient pas la traditionnelle première ligne "#!/bin/sh"43. Le paquet "shared-mime-info se situe dans le répertoire l/".44. Multipurpose Internet Mail Extensions. Les fichiers mime servent à typer les documents selon leurs extensions, ce qui permet notamment aux environnements de leur associer des applications.45. Dans ce cas, c'est la commande "ash qui doit exécuter le script : ash script.sh. Le Ash shell est disponible dans le répertoire ap/ de la Slackware. Le paquet ash" faisant moins de 200K une fois décompressé, l'installer ne coûte vraiment pas grand chose.46.Ce qui est valable pour les disquettes l'est vraisemblablement pour les CD puisque c'est l'installateur Slackware qui emploie le Ash Shell. Ne négligez donc pas trop ce point.47. La man-page ici traduite date un peu. La commande "setup" à laquelle ce passage fait référence a été retirée de la Slackware dans sa version 8.1. Celle-ci était alors à la fois un outil d'installation et de maintenance. Lorsqu'elle a été retirée, la commande "pkgtool" a récupéré certaines de ses fonctionnalités, notamment sa capacité à exécuter les scripts de configuration.48. En français, « rien qu'une fois ».49. L'option "CONFIGURE de setup avait pour effet de lancer la totalité des scripts de configuration. Les scripts onlyonce permettaient donc de créer des exceptions. À présent que pkgtool" propose de choisir les scripts à exécuter, cela n'a plus lieu d'être.50. Prenez garde toutefois à ne laisser aucun espace derrière le symbole, si vous voulez que ça marche.51. « pipe » en anglais.52. Il est également possible de rediriger les deux sorties vers un même point. Pour plus d'informations sur le vaste sujet des redirections, consultez la section « REDIRECTION » de la man-page de "bash".53. Pour mieux appréhender le concept, gardez à l'esprit qu'en français shell se traduit « coquille ».54. Le terme « définition » englobe également ici la situation dans le système de fichiers, stockée à chaque changement dans la variable "PWD".55. Ils peuvent également servir à ce que des chaînes séparées par des espaces soient considérées comme une seule et même chaîne.56. La syntaxe donnée ici est la plus rigoureuse, "${NOM} peut se noter plus simplement $NOM".57. Une notation alternative pour "$(commande) est `commande`".58. Il existe de nombreuses autres possibilités pour agir sur les valeurs des variables. Consultez la sous-section « Remplacement des paramètres » (dans « EXPANSION ») de la man-page de "bash" pour plus d'informations.59. En français « in case » se traduit par « au cas où ».60. Si nous avions mis "case 'tata' in au lieu de case 'toto' in, nous aurions obtenu « Ne concorde avec aucune valeur" ». car la dernière ligne signifie « n'importe quelle valeur ». Même si prévoir une telle ligne (dite « fallback », « retomber ») est très courant, ce n'est toutefois nullement obligatoire et son absence ne générera aucune erreur.61. En français for… in… do se traduit par « pour… dans… fais » et done par « achevé ».62. En français if… then se traduit par « si… alors ».63. On peut, en utilisant les séquences "else et elif", faire de la fonction « if/then/fi » un quasi-équivalent de la fonction « case/in/esac ». Consultez la sous-section « Commandes composées » (dans « GRAMMAIRE DU SHELL ») de la man-page de "bash" pour de plus amples renseignements.64. En français while se traduit par « tant que ».65. La commande "read sert à stocker dans une variable (REPLY, par défaut) une chaîne de caractères donnée par l'utilisateur. L'argument -p" permet d'afficher un message précédant la saisie.