"Packager" vos sources

 Herve.Frezza-Buet@supelec.fr


1 - Objectif

Nous allons apprendre comment fournir un package contenant des sources, qui s'installe facilement. Nous profiterons des outils gnu : automake et autoconf en particulier. Enfin, on verra comment faire des binaires qui s'installent tout seul, à savoir des packages rpm.

On supposera une connaissance de base des makefiles, et on travaillera à partir de l'exemple suivant.

On veut définir un package hello qui fournit une librairie dynamique et un exécutable. Nous allons installer un package déjà fait, puis le commenter par la suite.

2 - Installation à partir des sources

2.1 - Mode d'emploi

Pour que ça marche, vous devez disposer de gtk et de glade, version 2, mais c'est juste parce que ce package particulier en dépend.

Passez en root, car on fera une install dans les répertoires systèmes standards (c'est pas obligé, mais c'est plus simple pour commencer). Téléchargez le fichier hello-1.00.tar.gz.

Extraire l'archive (on dit détargézifier en français) et aller dans le répertoire ainsi généré.
prompt> tar zxvf hello-1.00.tar.gz
prompt> cd hello-1.00
	
L'étape suivante consiste à générer des makefiles. Mais pour être sûr qu'ils vont bien fonctionner, un tas de trucs sont vérifiés. La génération et la vérification sont pris en charge par le script configure. Si tout est ok, on installe (cible 'install' du makefile généré).
prompt> libtoolize --force
prompt> ./configure --prefix=/usr
prompt> make install
	
Et le tour est joué ! La commande libtoolize est souvent inutile, mais si vous voyez apparaître des erreurs parlant de libtool, c'est elle qu'il faut invoquer, juste une bonne fois pour toutes. Il y a d'autres cibles intéressantes dans les makefiles générés.
make
Compilation des sources.
make install
Compilation puis installation des sources.
make clean
On efface les fichiers intermédiaires de compilation (gain de place).
make uninstall
On fait le ménage au niveau des repertoires système lorsqu'on désinstalle le package.
make dist
Cette commande regénère hello-1.00.tar.gz. C'est pratique lorsqu'il s'agit de votre package, car vous obtenez ainsi le fichier à distribuer sur une page web par exemple.

2.2 - Que s'est-il passé ?

Un exécutable a été installé...
prompt> ls /usr/bin
...
hello-demo 
...
	
... ansi que des librairies...
prompt> ls /usr/lib
...
libhello.a
libhello.la
libhello.so
libhello.so.0
libhello.so.0.0.0
...
	
... assorties des headers correspondants.
prompt> ls /usr/include/hello-1.0/
hello.h
	
On peut repasser en utilisateur normal et lancer hello-demo depuis une ligne de commande. Mais on peut aussi utiliser la librairie hello. Commençons par lancer hello-demo.
prompt> hello-demo
	


Cette interface graphique est faite avec libglade, et l'application, au moment du lancement, a besoin de trouver un fichier de ressource pour la construire. Le package en a justement installé un.
prompt> ls /usr/share/hello_demo-stuff
hello-demo.glade
Enfin, si on veut profiter de la librairie hello fournie, il faut pouvoir compiler les sources avec les bons chemins d'accès aux headers (de libglade, de gtk, de xml, etc !!!!) et les bons flags de linkage. Heureusement, il y a l'utilitaire pkg-config qui produit les flags utiles à la compilation.
prompt> pkg-config --cflags hello
-I/usr/include/hello-1.0 -I/usr/include/gtk-2.0 -I/usr/include/libglade-2.0 -I/usr/lib/gtk-2.0/include -I/usr/include/atk-1.0 -I/usr/include/pango-1.0 -I/usr/X11R6/include -I/usr/include/freetype2 -I/usr/include/glib-2.0 -I/usr/lib/glib-2.0/include -I/usr/include/libxml2

prompt> pkg-config --libs hello
-Wl,--export-dynamic -L/usr/lib -lhello -lglade-2.0 -lgtk-x11-2.0 -lxml2 -lz -lgdk-x11-2.0 -latk-1.0 -lgdk_pixbuf-2.0 -lm -lpangoxft-1.0 -lpangox-1.0 -lpango-1.0 -lgobject-2.0 -lgmodule-2.0 -ldl -lglib-2.0
	
Comment pkg-config connait-il les flags qui sont nécessaires à l'utilisation de cette librairie ? Notre package a placé le fichier adéquat, là où il faut.
prompt> ls /usr/lib/pkgconfig
...
hello.pc
...
Donc pour compiler un exécutable essai.cc qui utilise la librairie et ses headers, il suffira de taper ce qui suit, plutot que de retenir cette impressionnante liste de flags.
prompt> g++ -o mon_essai `pkg-config --cflags hello` essai.cc `pkg-config --libs hello`

2.3 - Résumé des fichiers installés

/usr/lib/libhello.a
/usr/lib/libhello.la
/usr/lib/libhello.so
/usr/lib/libhello.so.0
/usr/lib/libhello.so.0.0.0

/usr/lib/pkgconfig/hello.pc

/usr/include/hello-1.0/hello.h

/usr/bin/hello-demo

/usr/share/hello_demo-stuff/hello-demo.glade

3 - Construction des RPM

Dans ce qui précède, nous avons installé hello à partir des sources. Nous nous proposons ici de la faire à l'aide de packages rpm, qu'il nous faut au préalable compiler. Donc deux étapes : compiler les packages, puis les installer.

3.1 - Préliminaire

Nous allons d'abord désinstaller hello, à partir des sources.
prompt> cd hello-1.00/
prompt> make uninstall clean
Ensuite, sous votre compte (vaut mieux éviter root), il faut faire quelques préparations. Mon compte, pour cet exemple, est herve, et mon répertoire est /home/herve. Vous adapterez les fichiers et les commandes qui suivent à votre cas.

Sous votre racine donc, décompressez l'archive suivante MesRPMs.tar.gz, afin de créer une arborescence adéquate pour ce qui suit.
prompt> cd ~
prompt> tar zxvf MesRPMs.tar.gz
Créer ensuite, sous votre racine toujours, le fichier texte .rpmmacros qui contient le texte suivante :
%packager      Herve Frezza-Buet 
%vendor        Supelec

%_topdir       /home/herve/MesRPMs
%_archi_libdir lib
Nota : sur machines 64 bits sous fedora, il faut mettre lib64

3.2 - Créez vos .rpm

On n'est maintenant prêt à créer nos rpm simplement à partir de hello-1.00.tar.gz. Placez-vous dans un répertoire où cette archive se trouve, puis tapez :
prompt> rpmbuild -ta hello-1.00.tar.gz
Tout est automatique, les fichiers .rpm sont dans MesRPMs/RPMS/i386. Vous pouvez les distribuer... En particulire, le package -devel sert à installer les .h pour des développeurs utilisant la librairie.

3.2 - Installation

Vos rpm s'installent comme tous les rmp. Il faut être root pour le faire.
prompt> rpm -ivh hello-1.00-1.i386.rpm hello-devel-1.00-1.i386.rpm
Préparation...              ########################################### [100%]
   1:hello                  ########################################### [ 50%]
   2:hello-devel            ########################################### [100%]

4 - Faire votre propre distribution

Il vous suffit de partir du fichier hello-1.00.tar.gz, de le "détargézifier" comme on l'a vu, et de vous servir du répertoire ainsi créé comme "projet vide".
prompt> tar zxvf hello-1.00.tar.gz
prompt> cd hello-1.00
	
Ensuite, vous modifierez les fichiers suivants, pour qu'ils décrivent non plus le package hello, mais le votre. Ils sont émaillés de commentaires qui devraient vous permettre de comprendre ce qu'ils font.
configure.in
Définitions globales au package. C'est dans ce fichier qu'on précise, entre autres, le numéro de version, et les flags de compilation (-I -D). Cf. la variable CXXFLAGS définie dans ce fichier.
hello.spec.in
Il s'agit du fichier qui sert à construire les RPM. Attention, les % précèdent des instructions... ce sont les lignes commençant par # qui sont des commentaires. Veillez aux dépendances (lignes "Requires: ..." et "BuildRequires: ..."), ainsi qu'à spécifier les fichiers installés (voir les directives "%files" et "%files devel" en fin de fichier).
Makefile.am
Exprime les sous-répertoires concernés, les fichiers supplémentaires à inclure dans le package.
hello.pc.in
Remplacez-le par un xxx-1.0.pc.in, si votre package est xxx. Attention aux références faites à ce nom dans configure.in et Makefile.am . Ce fichier ne sert pas à la compilation. Il permet, si vous définissez des librairies dans votre package, de pouvoir offrir aux utilisateurs de votre librairie les facilités offertes par l'utilitaire pkg-config (cf. fin du paragrapge 2.2).
src/*.cc src/*.h
Rajoutez vos sources, et également les fichiers de config, comme hello.glade. Ces fichiers de config peuvent aussi être des pixmaps utilisées par votre interface graphique, etc...
src/Makefile.am
Ce fichier décrit la compilation des librairies et des exécutables. Il est bien plus simple qu'un makefile usuel ! Attention, pour les exécutables, c'est ici qu'on définit les flags de linkage (-L -l) (cf. ..._LDFLAGS et ..._LDADD). Ces deux variables n'ont pas toujours le même comportement, j'ai pour ma part du mal à cerner la différence. Peut-être simplement l'ordre d'écriture des flags dans la ligne de compilation générée...
Attention, si vous modifiez configure.in, tapez
prompt> ./reconf
et si vous modifiez un Makefile.am, vous devrez configurer.
prompt> ./configure
et enfin, quand tout marche
prompt> make dist
et emballez, c'est pesé !

5 - Exercice

5.1 - Package

Téléchargez sur votre compte (en root, c'est plus simple) le fichier vroum.tar.gz. Il contient du code en vrac. On souhaite en faire une bibliothèque, un utilitaire et un exemple. Vous noterez dans les fichiers la présence de commentaires pour doxygen.

Parmis les fichiers que vous venez de ramener, il y a
vroum/vroum.h
vroum/vroumBase.h
vroum/vroumCar.h
vroum/vroumTruck.h

vroum/vroumBase.cc
vroum/vroumCar.cc
vroum/vroumTruck.cc
qui forment la librairie à proprement parler, et
vroum/vroum-utility.cc
qui est un utilitaire qui est fourni avec la librairie. On fournit de plus un exemple en guise de tutorial :
vroum/example-001.cc
Essayez de faire vous même le package, avec un répertoire analogue à src, en plus, pour l'exemple.

Le fichier vroum-1.00.tar.gz est un corrigé.

5.2 - Documentation

On va faire ça avec doxygen (d'où les commentaires dans les .h. L'exemple est inclu dans la doc par un commentaire spécial, que j'ai mis dans vroum.h). Tapez quelque part :
doxygen -g
mv Doxyfile vroum.doxy
Dans le fichier vroum.dowy, il faut renseigner quelques champs. Supposons que votre répertoire source vroum-1.00 soit dans /home/herve/src, dans le fichier vroum.doxy, il faut :
PROJECT_NAME           = vroum
...
PROJECT_NUMBER         = 1.00
...
OUTPUT_DIRECTORY       = vroum-html-doc
...
EXTRACT_ALL            = YES
...
EXTRACT_STATIC         = YES
...
SORT_BY_SCOPE_NAME     = YES
...
INPUT                  = /home/herve/vroum/src
...
FILE_PATTERNS          = *.h
...
EXAMPLE_PATH           = /home/herve/vroum/examples
...
EXAMPLE_PATTERNS       = *.h *.cc
...
GENERATE_LATEX         = NO
Et ensuite, tapez
doxygen vroum.doxy
et la doc est générée dans vroum-html-doc/html/index.html.