Les outils Automake et Autoconf....
Vous trouverez ci-après une présentation des outils de création de scripts de configuration pour la gestion et l'installation de logiciels et de son code source. Au travers de cette présentation, des exemples simples vous permettrons de mettre en pratique rapidement les concepts, pour ensuite les approfondir grâce aux références de manuels....
Sommaire
- Concepts de base
- Outil Autoconf
- Outil Automake
- Gestion des fichiers d'en-tête (outil Autoheader)
- Outil Configure
- Tableau récapitulatif
- FAQ & Eventuels problèmes
- Bibliographie
1. Concepts de base
Actuellement, si l'on veut développer une application informatique "correctement", on va écrire plusieurs fichiers sources. La multiplicité de ces fichiers fait que la maintenance de notre projet devient vite contraignante. C'est pourquoi, paresse oblige, ces tâches (compilation, gestion des dépendances....) sont confiées à un Makefile.
Mais certaines opérations restent encore difficile en raison de l'évolution de notre programme, ou encore en raison de l'adaptation sur différents systèmes. Ainsi, il faut quand même maintenir le Makefile.
C'est là qu'interviennent les outils de configuration et de création de scripts automatiques (Autoconf, Automake, Configure...).
Ces outils ont deux objectifs principaux :
- simplifier le développement de programme portable. Ils permettent aux développeurs de se concentrer sur l'écriture du programme, en simplifiant les détails de portabilité entre les Unix et en lui permettant de décrire la structure de son application avec un langage plus simple que celui du Makefile.
- simplifier la compilation des programmes distribués sous formes de fichiers sources. Tous les programmes sont compilés en utilisant deux étapes simples et standards (./configure et make). Il n'y a pas besoin d'installer d'outils spécifiques pour l'installation.
Seul les développeurs de programme doivent avoir installés les outils présentés ci-après. Les personnes qui veulent simplement installer un logiciel à partir des sources n'ont pas besoin d'outils spéciaux, excepté un shell Unix, un programme make et un compilateur C.
Voici les deux outils principaux :
- Automake : système pour décrire la structure de l'application, en permettant au développeur d'écrire un Makefile simplifié. Cet outil génère un fichier 'moule' du Makefile à partir d'un série de macros.
- Autoconf : outil qui fournit une structure de portabilité, basée sur un ensemble de tests des spécificités de la machine au moment de l'installation.
Pour commencer à utiliser ces outils et construire un package près à l'installation, vous devez écrire trois fichiers (configure.in, makefile.am, acconfig.h) et lancer certains outils pour générer les fichiers additionnels.
Voici le schéma des dépendances entre les fichiers et les outils (le fichier acconfig.h sera présenté plut tard, restons pour l'instant dans un schèma simple!! :) ).
Les deux outils possèdent la même philosophie. A partir de fichier simple écrit par le développeur, ils vont générer des fichiers "moules", qui seront complétés au dernier moment (lors de la compilation).
2. Outil Autoconf
Autoconf est un outil qui génère un script exécutable (configure) pour adapter l'installation de nos codes sources en fonction du système et de la machine d'installation. Le script configure est indépendant d'Autoconf, ainsi l'utilisateur n'a pas besoin d'avoir l'outil Autoconf.
Ce script est créé à partir d'un fichier appelé configure.in, qui contient la description de toutes les options et spécificités que l ’on veut tester.
Ensuite, c'est le script configure qui effectuera réellement les tests. Il convertira le fichier "moule" Makefile.in en véritable Makefile.
Le principal fichier pour la génération du script configure est comme vous l'avez compris le fichier configure.in.
- Configure.in : ce fichier contient un ensemble de macros Autoconf, décrivant les options et les caractéristiques du système à tester (comme la présence de fichiers d'en-tête ou de fonctions). De nombreuses macros existent déjà pour tester certains aspects, mais il est possible de créer ses propres macros à partir de "templates".
Pour commencer, vous pouvez lancer la commande autoscan, qui va générer un fichier nommé configure.scan. Ce fichier peut servir de prototype pour configure.in. Cette commande examine les fichiers sources en cherchant les problèmes de portabilité. Il ne vous reste plus qu'à renommer le fichier configure.scan en configure.in, et à le compléter par d'autres macros...
Le langage de configure.in est procédural, c ’est à dire que chaque ligne du fichier est une commande qui est exécutée (pour la syntaxe, regardez l'exemple).
- aclocal.m4 : nécessaire lorsque l'on utilise Automake, ou bien si on a défini ses propres macros. Il est possible de générer ce fichier à partir de la commande aclocal. Cet outil recherche les définitions de macros externes dans les fichiers .m4 (écrit si on redéfini des macros) et dans le fichier Configure.in, et créé le fichier aclocal.m4. Par exemple, si on utilise Automake, l'outil aclocal rendra compréhensible les macros automake (ex.
AM_INIT_AUTOMAKE
issue de configure.in) pour Autoconf (en les traduisant dans le fichier aclocal.m4).
Ce qui donne le schéma de relation suivant :
Dans un premier temps, je vais redéfinir quelques règles sur la syntaxe du fichier Configure.in :
- les lignes qui commencent par dnl sont des commentaires et ne sont pas exécutées par autoconf.
- le fichier doit toujours commencer par la macro
AC_INIT(exemple.c)
. Cette macro prend en argument le nom d'un des fichiers caractéristique de notre package (pour vérifier que le programme est exécuté au bon endroit).
- il doit également toujours se terminer par
AC_OUTPUT(Makefile)
. Cette macro contient la liste des fichiers que configure doit générer. Il s'agit normalement de la liste du ou des Makefile dans chacun de leur répertoire (chacun des fichiers est séparés par un espace (AC_OUTPUT(Makefile src/Makefile man/Makefile X/Imakefile)
.
Maintenant, prenons l'exemple d'un projet contenant un fichier source nommé exemple.c, destiné à afficher un message texte. Voici les étapes à suivre pour utiliser l'outils Autoconf et générer un script configure (le prompt est repésenté par 'yb@I2000>'
) :
yb@I2000 > autoscan
Cette commande va générer un fichier configure.scan, qu'il faut renommer en configure.in. Ce fichier, une fois complété aura l'allure suivante :
dnl Process this file with autoconf to produce a configure script
AC_INIT(exemple.c)
AM_INIT_AUTOMAKE(exemple, 1.0)
dnl Checks for programs
AC_PROG_CC
AC_OUTPUT(Makefile)
La ligne AC_PROG_CC
permet de chercher le compilateur C de la machine d'installation. J'ai également inséré une ligne pour Automake : AM_INIT_AUTOMAKE(example, 1.0)
. Cette dernière permet de définir le nom du package, ainsi que le numéro de version. Les différents préfixes des macros indiquent de quel outil la commande provient. Les macros qui commencent par AC_
sont celles d'Autoconf et celles qui commencent par AM_
sont celles d'Automake.
Une fois le fichier configure.in écrit, il faut lancer les commandes suivantes :
yb@I2000 > aclocal
yb@I2000 > autoconf
La première permet d'interpréter la macro pour automake (et créé le fichier aclocal.m4) et la seconde génère tout simplement le script configure.
3. Outil Automake
Automake est un outil qui permet de minimiser les tâches de maintenance, en décrivant la structure de l'application. En fait, il génère un (ou des) fichier(s) "moule" du Makefile, nommé Makefile.in, à partir d'une série de macros contenues dans le(s) fichier(s) Makefile.am. Cet outil est souvent associé à Autcoconf.
Automake se base sur le fichier Configure.in pour savoir quels sont les Makefile.in
à générer. La description de ce que doit contenir un de ces fichiers est elle-même contenue dans un fichier Makefile.am (voir le § suivant).
Je rappelle juste que le fichier Makefile.in est celui qui va être transformé par l'outil Configure en véritable Makefile. Automake permet de générer tout simplement ce fichier... :)
L'outil Automake s'appuie sur deux fichiers pour générer le Makefile.in. Le principal bien sur est le fichier Makefile.am.
- Makefile.am : ce fichier décrit comment le code doit être construit. Il contient une série de définitions de macros Automake sous la forme :
variable = valeur
Il peut également contenir des définitions de "cible" de Makefike (ex. : clean, install...). Toutes ces définitions vont induire les règles du Makefile.
- Configure.in : ce fichier, décrit pour l'outil Autoconf, peut contenir également certaines macros Automake, par exemple pour savoir quels sont les Makefile.in à générer. Pour utiliser Automake, ce fichier doit contenir au moins un ligne spécifique qui est :
AM_INIT_AUTOMAKE(package,version)
Les paramètres à la directive AM_INIT_AUTOMAKE
permettent de définir le nom du package correspondant au programme, ainsi que son numéro de version.
Pour d'autres règles, voir le § mini-exemple...
Avant de rentrer dans un exemple plus concret, voici quelques règles générales et de syntaxe à respecter pour la création des fichiers Makefile.am et Configure.in :
- pour chaque Makefile.am, il doit y avoir un Makefile correspondant dans la macro
AC_OUTPUT
du fichier Configure.in.
- il y a en général un Makefile.am par répertoire du projet. Pour chaque répertoire avec des sous-répertoires, le fichier Makefile.am doit contenir la ligne suivante :
SUBDIRS = dir dir ...
où chaque dir est le nom d'un sous-répertoire.
- une ligne commençant par ## dans le fichier Makefile.am est ignorée par Automake. Il s'agit donc d'un ligne de commentaire.
- si le package doit créer un programme, alors dans le fichier Makefile.am situé dans le répertoire où le programme doit être construit, il y aura une ligne du type :
bin_PROGRAMS = monProgramme
où monProgramme
est le nom du programme. Ensuite, il y a une ligne pour spécifier les fichiers sources nécessaires :
monProgramme_SOURCES = file file ...
où chaque file est le nom d'un fichier source lié au programme (ex. : main.c). Les fichiers desquels dépendent les file, comme par exemple les fichiers inclus, sont automatiquement détectés et incorporés au Makefile.
Reprenons notre exemple, avec cette fois ci, deux répertoires (src et doc), et l'appel à une bibliothèque (libexemple.a).
Dans un premier temps, il faut donc écrire un fichier Configure.in (reprendre celui montrer en exemple d'Autoconf). Ensuite, écrire le fichier Makefile.am suivant :
## Process this file with automake to produce makefile.in
SUBDIRS = src doc
bin_PROGRAMS = exemple
exemple_SOURCES = exemple.c fonction.c exemple.h
exemple_LDADD = libexemple.a
Il ne vous reste plus qu'à lancer la commande suivante pour générer le fichier Makefile.in :
yb@I2000 > automake --add-missing
L'option passée à Automake l'informe qu'il doit installer les fichiers qui pourraient éventuellement manquer. En effet, Automake requiert certains fichiers dans certaines situations. Il est aussi possible de spécifier l'option --foreign, pour avoir un niveau de rigueur décontracté (par opposition à --gnu, option par défaut, qui requiert les fichiers INSTALL, NEWS, README, COPYING, AUTHORS, et ChangeLog dans le répertoire source). Pour les autres options admises par Automake, voir le manuel Automake...
4. Gestion des fichiers d'en-tête (outil Autoheader)
Cet outil est utilisé pour la gestion des variables du pré-processeur (#define, #undef), et
pour la gestion des fichiers d ’en-tête et leurs fonctions (stdlib.h, fonction free…). Il créer un fichier "patron" (config.h.in) comprenant un ensemble de #define pour l'outils configure, à partir de acconfig.h et Configure.in. Voici un petit schéma pour mieux comprendre l'intégration de cet outil avec les autres :
L'outils Autoheader scanne le fichier Configure.in et recherche quels sont les symboles du pré-processeur C qu'il doit définir.
Voici les macros que l'on peut trouver dans le fichier Configure.in :
AM_CONFIG_HEADER(config.h)
Cette macro (nécessaire) spécifie le nom du fichier d'en-tête qui contiendra les définitions de macros du pré-processeur. Normalement, il s'agit de config.h. Ainsi, les fichiers sources comporteront : #include "config.h"
. Cette macro peut optionnellement définir le nom du fichier créé par Autoheader (en entrée de configure). Par défaut, il s'agit de config.h.in. Mais ce nom n'est pas "génial" pour le système de fichier DOS. Il peut être mieux de le renommer tout simplement config.in. Ce qui donnera la macro suivante :
AM_CONFIG_HEADER(config.h:config.in)
Cette macro sous entend l'utilisation d'Automake, si ce n'est pas le cas, on peut utiliser AC_CONFIG_HEADER(...)
.
AC_CHECK_HEADERS(unistd.h)
Permet de vérifier la présence ou non d'un (ou des) fichier(s) d'en-tête, listé(s) en argument (séparé par des espaces). Ainsi, dans le fichier config.h.in, on aura le code suivant :
/* Define as 1 if you have unistd.h. */
#define HAVE_UNISTD_H 0
Sur les systèmes qui ont 'unistd.h', le script configure changera le 0 en 1. Sur les autres, il laissera la ligne inchangée.
L'autre fichier utilisé est le fichier acconfig.h :
- Ce fichier est utilisé pour décrire les macros qui ne sont pas reconnues par l'outil Autoheader. Il s'agit généralement d'un fichier inintéressant, qui consiste en une collection de lignes de #undef.
Si vous générer un fichier d'en-tête portable (en utilisant la macro AM_CONFIG_HEADER
dans le fichier Configure.in), alors il faut écrire le fichier acconfig.h, qui contiendra les lignes suivantes :
/* Name of package */
#undef PACKAGE
/* Version of package */
#undef VERSION
L'outil Autoheader informe toujours par un message d'erreur lorsqu'il manque un élément dans le fichier acconfig.h.
5. Outil Configure
L'outil Configure est un script shell, qui va convertir les fichiers "moules" dans leur formes définitives (Makefile.in -> Makefile). Il effectue les tests souhaités avant la compilation et remplace les paramètres de configuration par leurs valeurs appropriées. Ce script est écrit de la manière la plus portable possible.
Ce script shell est fourni régulièrement avec le package pour l'utilisateur final. Il est créé par le développeur en lançant l'outil Autoconf.
Voici le schéma représentant les fichiers qui interagissent avec Configure :
- config.status : la première étape pour construire un programme est de lancer le script configure. Ce script va créer le fichier config.status, qui est lui-même un script shell. La première fois que l'on utilise configure, il lancerera automatiquement le script config.status. Ce script, relancé par la suite, va recréer les fichiers listés. En fait, il décrit quelles options de configuration étaient spécifiées lors de la dernière configuration du package.
- un ou plusieurs Makefile : un dans chaque sous-répertoires du projet. C'est le fichier que make va lire pour construire le programme, en compilant tous les fichiers sources et mettant à jour les binaires.
- config.h : ce fichier décrit les variables du pré-processeur C, sur lesquelles le code C s'appuiera pour adapter son comportement en fonction du système. Il contient les directives
#define
. Ce fichier est optionnel, créé si l'on gère un fichier d'en-tête.
- config.cache : ce fichier est utilisé par le script configure pour mettre en cache les résultats entre les différentes utilisations.
- config.log : il contient tous les messages produits par le compilateur, pour l'aide au débuggage si configure rencontre un problème.
Il est possible de choisir le répertoire d'installation du programme. Pour cela, il faut utiliser l'option --prefix
lors de l'utilisation de configure. Par défaut, ce répertoire est /usr/local
.
6. Tableau récapitulatif
Voici un tableau qui synthétise les différents outils à utiliser dans le développement d'un package :
Quand |
Commande |
Actions |
Au début du projet |
autoscan |
Génère un fichier moule du fichier Configure.in |
"" |
|
Ecrire un fichier Makefile.am (structure du programme) |
"" |
aclocal |
Pour installer les outils complémentaires à automake |
"" |
autoheader |
Pour déterminer les variables du pré-processeur à définir, et les sauver dans le fichier config.h.in |
Au début, ou si configure.in a été modifié |
autoconf |
Génère configure à partir de Configure.in |
Au début, ou si l'on a perdu les makefile.in |
automake |
Génère les fichiers Makefile.in à partir des Makefile.am |
Pour changer de configuration |
configure |
Génère les fichiers Makefile et le fichier config.h en fonction des options de compilation choisies |
Pour compiler les sources |
make |
Compile les sources ou met à jour les binaires |
7. FAQ & problèmes courants
Voici une lsite non exhaustive des problèmes que l'on peut rencontrer en utilisant ces outils. Cette liste est composée de questions récupérées au fil de mes visites sur le web...
- Autoconf me dis quelque chose à propos de macros indéfinies :
Cela signifie qu'il y a des macros dans le fichier configure.in, qui ne sont pas définies par Autoconf. Vous utilisez une vieille version d'Autoconf; essayer d'en installer une nouvelle version.
- Mon Makefile ne contient aucun caractères :
Cela peut signifier que vous avez essayer d'utiliser une substitution autoconf dans le Makefile.in sans avoir ajouter un appel approprié à AC_SUBST au scrip configure. Ou cela peut tout simplement signifier que vous devez reconstruire le Makefile. Pour le reconstruire depuis le Makefile.in, lancer le script shell config.status sans arguments. Si vous devez forcer configure à être relancé, lancez d'abord config.status --recheck.
- Message du type No rule to make target... needed by .deps/.P :
Les dépendances des fichiers sont stockées dans un répertoire appelé .deps. Si un fichier disparaît brutalement, il se peut qu'il soit encore référencé lors du make, ce qui conduit à ce message. Le plus simple est d'effacer le répertoire .deps.
- Impossible de refaire make :
Lorsque une erreur a été commise dans un Makefile.am, les mécanismes automatiques qui permettent de régénérer les Makefile peuvent ne plus fonctionner. Il faut alors les recréer soi-même grâce à Automake et Autoconf, comme expliqué dans la section \ref{sec:base}.
- configure: error: source directory already configured :
Il est possible de compiler des sources dans plusieurs répertoires, comme nous l'avons vu dans le premier exemple, page \pageref{sec:base}. Mais ceci n'est vrai qu'à condition de ne pas avoir compilé dans le répertoire de sources. En effet, lorsque l'on configure le répertoire de sources pour y effectuer une compilation, on créé un certain nombre de fichiers qui peuvent interférer avec ceux des autres répertoires de compilation, et engendrer des problèmes difficiles à détecter. Dans sa grande bonté, Autoconf empêche ce genre de situation.
- Problèmes de syntaxe dans le fichier configure.in :
La syntaxe des macros utilisées par Autoconf impose que les parenthèses délimitant les paramètres d'une fonction soient accolées au nom de la fonction. Donc :
AC_DEFINE(CFLAGS) juste
AC_DEFINE (CFLAGS) faux
8. Bibliographie
Voici les références sur lesquelles je me suis appuyé pour la réalisation de ce site :
Site web :
Livres :
- Managing Projects with make, by Andrew Oram & Steve Talbott (O'Reilly)
- Un livre sur le compilateur Make.
- Programming with GNU Software, by Mike Loukides & Andy Oram (O'Reilly)
- Un autre livre, sur l'ensemble des outils GNU.
Breugnot Yannick © 2000