Skip to content

Les autotools #3 - Automake

Nous avons vu précédemment que « autotools » est un terme générique utilisé pour désigner l'ensemble des outils de build du projet GNU, le « GNU build system ».

Dans ce billet, nous allons faire un focus sur l'outil automake, qui est un outil permettant de produire des fichiers Makefiles portables et normalement totalement compatibles POSIX ayant pour objectif de construire une solution logicielle complète, quelque-soit la plateforme, en ne spécifiant que le strict nécessaire. Du point de vue du programmeur, l'écriture d'un Makefile se résumera donc à décrire ce qu'il souhaite réaliser dans un langage de plus haut niveau que le Makefile standard.

Description d'un fichier Makefile.am

En général, il suffit de spécifier :

  • Une ligne qui déclare le nom du programme ou de la bibliothèque à construire.
  • Une liste de fichiers sources et d'entêtes.
  • Eventuellement une liste d'options à passer au compilateur (notamment, dans quels répertoires certaines entêtes sont disponibles).
  • Eventuellement une liste d'options à passer à l'éditeur de liens (quelles sont les bibliothèques dont le programme a besoin et dans quels répertoires elles se trouvent).

Cette description simple permet à « automake » de produire un « Makefile » standard proposant un certain nombre de cibles permettant de :

  • Construire le projet.
  • Construire et exécuter les tests unitaires.
  • Nettoyer les fichiers produits lors de la construction du projet.
  • Installer le(s) programme(s) et bibliothèque(s) dans les répertoires prévus à cet effet.
  • Désinstaller le(s) programme(s) et bibliothèque(s) des répertoires dans lesquels ils ont été installés.
  • Créer une archive de distribution des sources (tarball nommé « paquet-version.tar.gz »).
  • Vérifier que cette archive est auto-suffisante, et en particulier qu'il est possible de construire le projet dans un répertoire autre que celui où les sources sont déployées.

Automake prend aussi en charge le génération et la gestion des dépendances entre les sources, les entêtes, et les objets produits, afin que lorsqu'un fichier est modifié, la prochaine invocation de « make » sache ce qui doit être reconstruit.

Cibles standards

Un « Makefile » produit par « automake » supporte nativement un certain nombre de cibles standards dont la liste est décrite ci-après :

Cible Description
make all Construit tout, les programmes, les bibliothèques, la documentation, etc. (équilavent à « make »).
make check Construit et exécute les tests unitaires (s'il en existe).
make install Installe tout ce qui a besoin d'être installé sur le système en utilisant le préfixe défini à la configuration.
make install-strip Identique à « make install », mais retire en plus les informations et symboles de débuggage (« strip »).
make installcheck Vérifie l'installation des programmes et bibliothèques précédemment installés, si spécifié et supporté.
make uninstall Désinstalle tout ce qui a précédemment été installé par « make install ».
make mostlyclean Nettoie ce qui doit être reconstruit.
make clean Nettoie les fichiers produits par « make all », les objets, les programmes, les bibliothèques, etc.
make distclean Identique à « make clean », mais retire en plus les fichiers produits par le script « configure ».
make maintainer-clean Identique à « make distclean », mais retire en plus les fichiers auto-générés s'il en existe (par lex, yacc, etc.).
make dist Créé un tarball nommé « paquet-version.tar.gz » d'après les sources définis dans les fichiers Makefile.am.
make distcheck Identique à « make dist », mais vérifie en plus que le logiciel compile, que les tests unitaires passent, etc.

Précisions concernant les différentes cibles de nettoyage :

  • Si « make » l'a construit, et que c'est un objet que l'on veut normalement reconstruire (par exemple un « .o »), alors « make mostlyclean » doit le supprimer.
  • Si « make » l'a construit, alors « make clean » doit le supprimer.
  • Si « configure » l'a construit, alors « make distclean » soit le supprimer.
  • Si le mainteneur du logiciel l'a construit à l'aide d'un outil spécial, alors « make maintainer-clean » doit le supprimer.

Certaines cibles peuvent potentiellement contenir des surcharges en ajoutant le suffixe « -local » afin de procéder à des actions non prévues en standard par « automake ».

L'exemple suivant permet d'afficher un message lorsque certaines cibles standards sont terminées :

# Makefile.am overriden targets
all-local:
	@echo "=== all done ==="

mostlyclean-local:
	@echo "=== mostlyclean done ==="

clean-local:
	@echo "=== clean done ==="

distclean-local:
	@echo "=== distclean done ==="

maintainer-clean-local:
	@echo "=== maintainer-clean done ==="

install-exec-local:
	@echo "=== install-exec done ==="

install-data-local:
	@echo "=== install-data done ==="

uninstall-local:
	@echo "=== uninstall done ==="

Nettoyer des fichiers

Si des fichiers doivent être explicitement supprimés alors qu'ils ne sont pas réellement produits lors de la construction du logiciel (par exemple après le passage des tests unitaires, ...), des variables permettent de les référencer :

Variable Description
MOSTLYCLEANFILES Liste des fichiers supplémentaires à nettoyer lors de l'exécution de « make mostlyclean »
CLEANFILES Liste des fichiers supplémentaires à nettoyer lors de l'exécution de « make clean »
DISTCLEANFILES Liste des fichiers supplémentaires à nettoyer lors de l'exécution de « make distclean »
MAINTAINERCLEANFILES Liste des fichiers gérés par le mainteneur à nettoyer lors de l'exécution de « make maintainer-clean »
# Makefile.am cleanup
MOSTLYCLEANFILES = \
	*.out \
	$(NULL)

DISTCLEANFILES = \
	*.log \
	$(NULL)

Déclarer des sous-répertoires

Dans le langage « automake », la variable « SUBDIRS » permet de spécifier les sous-répertoires à parcourir avant le traitement du répertoire courant.

# Makefile.am subdirectories
SUBDIRS = \
	subdir1 \
	subdir2 \
	subdir3 \
	$(NULL)

Déclarer une bibliothèque

Dans un fichier « Makefile.am », le suffixe « _LTLIBRARIES », signifiant « libtool libraries », est utilisé pour décrire la liste des bibliothèques à construire :

  • La variable « lib_LTLIBRARIES » permet de spécifier la liste des bibliothèques produites par « libtool » installables sur le système cible.
  • La variable « noinst_LTLIBRARIES » permet de spécifier la liste des bibliothèques produites par « libtool » non installables sur le système cible.

Le nom d'une bibliothèque est conventionnellement « lib{nom-de-bibliotheque}.la », l'extension « .la » signifiant « libtool archive ». Ce nom sera utilisé pour décrire tous les objets la composant en utilisant systématiquement le préfixe « lib{nom_de_bibliotheque}_la_ » (tous les caractères non alphanumériques du nom de la bibliothèque sont remplacés par des caractères « underscore »).

La liste des objets composant une bibliothèque « libtool » est :

Variable Description
lib{nom_de_bibliotheque}_la_SOURCES Contient la liste des sources et des entêtes non distribuables.
lib{nom_de_bibliotheque}_la_include_HEADERS Contient la liste des entêtes distribuables sur le système cible.
lib{nom_de_bibliotheque}_la_CFLAGS Contient éventuellement des options particulières de compilation.
lib{nom_de_bibliotheque}_la_CPPFLAGS Contient éventuellement des options particulières de préprocesseur.
lib{nom_de_bibliotheque}_la_LDFLAGS Contient éventuellement des options particulières d'édition de liens.
lib{nom_de_bibliotheque}_la_LIBADD Contient éventuellement la liste des bibliothèques dont l'objet dépend.
lib{nom_de_bibliotheque}_la_includedir Permet de spécifier le répertoire de destination des entêtes distribuables.

Il est devenu courant de fournir un fichier de package compatible pkg-config. Pour cela, il suffit de déclarer ce fichier dans une variable suffixée par « _DATA », de déclarer le répertoire de destination de ce fichier, généralement « $(libdir)/pkgconfig », et si ce fichier est généré par « autoconf », déclarer le nom de son template dans la variable « EXTRA_DIST ».

# Makefile.am library
lib_LTLIBRARIES = \
	libmylibrary.la \
	$(NULL)

libmylibrary_la_includedir = $(includedir)/mylibrary

libmylibrary_la_SOURCES = \
	mylibrary-priv.h \
	mylibrary.c \
	$(NULL)

libmylibrary_la_include_HEADERS = \
	mylibrary.h \
	$(NULL)

libmylibrary_la_CPPFLAGS = \
	-I$(top_srcdir) \
	$(NULL)

libmylibrary_la_LDFLAGS = \
	-L$(top_builddir) \
	-version-info 0:0:0 \
	$(NULL)

libmylibrary_la_LIBADD = \
	-lX11 -lXext \
	$(NULL)

pkgconfigdir = $(libdir)/pkgconfig

pkgconfig_DATA = \
	mylibrary.pc \
	$(NULL)

EXTRA_DIST = \
	mylibrary.pc.in \
	$(NULL)
# mylibrary.pc.in
prefix=@prefix@
exec_prefix=@exec_prefix@
libdir=@libdir@
includedir=@includedir@

Name: mylibrary
Description: my super useful library
Version: @PACKAGE_VERSION@
Requires: 
Cflags: -I${includedir}
Libs: -L${libdir} -lmylibrary

Déclarer un programme

Dans un fichier « Makefile.am », le suffixe « _PROGRAMS » est utilisé pour décrire la liste des programmes à construire :

  • la variable « bin_PROGRAMS » permet de spécifier la liste des programmes installables sur le système cible.
  • la variable « noinst_PROGRAMS » permet de spécifier la liste des programmes non installables sur le système cible.

Le nom d'un programme est relativement libre. Ce nom sera utilisé pour décrire tous les objets le composant en utilisant systématiquement le préfixe « {nom_de_programme}_ » (tous les caractères non alphanumériques du nom du programme sont remplacés par des caractères « underscore »).

La liste des objets composant un programme est :

Variable Description
{nom_de_programme}_SOURCES Contient la liste des sources et des entêtes.
{nom_de_programme}_CFLAGS Contient éventuellement des options particulières de compilation.
{nom_de_programme}_CPPFLAGS Contient éventuellement des options particulières de préprocesseur.
{nom_de_programme}_LDFLAGS Contient éventuellement des options particulières d'édition de liens.
{nom_de_programme}_LDADD Contient éventuellement les bibliothèques avec lesquelles lier le programme.
# Makefile.am program
bin_PROGRAMS = \
	myprogram \
	$(NULL)

myprogram_SOURCES = \
	myprogram.c \
	myprogram.h \
	$(NULL)

myprogram_CPPFLAGS = \
	-I$(top_srcdir) \
	$(NULL)

myprogram_LDFLAGS = \
	-L$(top_builddir) \
	$(NULL)

myprogram_LDADD = \
	$(top_builddir)/mylibrary/libmylibrary.la \
	-lcrypto -lm \
	$(NULL)

Déclarer un test unitaire

Dans un fichier « Makefile.am », le préfixe « check_ » est utilisé pour décrire tout ce qui est lié aux tests unitaires :

  • la variable « check_SCRIPTS » permet de spécifier la liste des scripts permettant de lancer les tests unitaires.
  • la variable « check_PROGRAMS » permet de spécifier la liste des programmes spécifiques contenant les tests unitaires.
  • la variable « TESTS » permet de spécifier la liste des tests unitaires à exécuter.

Le nom d'un programme de tests unitaires est relativement libre. Ce nom sera utilisé pour décrire tous les objets le composant en utilisant systématiquement le préfixe « {nom_de_programme}_ » (tous les caractères non alphanumériques du nom du programme sont remplacés par des caractères « underscore »).

La liste des objets composant un programme de tests unitaires est :

Variable Description
{nom_de_programme}_SOURCES Contient la liste des sources et des entêtes.
{nom_de_programme}_CFLAGS Contient éventuellement des options particulières de compilation.
{nom_de_programme}_CPPFLAGS Contient éventuellement des options particulières de préprocesseur.
{nom_de_programme}_LDFLAGS Contient éventuellement des options particulières d'édition de liens.
{nom_de_programme}_LDADD Contient éventuellement les bibliothèques avec lesquelles lier le programme.
# Makefile.am unit-test
check_SCRIPTS = \
	testsuite.sh \
	$(NULL)

check_PROGRAMS = \
	testsuite \
	$(NULL)

testsuite_SOURCES = \
	testsuite.c \
	testsuite.h \
	$(NULL)

testsuite_CPPFLAGS = \
	-I$(top_srcdir) \
	-I$(top_srcdir)/mylibrary \
	$(NULL)

testsuite_LDFLAGS = \
	-L$(top_builddir) \
	$(NULL)

testsuite_LDADD = \
	$(top_builddir)/mylibrary/libmylibrary.la \
	$(NULL)

TESTS = \
	testsuite.sh \
	$(NULL)

EXTRA_DIST = \
	testsuite.sh \
	$(NULL)

MOSTLYCLEANFILES = \
	testsuite.log \
	$(NULL)

What else ?

Vous avez pu constater au travers ces quelques lignes que cet outil est doté de très nombreuses possibilités de construction de projets. Dans le prochain billet, nous parlerons de son allié, « libtool ».

Une coquille, une faute ?

Vous constatez une coquille, une faute d'orthographe ou de grammaire ? Dites-le moi par mail !

Rétroliens

Pas de rétroliens

Commentaires

Afficher les commentaires en Vue non groupée | Vue groupée

Pas de commentaires

L'auteur n'a pas autorisé l'ajout de commentaires pour ce billet.

Ajouter un commentaire


Pour éviter le spam par des robits automatisés (spambots), merci d'entrer les caractères que vous voyez dans l'image ci-dessous dans le champ de fomulaire prévu à cet effet. Assurez-vous que votre navigateur gère et accepte les cookies, sinon votre commentaire ne pourra pas être enregistré.
CAPTCHA

Form options

Les commentaires postés doivent être approuvés avant d'être affichés dans le blog.