Bonjour à tous,
Ça faisait longtemps que je n'ai pas fait un mail de 10 pages, alors en voici
un ! :-)
Le développement de Ncooker avance et il reste un fichier des NBUILDs pour
lequel je voudrais apporter des améliorations : le fichier build.
Pour rappel, ce fichier est un script bash contenant un ensemble de fonctions
dont le nom commençe par do_*. Chacune d'elles représente une étape du
processus de compilation du NBUILD qui va permettre d'obtenir un paquet NBA.
Elles contiennent les instructions permettant de réaliser l'étape
correspondante. Ces fonctions sont appelées l'une après l'autre par Ncooker,
et il est possible de n'exécuter que certaines d'entre elles, ce qui est bien
pratique durant la mise au point d'un NBUILD.
Voici rapidement la liste de ces fonctions utilisables actuellement, et leur
rôle, dans l'ordre où elles sont appelées :
- do_preconfig() : cette fonction est utilisée pour appliquer des patches aux
fichiers sources et/ou à modifier des fichiers à l'aide sed ou awk par
exemple. Plus généralement, elle permet de modifier certains paramètres avant
que l'environnement de compilation soit généré.
- do_config() : cette fonction lance le script ./configure avec les options
voulues, ce qui a pour effet de préparer l'environnement de compilation.
- do_premake() : cette fonction peut être utilisée pour modifier les fichiers
générer par le script ./configure ou configurer certaines choses à la main
qui n'ont pas été faite par ./configure. Plus généralement, elle permet de
terminer la préparation de l'environnement de compilation.
- do_make() : cette fonction se contente généralement de lancer la commande
« make », éventuellement avec des paramètres, pour procéder à la compilation
de l'application.
- do_preinstall() : cette fonction permet de préparer l'environnement pour
installer l'application dans un fakeroot, un dossier utilisé comme s'il
s'agissait de la racine de l'arborescence du système. Dans beaucoup de
paquets actuels, elle est utilisée pour copier des fichiers d'informations
(AUTHOR, README, NEWS, CHANGELOG ...) dans le fakeroot. Perso, je trouve que
cela aurait plus sa place dans la fonction do_postinstall() (voir plus loin).
- do_install() : cette fonction procède à l'installation de l'application dans
le fakeroot. Elle fait généralement appel à la commande « make
DESTDIR=$INST_ROOT install » où la variable $INST_ROOT, positionnée par
Ncooker, contient le chemin d'accès au fakeroot.
- do_postinstall() : cette fonction permet de « finaliser » l'installation, ce
qui représente une notion assez large :-) . Tout dépend ici des besoins de
l'application. Il peut s'agir par exemple de créer un fichier de
configuration par défaut.
Elle sert aussi à nettoyer les fichiers objets (binaires et librairies) de
leurs symboles (comme les symboles de débuggage par exemple), ce qui permet
de réduire leur taille.
Elle est également utilisée pour copier les ressources incorporées au NBUILD
dans le fakeroot, comme un fichier *.desktop par exemple.
Dans certains paquets, elle est aussi utilisée pour déclarer les fichiers dits
« sensibles », comme les fichiers de configuration, qu'il sera possible de
préserver lors d'une mise à jour du paquet pour éviter qu'ils soient écrasés.
- do_package() : c'est la fonction qui génère le paquet NBA. Elle fait appel à
la commande makenpkg2 pour créer un fichier .tgz avec ce qui se trouve dans
le fakeroot. Cette commande génère des informations supplémentaires comme la
liste des fichiers contenant le .tgz, la liste des dépendances nécessaires au
bon fonctionnement de l'application, etc. Tout ceci est regroupé pour former
un paquet NBA.
Il reste une dernière fonction, do_static(), qui n'est pas obligatoire, et qui
sert à compiler l'application en mode « statique », c'est à dire en
incorporant directement dans le fichier binaire de l'application le code des
librairies de fonctions utilisées (en gros, hein :-) ). Elle n'est appelée
que si on invoque Ncooker avec une option spéciale, et remplace alors la
fonction do_make(). Si je ne me trompe pas, elle est utilisée pour faire le
devkit. Il faudrait savoir si elle est toujours nécessaire (Riri ?).
Toutes ces fonctions, à part do_static(), sont obligatoires dans le fichier
build, _même_ si elles ne sont pas nécessaires pour la bonne compilation de
l'application. Dans le cas où une fonction n'a pas besoin d'être utilisée, il
suffit de placer un « echo "Nothing to do." » dans son corps pour indiquer
qu'il n'y a rien à faire à cette étape.
Voilà pour ce qui est du rappel :-) (n'hésitez pas à compléter si j'ai oublié
des choses)
Quelles sont les améliorations que je propose d'apporter ?
Tout d'abord, je voudrais étoffer un peu cette liste de fonctions pour obtenir
ceci :
- do_uncompress()
- do_patches()
- do_preconfig()
- do_config()
- do_premake()
- do_make()
- do_check()
- do_preinstall()
- do_install()
- do_postinstall()
- do_packages()
- do_help()
- do_static() (?)
J'ai ajouté les quatre fonctions do_uncompress(), do_patches(), do_check() et
do_help().
La première permet de réaliser soi-même la décompression des archives sources
au lieu de laisser Ncooker le faire. Ça peut s'avérer utile avec certains
paquets comme le driver Nvidia par exemple.
La seconde permet de séparer l'application des patches de la
« préconfiguration » avec do_preconfig(). Autrement dit, do_preconfig()
garderait son rôle actuel excepté l'application des patches, qui eux seraient
faits dans do_patches(). L'intérêt d'une telle modification n'apparaît pas
immédiatement, mais attendez la suite :-)
La troisième permet de lancer une vérification de la compilation. Cette
fonctionnalité n'est pas présente dans tous les makefiles, mais lorsqu'elle
l'est, un simple « make check » permet de lancer une série de tests pour
valider que l'application s'est compilée correctement. C'est particulièrement
important pour les librairies de base du système.
La dernière enfin permet d'afficher des infos utiles pour compiler le paquet,
comme les options utilisables avec ./configure par exemple.
Les plus attentifs auront remarqués que j'ai ajouté un « s » à la fonction
do_package() :-) car je souhaite ajouter la possibilité de générer plusieurs
NBAs à partir d'un seul NBUILD :-) C'est un autre sujet ...
Là où ça commence à devenir plus intéressant, c'est que _toutes_ ces
fonctions, sans exception, seraient OPTIONNELLES ! C'est-à-dire que pour
certains paquets, il ne serait pas nécessaire de fournir un fichier build
pour générer un paquet NBA :-)
Comment cela est-il possible ? Tout simplement en intégrant à Ncooker un
comportement par défaut, proche du fameux triplet de commandes « ./configure;
make; make install » qui permet de compiler une très grande majorité
d'applications.
L'idée est que pour chaque étape, Ncooker regarde si le fichier build contient
une fonction associée. Si c'est le cas, il l'exécute, sinon, il utilise celle
fournit par défaut avec la commande build. Puis il passe à la suivante en
procédant de la même manière.
Examinons à nouveau toutes les étapes en utilisant ce procédé :
- Décompression des archives sources : Ncooker regarde si la fonction
do_uncompress() existe. Si oui, il la lance, sinon il décompresse lui-même
les archives dans le répertoire qui va bien.
- Application des patches : comme précédemment, Ncooker regarde si la fonction
do_patches() existe et la lance le cas échéant. Sinon, il applique
automatiquement les patches trouvés dans le répertoire /patches du nbuild.
Plusieurs choses peuvent être mises en place ici. D'abord, on pourrait classer
les patches dans une arborescence :
patches/
|_ x86/
|_ x86_64/
Le répertoire patches/ pourrait contenir les patches à appliquer tout le
temps, indifféremment de l'architecture matérielle du système. Le
sous-répertoire x86/ contiendrait les patches à appliquer que pour les
architectures 32bits, et x86_64/, uniquement ceux à appliquer pour les
architectures 64bits. À charge pour Ncooker de déterminer automatiquement
l'architecture matérielle.
Si cela s'avère nécessaire, on peut créer des sous-répertoires dans x86 (et
x86_64) pour les patches spécifiques à certains microprocesseurs. Par
exemple,
patches/
|_ x86/
|_ pentium4
|_ athlon-xp
Si le microprocesseur est un athlon-xp, les patches appliqués seraient ceux
qui se trouvent dans les répertoires patches/, patches/x86/ et
patches/x86/athlon-xp/.
Là encore, à charge pour Ncooker de déterminer le type de microprocesseur.
Si les patches sont compressées, ils sont automatiquement décompressés avant
utilisation.
Quant aux options à utiliser par défaut avec la commande « patch », j'ai
décortiqué les paquets fournis avec nasgaia 1.0.1, et le plus souvent, ce
sont les options « -Np1 -i » qui sont utilisées. Je propose donc de les
adopter par défaut. Certains paquets utilisent l'option « -p2 » au lieu de
« -p1 ». Dans ce cas, soit on écrit la fonction do_patches() dans le fichier
build pour appliquer soi-même le patch, soit on modifie le patch pour qu'il
n'y ait qu'un seul niveau à supprimer dans le chemin du fichier (« man
patch » pour ceux qui ont du mal à suivre ;-) )
- do_preconfig() : le comportement par défaut de Ncooker ne fait rien.
- do_config() : S'il n'y a pas de fonction do_config() dans le fichier build,
Ncooker recherche un script ./configure exécutable. S'il le trouve il
l'exécute. Ok, mais avec quelles options par défaut ? :-) Ici, il n'est pas
possible de choisir des options par défaut qui soient vraiment
« passe-partout » ... Qui plus est, je me souviens que quelqu'un avait déjà
émis le souhait de pouvoir savoir qu'elles sont les options de ./configure
utilisées par défaut dans les nbuilds. Je propose une solution pour répondre
aux deux problèmes en même temps : utiliser une variable NPKG_CONFIG_OPTIONS
dans le fichier « infos » du nbuild. Par exemple :
NPKG_CONFIG_OPTIONS="--prefix=/usr --with-ssl"
Le comportement par défaut de Ncooker serait alors de lancer « ./configure
$NPKG_CONFIG_OPTIONS ». D'un autre coté, la commande « Ncooker info
paquet.nbuild » montrerait, entre autres, les options utilisées par défaut
avec ./configure en affichant simplement la valeur de la variable
NPKG_CONFIG_OPTIONS.
Bien sûr, la commande « Ncooker build » proposerait une option pour permettre
à l'utilisateur de surpasser les options par défaut. Par exemple :
$ Ncooker build --config-options "--without-ssl" paquet.nbuild
La commande lancée par Ncooker serait alors :
./configure $NPKG_CONFIG_OPTIONS <options passées à --config-options>
soit :
./configure --prefix=/usr --with-ssl --without-ssl
la dernière option annulant l'effet de la seconde.
- do_premake() : le comportement par défaut de Ncooker de fait rien.
- do_make() : le comportement par défaut de Ncooker est de lancer la commande
« make ». Là aussi, on peut utiliser une variable NPKG_MAKE_OPTIONS dans le
fichier « infos » pour définir des paramètres à utiliser avec make + une
option spéciale pour la commande « Ncooker build ».
- do_ckeck() : le comportement par défaut de Ncooker est de faire un grep sur
le fichier Makefile pour recherche une entrée « check: » ou « test: ». S'il
en trouve une, il lance la commande « make » qui correspond (make check ou
make test).
- do_preinstall() : le comportement par défaut de Ncooker ne fait rien.
- do_install() : le comportement par défaut de Ncooker est de lancer la
commande « make DESTDIR=$INST_ROOT install ». Parfois, il faut utiliser une
autre variable que DESTDIR. Il faut voir s'il y a un moyen de la trouver
automatiquement. Sinon, il faudra écrire la fonction do_install() dans le
fichier build directement.
- do_postinstall() : Le comportement par défaut de Ncooker est de supprimer
les symboles des fichiers objets, et de placer un certains nombres de fichier
d'informations (AUTHOR, README, NEWS, CHANGELOG ...) dans le
répertoire /usr/share/doc/<nom-appli> du fakeroot s'ils existent.
- do_packages() : Pour ce qui est de la création des paquets NBAs, je pense
qu'il faut en parler sur un thread à part :-) Dans tous les cas, le
comportement par défaut de Ncooker est de créer un seul paquet NBA.
- do_help() : le comportement par défaut est d'exécuter ./configure --help
si ./configure existe, et/ou d'afficher le fichier README/INSTALL s'ils
existent.
Voilà pour l'idée de base :-)
La création d'un paquet nbuild serait ainsi grandement facilitée :
* dans le meilleur cas, il n'y a pas de fichier build à écrire, seules les
variables NPKG_CONFIG_OPTIONS et NPKG_MAKE_OPTIONS doivent être définies dans
le fichier « infos » (c'est Geekitus qui va être content ;-) )
* Le cas intermédiaire est que seules certaines fonctions par défaut de
Ncooker conviennent pour compiler le paquet, mais pas d'autres. Il suffit
alors de réécrire dans le fichier build uniquement les fonctions par défaut
qui ne vont pas.
* Le pire cas est bien sûr de devoir réécrire toutes les fonctions parce le
comportement par défaut de Ncooker n'est absolument pas adapté.
Cette solution présente aussi l'avantage de laisser la liberté au nbuildeur
d'écrire l'ensemble des fonctions du fichier build s'il le souhaite,
indépendamment du fait que le comportement par défaut de Ncooker puisse ou
non convenir pour son paquet.
Si vous avez bien assimiler cette proposition, passons à l'étape
supérieure :-) : le couple autoconf/automake n'est pas la seule manière de
compiler une application. Il existe d'autre solutions comme Scons par
exemple. Une idée pour rendre Ncooker encore plus pratique/souple serait que
la commande build ne dispose pas uniquement d'un comportement par défaut pour
autoconf/automake, mais soit livrée avec un comportement par défaut pour les
outils de construction les plus utilisés. Il détecterait automatiquement
l'outil utilisé et sélectionnerait le comportement par défaut
correspondant :-) ...
Voilà, dites-moi ce que vous pensez de tout ça ;-)
++
Gontran