Everyone is welcome here (except, of course, those who have borrowed books from me for and have not returned them yet 😉)

Autotools

Posted on mai 17, 2022 in computer-science

Note: Ce document est une mise à jour de mon article comment utiliser les « autotools » pour créer et distribuer des packages .tar.gz « à la GNU » pubkié en 2001.

Prérequis

Si vous désirez exécuter les commandes décrites dans ce tutorial, il faut un système de compilation. Sous Ubuntu :

sudo apt install build-essential autoconf libtool

Créer des paquetages tar.gz avec les autotools

N’avez vous jamais eu envie de distribuer vos projets sous la forme d’un paquetage .tar.gz comme ceux du projet GNU ?

Le premier avantage est que l’installation est normalisée: en général, une simple commande

./configure && make && make install

suffit pour compiler et installer un paquetage (et make uninstall pour tout désinstaller).

Le deuxième avantage est que le script configure détecte les particularités du système sur lequel s’effectue l’installation. Cela permet d’écrire des programmes qui s’adaptent et compilent sur des systèmes très variés. Même si vous ne programmez pas en C et distribuez de simples scripts, en shell ou awk par exemple, la création d’un paquetage "à la GNU" permet une installation automatique et propre: configure détecte où se trouvent les programmes shell ou awk (dans /bin, /usr/bin ou /usr/local/bin, ...), et modifie la première ligne des scripts en conséquence. Il peut également installer les documentations (pages ‘man’ ou ‘info’) aux endroits appropriés.

Les paquetages GNU obéissent à des règles très précises et assez complexes. Il existe des outils qui aident à générer de tels paquetages : les principaux sont autoconf et automake. Toutefois, leur documentation est d’un abord quelque peu difficile. Cet article montre, sur un exemple simple, comment les utiliser pour créer des paquetages .tar.gz.

Notre projet est un simple programme en C, consistant en un unique fichier source nommé, au hasard, hello.c. En premier lieu, il faut créer un répertoire pour le projet (mkdir hello), puis, à l’intérieur de ce répertoire, un sous-répertoire src dans lequel sera plaçé le fichier hello.c:

mkdir -p hello/src
cd hello

cat > src/hello.c <<EOF
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif

#include <stdio.h>

int main()
{
    printf("%s %s\n", PACKAGE,VERSION);
    printf("Hello world!\n");
    printf("Size of int = %d bytes\n", SIZEOF_INT);
    #ifdef WORDS_BIGENDIAN
        printf("Big endian\n");
    #else
        printf("Small endian\n");
    #endif
}
EOF

Cette version de hello.c contient quelques lignes de plus que le programme classique. Ces lignes supplémentaires ont pour but d’illustrer quelques possibilités d’autoconfiguration. Le fichier inclus config.h sera généré par l’appel configure, il contiendra, entre autres, la définition de macros qui spécifient des caractéristiques de la machine où s’effectue l’installation; par exemple, WORDS BIGENDIAN spécifie l’ordre des octets dans les mots, et SIZEOF_INT spécifie la taille, en octets, occupé par les variables de type ‘int’.

Pour générer le projet, il faut maintenant créer quatre fichiers: Makefile.am, src/Makefile.am, acconfig.h et configure.ac (cf. Table 2).

Makefile.am indique les sous-répertoires à traiter. src/Makefile.am indique les binaires à produire et leurs sources. Finalement, le fichier le plus substantiel est configure.ac.

# Création des fichiers de configuration
# (à executer depuis le repertoire `hello`)

cat > Makefile.am <<EOF
SUBDIRS = src
EOF

cat > src/Makefile.am <<EOF
bin_PROGRAMS = hello
hello_SOURCES = hello.c
EOF

cat > configure.ac <<EOF
AC_INIT([hello], [1.0])
AC_CONFIG_SRCDIR([src/hello.c])
AM_INIT_AUTOMAKE
AC_PROG_CC
AC_CONFIG_HEADER(config.h)
AC_C_BIGENDIAN
AC_CHECK_SIZEOF(int)
AC_OUTPUT(Makefile src/Makefile)
EOF

Une fois ces fichiers créés, il faut générer différents fichiers de support, en exécutant les commandes suivantes (les caractères # introduisent des remarques; seules les commandes, situées à leur gauche, doivent être tapées).

aclocal     # crée aclocal.m4
autoheader  # crée config.h.in
touch README AUTHORS NEWS ChangeLog
automake -a # crée Makefile.in et src/Makefile.in
autoconf    # crée configure

Pour créer un paquetage respectant à la lettre les standards GNU, il est nécessaire de créer les fichiers NEWS, README, AUTHORS et ChangeLog dans le répertoire principal du projet. Les informations qui doivent apparaître dans ces fichiers sont précisées dans la documentation info GNU coding standards, mais les gens pressés pourront se conformer à cette exigence par un simple touch NEWS README AUTHORS ChangeLog.

Ne vous inquiétez pas d’éventuels messages d’avertissement. Par contre si une commande est inconnue, vérifiez que votre système contient bien les outils de base de développement GNU tels que le compilateur gcc, make, autoconf, automake, etc.

Nous pouvons maintenant effectuer une compilation et une installation:

./configure        # create Makefiles
make               # compile the package
sudo make install  # install the package in /usr/local

Il faut noter que, par défaut, les fichiers sont installés dans /usr/local, et donc que l’étape make install nécessite d’avoir les droits de super-utilisateur. Néanmoins, on peut installer les programmes à un autre endroit; par exemple, en exécutant:

configure --prefix=$HOME

les fichiers s’installeront alors dans des sous-répertoires bin, man, etc. du répertoire de l’utilisateur. C’est l’un des avantages importants de ces paquetages .tar.gz, par rapport aux .rpm ou .deb, que de pouvoir être installés par un utilisateur qui n’a pas les droits de superutilisateur.

Vous pouvez lire le fichier INSTALL qui détaille d’autres options d’installation.

Générer le paquetage

Pour générer le package hello-0.1.tar.gz, il ne reste alors plus qu’à taper:

 make dist # crée hello-0.1.tar.gz
 make distclean # nettoie le répertoire du projet

Essayez ensuite de décompacter le paquetage, de le compiler et de l’installer. Si vous avez bien suivi la recette, tout devrait fonctionner “automagiquement”. Quelques remarques méritent d’être mentionnées. Le fichier le plus complexe est configure.ac; cependant il existe une commande, autoscan, qui accompli une partie du travail en produisant un fichier configure.scan pouvant servir de point de départ pour l’écriture de ce fichier. Le numéro de version (ici 0.1) provient de la ligne AC_INIT dans configure.ac. Il est accessible dans le source par la macro VERSION. Une fois que vous avez exécuté ./configure et que le fichier Makefile existe dans votre répertoire, il n’est plus nécessaire d’entrer toute la série de commandes aclocal, ... à chaque fois que vous aurez modifié un fichier (par exemple configure.ac): une simple commande make suffira.

Installer de la documentation ou des scripts

Pour installer des pages de manuel, il faut ajouter dans Makefile.am une ligne commençant par man MANS = et suivie de la liste des fichiers au format nroff (p.ex. man MANS = hello.1). Nous conseillons de mettre tous ces fichiers dans un sous-répertoire man de la distribution, et d’ajouter ce répertoire dans la liste SUBDIRS du fichier Makefile.am principal.

Supposons maintenant que notre distribution contiennent des scripts écrit dans le language gawk : script1.awk et script2.awk. Nous voudrions que le chemin de gawk soit détecté automatiquement et que ces scripts soient installés, sous les noms script1 et script2. Pour cela, il faut modifier configure.ac et src/Makefile.am. Ajoutez une ligne ((AC PATH PROGS(GAWK, gawk) )) dans configure.ac; cela vérifiera la disponibilité de gawk sur le système, et fournira son chemin dans la variable $(GAWK). Le nouveau src/Makefile.am est listé dans la table 3. Cet exemple peut facilement être adapté à des scripts écrits dans des languages quelconques, tcl, perl ou python, par exemple.

### Fichier src/Makefile.am installant des scripts gawk
bin_SCRIPTS = script1 script2
CLEANFILES = $(bin_SCRIPTS)
EXTRA_DIST = script1.awk script2.awk
script1 : script1.awk
echo "#! " $(GAWK) > $@
cat $< >> $@
chmod ugo+x $@
script2 : script2.awk
echo "#! " $(GAWK) > $@
cat $< >> $@
chmod ugo+x $@

Installer une librairie

TODO

Voir * https://www.gnu.org/software/libtool/manual/html_node/Using-Automake.html#Using-Automake * https://www.gnu.org/software/automake/manual/html_node/Libtool-Concept.html

Voici Makefile.am de ma librarie (http://github/chrlr/expe_c/psychexp) consistant en deux fichiers sources: psychexp.h psychexp.c

lib_LTLIBRARIES=libpsychexp.la
libpsychexp_la_SOURCES=psychexp.h psychexp.c
libpsychexp_la_LIBADD=-lSDL2
include_HEADERS=psychexp.h

expliquer l'utilisation de libtoolize

Créer un paquetage .deb contenant le binaire

Reprenons l'exemple du projet hello. Les commandes

./configure
make dist

produisent le fichier hello-1.0.tar.gz.

Nous allons utiliser la commande alien pour convertir ce “tarball” en en package .deb pouvant être installé par dpkg

sudo apt install alien
alien -k hello-1.0.tar.gz`

Notez que cet outil ne permet que la création de paquetage binaire, et pas de paquetage source.

(Voir https://help.ubuntu.com/community/CheckInstall pour plus d'information)

Créer un paquetage rpm

(WARNING: cette partie date de 2001 et est très certainement obsolete. Je n'utilse plus de système basé sur rpm depuis 2005).

Certains utilisateurs préférent les paquetages rpm aux tar.gz. Il y en fait deux types de rpm, ceux qui contiennent les sources (src.rpm) et ceux qui ne contiennent que les exécutables. Les seconds sont effectivement faciles à installer puisqu’ils ne nécessitent pas de compilation; mais ils font des hypothèses sur la machine sur laquelle ils s’installent, et sont donc généralement spécifiques à une distribution. Créer des paquetages src.rpm et rpm à partir de hello-0.1.tar.gz n’est pas difficile. La procédure générique est détaillée dans des documents disponibles sur les sites http://www.rpm.org et . Essentiellement, il s’agit de créer un fichier texte, ayant pour extension .spec, qui décrit le paquetage. Pour ‘hello’, voici la marche à suivre:

  1. copier hello-4.1.tar.gz dans /usr/src/packages/SOURCES (ou /usr/src/redhat/SOURCES selon votre distribution)

  2. dans /usr/src/packages/SPECS, créer le fichier hello.spec. Ce fichier décrit le contenu du futur paquetage rpm.

#
# exemple de fichier ‘spec’ pour le projet ‘hello’
#
Vendor: Christophe Pallier
Name: hello
Release: 1
Copyright: GPL (cf http://www.fsf.org)
Group: unsorted
Provides: hello
Packager: christophe@pallier.org
Version: 0.1
Summary: The hello program
Source: hello-0.1.tar.gz
%description
A slightly adapted version of the hello program.
%prep
%setup
%build
./configure
make
%install
make install
%files
/usr/local/bin/hello
  1. faire rpm -ba hello.spec (en tant que root) La commande rpm -ba crée le fichier hello-0.1-1.rpm dans RPMS/i386 et hello0.1-1.src.rpm dans SRPMS. Si vous distribuez l’exécutable, un superutilisateur pourra effectuer les opérations suivantes:

    rpm -qip hello-0.1-1.rpm # liste le contenu du paquetage rpm -i hello-0.1-1.rpm # install rpm -qil hello # verifie le paquetage rpm -e ello # desinstalle

Conclusion

Vous voici maintenant parti du bon pied pour créer vos paquetages. Pour faire des choses plus complexes, vous devrez lire les documentations au format info: GNU coding standards, Autoconf, Automake. Le lecture des fichiers configure.ac des paquetages existants est également instructive.