Retrouvez cet article dans : Linux Magazine 77
Dans le premier article sur les auto-tools, nous prenions pour exemple un programme simple réparti sur deux fichiers. Le programme principal appelait la fonction afficher() définie dans un autre fichier. Ce mois-ci, nous allons pousser le sujet en répartissant le code sur plusieurs répertoires et en profiter pour aborder la création des bibliothèques avec libtool.
Introduction
Votre premier programme bonjour_le_monde.c ne comptait probablement pas plus de lignes que le nombre de doigts d’un être humain normalement constitué (les utilisateurs d’Emacs mis à part [1]). Puis à l’aide de votre éditeur préféré (Emacs pour certains), vous l’avez édité, lui avez ajouté des fonctions, pour en faire un code source dont le nombre de lignes dépasse largement la moyenne (utilisateurs d’Emacs compris). En résumé, vous devez découper votre code et le répartir sur plusieurs fichiers. Avant d’aborder l’exemple qui nous suivra tout au long de cet article, nous verrons quelques idées sur l’art et la manière de découper le code. Puis, nous reprendrons l’exemple du premier article sur les auto-tools afin de le bricoler un peu, afin d’aboutir à une bibliothèque statique réalisée sans l’aide de libtool. Comme il est généralement préférable et préféré de générer des bibliothèques dynamiques, si possible avec libtool, nous terminerons avec cela.
L’art et la manière de répartir son code sur plusieurs fichiers
Répartir son code sur plusieurs fichiers est une opération d’apparence simple. Copiez et collez le code dans d’autres fichiers, créez quelques fichiers d’en-tête avec une jolie extension .h, et ajoutez quelques lignes en #include «fichier.h» et le tour est joué. Résultat, votre code est maintenant pire qu’avant, car non seulement vous ne vous y retrouvez plus, mais vous devez en plus effectuer vos recherches sur plusieurs fichiers au lieu d’un.
Le premier principe à respecter est de disposer pour chaque fichier d’extension .c un fichier de même nom et d’extension .h. Dans ce dernier, mettez les prototypes des fonctions que vous souhaitez accéder depuis le code situé dans les autres fichiers. Ce principe est généralement respecté, à l’exception de ceux qui préfèrent tout mettre dans un seul fichier d’en-tête. Sauf raison valable (nous en verrons une plus loin), ceci est une bêtise, car elle empêche de structurer le code.
Structurer le code, voici le deuxième principe. Il s’agit de regrouper les fonctions et structures qui travaillent sur un même type ou ensemble de données. Ainsi, vous allez placer dans le même fichier toutes vos fonctions servant à analyser la ligne de commande. Dans un autre fichier, vous pourrez trouver celles servant à la gestion des erreurs de votre programme. L’idée, ici, est de pouvoir isoler virtuellement (et concrètement plus loin dans l’article) certaines parties du code pour pouvoir les compiler à part.
Outre les fonctions de journalisation (log), celles d’analyse de la ligne de commande et celles de traitement des erreurs que nous retrouvons généralement dans tout programme, vous pouvez procéder de la façon suivante. Isolez les structures de données, ce qui vous permet de démarrer l’écriture de fichiers d’en-tête, à raison d’un par structure. Dans les fichiers de code source correspondant, mettez-y les fonctions qui initialisent, remplissent, vident ou modifient ces structures de données. Chaque fichier est ici normalement indépendant des autres.
Mais il reste les fonctions qui, en entrée, prennent plusieurs structures de données et, en sortie, génèrent ou modifient d’autres structures de données. Ces fonctions peuvent être mises dans d’autres fichiers de code source et regroupées en fonction des structures de données qu’elles altèrent ou génèrent. Les fichiers de code source correspondant ont plusieurs caractéristiques : ils doivent alors inclure une référence (merci #include) aux autres fichiers sources; ils sont le cœur de votre programme ; les fonctions appelées par main() se trouvent dans ces fichiers. Ces fonctions ne nous intéressent pas dans la suite de l’article, car nous allons nous concentrer sur celles que nous pouvons isoler.
Avant d’attaquer avec l’exemple, une petite remarque s’impose. L’intérêt d’isoler certains morceaux de code est de pouvoir les rendre réutilisables. Vous pouvez ainsi partager plus facilement et plus proprement le même code entre deux programmes constituant la même application et même reprendre ce code tel quel pour d’autres applications de votre cru.
L’exemple
Nous allons reprendre pour exemple, celui qui va nous suivre tout au long de l’article, l’exemple du premier article sur les auto-tools. Il était composé d’un fichier afficher.c et d’un fichier main.c. Le code était déjà un peu structuré car la fonction afficher() se trouve déjà dans un fichier distinct du reste. La différence majeure entre l’exemple de cet article et l’autre consiste à déplacer ce fichier afficher.c dans un nouveau répertoire libmytoolkit/, et donc à adapter le fichier d’en-tête en conséquence. Voici notre arborescence :
AUTHORS (le nom des auteurs) ChangeLog (contenu sans importance) configure.ac libmytoolkit/afficher.c libmytoolkit/Makefile.am libmytoolkit/mytoolkit.h Makefile.am NEWS (contenu sans importance) README (contenu sans importance) bonjour/main.c bonjour/Makefile.am
Remarque :
Le répertoire que nous appelions src/ est devenu bonjour/ pour refléter le nom du programme dont les sources sont à cet endroit. Cette modification a pour objectif d’homogénéiser les noms des répertoires et de ne pas avoir d’une part libmytoolkit/ et d’autre part src/. Le premier faisait partie des sources du projet.
Les fichiers sont les suivants :
libmytoolkit/afficher.c
#include <stdio.h>
#include <stdlib.h>
#include “mytoolkit.h”
int afficher(char*str) {
printf(«%s\n», str);
return(0);
}
libmytoolkit/mytoolkit.h #ifndef MYTOOLKIT_H #define MYTOOLKIT_H int bonjour(const char*msg); #endif
bonjour/main.c
#include <stdio.h>
#include <stdlib.h>
#include <mytoolkit.h>
int
main (int argc, const char **argv)
{
afficher(“bonjour”);
exit (EXIT_FAILURE);
}
configure.ac # Process this file with autoconf to produce a configure script. AC_PREREQ(2.59) AC_INIT(bonjour, 0.2, ymettier@libertysurf.fr) AM_INIT_AUTOMAKE # Checks for programs. AC_PROG_CC AC_PROG_MAKE_SET AC_CONFIG_FILES([ Makefile libmytoolkit/Makefile bonjour/Makefile ]) AC_OUTPUT
Makefile.am SUBDIRS=libmytoolkit bonjour
bonjour/Makefile.am bin_PROGRAMS=bonjour bonjour_SOURCES=main.c
Remarquez au passage l’ordre des répertoires dans le fichier Makefile.am : nous devons compiler d’abord la bibliothèque et ensuite le programme principal. Cela est évident après avoir fait l’erreur !
Votre bibliothèque statique avec les auto-tools
Notre exemple, légèrement modifié pour prendre en compte la présence du nouveau répertoire libmytoolkit/, ne peut fonctionner tel quel. La séquence magique suivante ne fonctionne pas :
aclocal autoconf automake -a -c
En effet, en indiquant le nouveau répertoire à automake dans le fichier Makefile.am, nous demandons aux auto-tools (automake) de lire le fichier libmytoolkit/Makefile.am. Nous devons donc le créer pour générer un fichier archive, autrement appelé « bibliothèque statique », d’extension .a. Voici ce fichier :
libmytoolkit/Makefile.am noinst_LIBRARIES=libmytoolkit.a libmytoolkit_a_SOURCES=afficher.c mytoolkit.h
La première ligne commence par noinst_LIBRARIES au lieu du bin_PROGRAMS que nous connaissions. Si vous souhaitez installer cette bibliothèque lorsque vous lancez make install, mettez lib_LIBRARIES. Avec le préfixe noinst, vous indiquez que vous ne souhaitez pas installer la bibliothèque lors de la phase d’installation du logiciel.
Cette variable lib_LIBRARIES ou noinst_LIBRARIES contient les bibliothèques que vous voulez créer. Nous indiquons simplement libmytoolkit.a. Il nous faut alors préciser, ligne suivante, les fichiers sources nécessaires à sa compilation. La variable est composée, comme nous l’avons vu pour les programmes, du nom de l’objet à créer, suivi du suffixe _SOURCES. Notez que le caractère . (point) est interdit dans les noms de variable et vous devez le remplacer ici par un caractère tiret bas.
Relancez la séquence magique indiquée plus haut et cela devrait mieux fonctionner. Mieux, mais pas tout à fait. En effet, un message d’erreur vous indique (automake-1.9.4 pour moi) qu’il manque quelque chose :
$ automake -a -c libmytoolkit/Makefile.am:1: library used but `RANLIB’ is undefined libmytoolkit/Makefile.am:1: libmytoolkit/Makefile.am:1: The usual way to define `RANLIB’ is to add `AC_PROG_RANLIB’ libmytoolkit/Makefile.am:1: to `configure.ac’ and run `autoconf’ again.
Ce message est gentil de la part d’automake, car il nous dit quoi faire. En effet, pour créer notre bibliothèque statique, nous avons besoin de ranlib. Ajoutez cette ligne, par exemple à la suite de AC_PROC_CC dans le fichier configure.ac et relancez encore une fois la séquence magique qui s’exécute maintenant jusqu’au bout sans difficulté. Exécutez configure suivi de make...
$ make Making all in libmytoolkit [...] Making all in bonjour [...] main.c:4:23: error: mytoolkit.h: No such file or directory
... et les ennuis recommencent. Mais remarquez que tout s’est bien passé pour la bibliothèque qui est compilée. Nos soucis sont la prise en compte de la bibliothèque par le programme principal dans le répertoire bonjour/. Pour cela, nous devons indiquer au compilateur le chemin de l’emplacement où se trouve mytoolkit.h avec l’option -I et à l’éditeur de liens celui de libmytoolkit.a. De la même manière que vous aviez indiqué les sources du programme bonjour avec la variable de suffixe _SOURCES, créez une nouvelle variable de suffixe _CPPFLAGS pour les options du préprocesseur (et _CFLAGS pour celles du compilateur lorsque vous en avez l’utilité), et une de suffixe _LDADD pour indiquer à l’éditeur de liens les divers objets à rassembler. Cela donne le fichier suivant :
bonjour/Makefile.am
bin_PROGRAMS=bonjour
bonjour_SOURCES=main.c
bonjour_CPPFLAGS=-I${top_srcdir}/libmytoolkit
bonjour_LDADD=${top_builddir}/libmytoolkit/libmytoolkit.a
Mais quelles sont ces étranges variables top_srcdir et top_builddir ? Pourquoi ne pas tout simplement avoir mis -I../libmytoolkit pour les options du compilateur, et de même pour l’éditeur de liens ? Exécutez maintenant make distcheck et vous en aurez la raison. En effet, lors de la compilation, le répertoire courant, le répertoire des sources et le répertoire où sont placés les objets compilés sont trois répertoires différents. Ils peuvent être au même emplacement, ce qui est le cas lorsque vous exécutez simplement make.
Mais avec make distcheck, ainsi que peut-être avec votre distribution préférée lorsque vous créez un paquetage, il n’est pas dit que cet emplacement soit le même pour les trois répertoires.
Alors mieux vaut prendre les devants en ne tenant pas compte du répertoire courant et en utilisant des variables. Le fichier mytoolkit.h fait partie des sources alors que libmytoolkit.a est un objet compilé. Le premier se trouve dans l’arborescence des sources dont la racine est définie dans ${top_srcdir} et le second dans l’arborescence de compilation, de racine ${top_builddir}. Il ne vous reste plus qu’à compléter en fonction de votre arborescence de travail !
Vous disposez, à l’issue de la séquence magique, d’une bibliothèque dite « statique » qui ne s’installe pas (à cause du préfixe noinst dans le fichier libmytoolkit/Makefile.am) et d’un programme bonjour tirant parti de cette bibliothèque avec laquelle il est statiquement lié (d’où ce nom de bibliothèque statique pour libmytoolkit.a). Il ne nous reste plus qu’à rendre la chose dynamique.
Une bibliothèque dynamique, c’est mieux !
Pour rendre la bibliothèque dynamique, lorsque vous utilisez les auto-tools, il est souhaitable d’utiliser libtool. Cet outil vous permet de rendre portable la génération des bibliothèques sur diverses architectures sans que vous n’ayez la moindre notion de comment faire.
Par exemple, sur GNU/Linux, si vous savez créer une bibliothèque d’extension .so, vous serez bien dans l’embarras lorsque vous vous rendrez compte que sur Mac OS X, votre bibliothèque prend l’extension .dylib ! Avec libtool, vous n’avez plus à vous préoccuper de l’extension, du numéro de version de la bibliothèque... Libtool s’en charge pour vous pour peu que vous sachiez lui signifier ce que vous voulez faire.
Pour utiliser libtool, commencez par modifier votre fichier configure.ac afin d’y retirer la ligne contenant AC_PROG_RANLIB si elle existe (ce qui est le cas dans notre exemple), et mettez à la place AC_PROG_LIBTOOL.
En effet, la première macro est redondante par rapport à la seconde. Cette modification est la seule que vous apportez au fichier configure.ac.
Les fichiers Makefile.am des répertoires libmytoolkit/ et bonjour/ subissent des transformations dues à libtool. En effet, libtool définit un nouveau type de bibliothèque, dans un format qui lui est propre, qui est indépendant du système, et qui cache la notion de bibliothèque telle que définie par le système.
Autrement dit, avec libtool, nous parlons de bibliothèques sans savoir comment elles sont implémentées sur le système. La première conséquence est que les bibliothèques au sens libtool du terme prennent une extension .la. Cela nous amène au fichier bonjour/Makefile.am dont la seule modification est cette fameuse extension : remplacez libmytoolkit.a par libmytoolkit.la.
Les choses se corsent avec le fichier libmytoolkit/Makefile.am. En effet, nous ne voulons plus une bibliothèque statique, comme cela était défini via la variable noinst_LIBRARIES, mais une bibliothèque libtool.
Pour cela, nous changeons le suffixe qui devient _LTLIBRARIES. Comme nous souhaitons maintenant installer notre bibliothèque dans le sous-répertoire lib du répertoire d’installation, nous mettons lib_LTLIBRARIES=libmytoolkit.la. Remarquez que l’extension de la bibliothèque change aussi. Le fichier libmytoolkit/Makefile.am devient alors ceci :
lib_LTLIBRARIES=libmytoolkit.la libmytoolkit_la_SOURCES=afficher.c mytoolkit.h
Remarquez à nouveau que, dans la seconde ligne, l’extension qui précède le suffixe _SOURCES est devenu _la et que le point est, encore une fois, remplacé ici par un tiret bas.
Il faut maintenant lancer la séquence magique à nouveau, mais elle a changé suite à l’apparition de libtool. Vous devez commencer par un premier appel à libtoolize, avec l’option -f si nécessaire (si vous l’avez déjà lancé). La séquence magique est ensuite la même qu’au début :
libtoolize -f aclocal autoconf automake -a -c
Compilez maintenant avec la séquence habituelle :
./configure make make install
Vous devriez normalement vous retrouver avec un répertoire lib dans votre répertoire d’installation (ici /usr/local par défaut) qui contient, sur GNU/Linux, votre bibliothèque sous divers formats :
- Dynamique, d’extension
.so(ou.dylibsur Mac OS X) ; - Statique, d’extension
.a; - Libtool, d’extension
.la;
Liez votre programme et votre bibliothèque de façon dynamique
Lorsque vous utilisez une bibliothèque externe, vous n’avez qu’à utiliser l’option -L de l’éditeur de liens pour indiquer l’emplacement de la bibliothèque, et -l avec son nom.
Dans votre programme, dans bonjour/Makefile.am, cela est pareil, mais la complication vient des chemins à indiquer, car la bibliothèque n’est pas encore installée lorsque vous compilez votre programme.
Vous devez utiliser la variable ${top_builddir} que nous avons déjà vue précédemment. Voici le fichier bonjour/Makefile.am prêt à l’emploi pour lier dynamiquement la bibliothèque au programme :
bin_PROGRAMS=bonjour
bonjour_SOURCES=main.c
bonjour_CPPFLAGS=-I${top_srcdir}/libmytoolkit
bonjour_LDFLAGS=-L${top_builddir}/libmytoolkit -lmytoolkit
Remarque
La variable de suffixe _LDADD est devenue _LDFLAGS ici, car il s’agit d’options pour l’éditeur de lien. Nous ne sommes plus en train d’ajouter un objet à lier, mais d’indiquer qu’il faut lier une bibliothèque ainsi que son emplacement.
Le numéro de version de la bibliothèque
Avant d’en finir avec les bibliothèques, il est un point qui vous horripilera si vous n’aimez pas le joli numéro de version 0.0.0 que libtool a affublé à votre bibliothèque dynamique.
Comment le changer ? Nous devons aborder la gestion des numéros de versions de libtool. Sur Linux (entre autres), un numéro est noté ainsi : majeur.mineur.micro.
Vous allez devoir oublier cette notation au profit de la notation libtool : actuel.révision.ancienneté.
Elle fonctionne sur la notion de compatibilité des API entre diverses versions d’une bibliothèque. Voici la signification de cette notation :
actuel(ac) : une version de bibliothèque sera compatible avec toutes les versions antérieures portant le même numéroactuel;révision(rev) : deux versions de la bibliothèque dont seul ce numéro change sont compatibles à 100%. En d’autres termes, le changement du numérorévisiona pu être motivé par une correction de bogue ou une amélioration d’un algorithme interne par exemple ;ancienneté(anc) : il indique la différence entre le numéroactuelde la version la plus ancienne restant compatible avec la version actuelle. Par exemple, la version 4.13.2 est compatible avec toutes les versions 2.x.y et 3.x’.y’.
Pour vérifier si vous avez bien compris, répondrez-vous correctement aux questions suivantes ?
Quel est le premier numéro de version ?
Avec libtool, commencez toujours par 0.0.0. Cela peut générer un numéro 0.0.0 au niveau du système, mais aussi inhabituel que cela peut vous paraître, ne cherchez pas à changer cela.
Je viens de modifier mon API, quels numéros dois-je incrémenter ?
Avez-vous uniquement fait des ajouts ou un véritable changement rendant la nouvelle bibliothèque incompatible avec l’ancienne ? En cas d’ajout, incrémentez actuel et ancienneté et mettez révision à zéro : ac:rev:anc devient ac+1:0:anc+1.
Si la modification est plus profonde, incrémentez seulement le numéro actuel et mettez tout le reste à zéro pour signifier l’incompatibilité avec les versions antérieures. ac:rev:anc devient ac+1:0:0.
Je viens de modifier le code, sans toucher à l’API, quels numéros dois-je incrémenter ?
Incrémentez uniquement le numéro de révision prévu à cet usage : ac:rev:anc devient ac:rev+1:anc.
Je ne sais pas quoi me faire à manger ce soir
Ce n’est pas l’endroit pour poser de telles questions ! Néanmoins, voici quelques suggestions : une pizza ou une quiche, un bon steak avec des légumes, des lasagnes ou des pâtes, un bon riz avec quelques sushis ou sashimis... Pour le dessert, ouvrez votre frigo et voyez ce qu’il vous reste !
Indiquez à libtool le numéro de version de la bibliothèque
Lorsque vous avez décidé ou calculé le numéro de version, vous devez l’indiquer à libtool avec l’option -version-info de l’éditeur de liens, soit la variable libmytoolkit_la_LDFLAGS du fichier libmytoolkit/Makefile.am. Pour cela, et pour centraliser les divers numéros de version (celui du programme, celui des bibliothèques...) définissez trois variables dans votre fichier configure.ac. Celui-ci devient (extrait) :
AC_INIT(bonjour, 0.2, ymettier@libertysurf.fr) AM_INIT_AUTOMAKE LIBMYTOOLKIT_AC=0 LIBMYTOOLKIT_REV=0 LIBMYTOOLKIT_ANC=0 AC_SUBST(LIBMYTOOLKIT_AC) AC_SUBST(LIBMYTOOLKIT_REV) AC_SUBST(LIBMYTOOLKIT_ANC) # Checks for programs. AC_PROG_CC
Le fichier libmytoolkit/Makefile.am s’écrit alors ainsi :
lib_LTLIBRARIES=libmytoolkit.la
libmytoolkit_la_SOURCES=afficher.c mytoolkit.h
libmytoolkit_la_LDFLAGS=-version-info ${LIBMYTOOLKIT_AC}:${LIBMYTOOLKIT_REV}:${LIBMYTOOLKIT_ANC}
Mais pourquoi ne pas utiliser -release, plus simple ?
L’option -release permet d’indiquer un numéro de version complet. Cette manière de faire brise la compatibilité binaire qui peut exister avec des bibliothèques antérieures et c’est pour cela qu’elle est déconseillée. Il peut exister des cas particuliers où -release est préférable. En voici un : lorsque votre bibliothèque n’est destinée à être utilisée que par votre projet, le numéro de version de votre projet peut convenir pour peu qu’il respecte la notation majeur.mineur.micro. Alors, vous pouvez écrire ceci :
libmytoolkit_la_LDFLAGS=-release ${VERSION}
Attention:
A l’exception de ce cas particulier, il est fortement déconseillé d’indiquer le numéro de version du projet comme numéro de version d’une bibliothèque. Ainsi, à l’intérieur d’un projet, une bibliothèque doit avoir sa numérotation à part.
Le fichier d’en-tête de la bibliothèque
Votre programme compile, s’installe et s’exécute sans souci, mais si vous vous arrêtez ici, un problème se posera aux utilisateurs de votre bibliothèque partagée.
Qu’est-ce donc que ce fichier mytoolkit.h et où le trouver ? L’erreur vient d’ici : ce fichier étant un fichier source, il est facile d’oublier de l’installer. Pour cela, ajoutez encore une ligne au fichier libmytoolkit/Makefile.am, par exemple à la fin :
include_HEADERS=mytoolkit.h
Vous indiquez ainsi que le fichier est un fichier d’en-tête via le suffixe _HEADERS, et qu’il doit être installé dans le sous-répertoire include/ du répertoire d’installation. Vous pouvez encore une fois exécuter la séquence magique, la dernière pour cet article.
Comment générer un binaire statique ?
La génération d’un binaire statique ne doit pas être décidée par le développeur, mais par celui qui compile le programme et l’installe. Le développeur a juste pour rôle de permettre cela lorsque possible. Avec libtool, ce rôle est entièrement rempli, de façon transparente pour le développeur, ce qui constitue encore une bonne raison d’utiliser libtoool pour créer des bibliothèques.
La personne qui compile votre programme, si elle souhaite générer un binaire lié statiquement à votre bibliothèque, devra indiquer l’option -static à libtool. Cela se fait simplement via la variable d’environnement $LDFLAGS. Voici ce qu’il faut taper :
configure make LDFLAGS=-static make instal
Attention
Si vous voulez générer une bibliothèque dans une forme dynamique aussi bien que statique et lier le binaire à la version statique, vous (le développeur) devez ruser.
En effet, la variable LDFLAGS ne doit pas contenir -static lors de la génération de la bibliothèque, contrairement à l’étape de création du binaire. C’est à vous, développeur, de prévoir une variable bonjour_LDFLAGS qui prendra au bon vouloir de celui qui compile l’option -static ou non.
Voici une manière de faire, dans le fichier bonjour/Makefile.am :
bin_PROGRAMS=bonjour
bonjour_SOURCES=main.c
bonjour_CPPFLAGS=-I${top_srcdir}/libmytoolkit
bonjour_LDFLAGS=-L${top_builddir}/libmytoolkit -lmytoolkit ${BONJOUR_LDFLAGS}
En documentant correctement le manuel destiné à celui qui compile votre programme, vous lui indiquez que pour compiler la bibliothèque sous forme à la fois statique et dynamique, mais pour lier le programme de façon statique à la bibliothèque, il peut exécuter ceci :
configure make BONJOUR_LDFLAGS=-static make install
Conclusion
Grâce à cet article, j’espère que le terrain des bibliothèques et de libtool vous est quelque peu débroussaillé.
Certaines astuces, comme la dernière, sont rarement expliquées. D’autres, comme la façon de numéroter les versions, se trouvent dans le manuel de libtool et ailleurs.
Il ne vous reste plus qu’à découper correctement votre code et à créer des bibliothèques en pensant votre code pour qu’il soit réutilisable.
Rappelez-vous, c’est en séparant le toolkit du cœur de Gimp que GTK+ est né. Et c’est en isolant les objets de base par rapport aux objets graphiques que glib, gdk et gtk sont issus de GTK+.
Aujourd’hui, ces bibliothèques, initialement au cœur de Gimp, participent aux fondations du projet Gnome, et bien d’autres encore !
Remerciements :
Remerciements à Guillaume Rousse pour sa relecture et ses avis éclairés.
Liens :
Le manuel d’autoconf :
http://www.gnu.org/manual/autoconf/index.html ;
Le manuel d’automake :
http://www.gnu.org/manual/automake/index.html ;
Le manuel de libtool :
http://www.gnu.org/software/libtool/manual/ ;
C en action, O’Reilly.

