Maintenant que le logiciel est correctement configuré, il ne reste plus qu'à le compiler. C'est une étape qui est généralement très simple à effectuer, et qui ne pose généralement pas de problèmes majeurs.
L'outil préféré de la communauté du logiciel libre pour compiler des sources est make. L'intérêt de make est double :
il permet au développeur de gagner du temps, car il présente des avantages permettant de gérer la compilation de son projet de manière efficace,
il permet à l'utilisateur final de compiler et d'installer le logiciel en quelques lignes de commande, et ceci sans connaissance préalable du développement.
Les actions à exécuter pour arriver à une version compilée des sources sont stockées dans un fichier nommé habituellement Makefile ou GNUMakefile. En fait, lorsque make est invoqué il lit ce fichier s'il existe dans le répertoire courant. Si ce n'est pas le cas, il est possible de spécifier ce fichier en passant l'option -f à make.
make fonctionne selon un système de dépendances. C'est à dire que pour qu'un binaire soit compilé (cible), un certain nombre d'étapes doivent être accomplies (dépendances). Par exemple, pour créer le binaire glloq, on a besoin de compiler les fichiers objets (fichiers intermédiaires de la compilation) main.o et init.o, puis de les lier. Ces fichiers objets sont eux aussi des cibles, dont les dépendances sont les fichiers sources.
Ceci n'est qu'une introduction minimale pour survivre dans le monde impitoyable de make. Si vous voulez en savoir plus, je vous conseille de vous rendre sur le site d'APRIL à l'url http://www.april.org/groupes/doc/ pour une documentation à peine plus détaillée sur make. Pour une documentation exhaustive, voir Managing Projects with Make, seconde édition, chez O'Reilly, d'Andrew Oram et Steve Talbott.
Généralement, l'utilisation de make obéit à plusieurs conventions. Par exemple :
make sans argument exécute la compilation seule du programme, sans installation
make install compile le programme (mais pas toujours), et assure l'installation des fichiers nécessaires au bon endroit sur le système de fichiers. Certains fichiers ne sont pas toujours installés correctement (man, info), il faut alors les copier à la main. Dans certains cas, il faut effectuer une nouvelle fois un make install dans des sous-répertoires. Généralement il s'agit de modules développés par une tierce personne).
make clean efface tous les fichiers temporaires créés par la compilation, et y compris le fichier exécutable dans la majorité des cas.
La première étape est de compiler le programme, et donc de faire (exemple fictif) :
$ make gcc -c glloq.c -o glloq.o gcc -c init.c -o init.o gcc -c main.c -o main.o gcc -lgtk -lgdk -lglib -lXext -lX11 -lm glloq.o init.o main.o -o glloq
Parfait, le binaire est compilé correctement. Nous sommes prêts à passer à l'étape suivante, qui est l'installation des fichiers de la distribution (binaire, fichiers de données, etc...). Voir la section Installation.
Si vous avez la curiosité de regarder ce qu'il y a dans le fichier Makefile, vous y trouverez des commandes connues (rm, mv, cp, ...), mais aussi des chaînes de caractères étranges, de la forme $(CFLAGS).
Il s'agit de variables, c'est à dire de chaînes qui sont fixées généralement au début du Makefile, et qui seront ensuite remplacées par la valeur qui leur a été associée. C'est assez utile pour utiliser plusieurs fois de suite les mêmes options de compilation.
Par exemple, pour afficher la chaîne "toto" à l'écran en faisant un "make all":
TEST = toto all: echo $(TEST)
La plupart du temps, les variables suivantes sont définies :
CC : il s'agit du compilateur que l'on va utiliser. Généralement il s'agit de gcc, mais sur la plupart des systèmes libres, le compilateur par défaut utilisé par make (soit cc) est un synonyme de gcc. Dans le doute, n'hésitez pas à mettre ici gcc.
LD : il s'agit du programme utilisé parfois pour assurer la phase finale de la compilation (voir la section Les quatre phases de la compilation"). Par défaut, la valeur est ld.
CFLAGS : ce sont les arguments supplémentaires qu'on passera au compilateur lors des premières phases de la compilation. Parmi ceux-ci :
-Ichemin : spécifie au compilateur où chercher des fichiers d'en-tête supplémentaires (ex: -I/usr/X11R6/include permet d'inclure les fichiers d'en-tête se situant dans /usr/X11R6/include)
-Dsymbole : définit un symbole supplémentaire, utile dans certains programmes qui se compilent différemment selon les symboles définis (ex: utilise le fichier string.h si HAVE_STRING_H est défini)
On trouve souvent des lignes de compilation de la forme :
$(CC) $(CFLAGS) -c toto.c -o toto.o
LDFLAGS (ou LFLAGS): ce sont les arguments passés lors de la dernière phase de la compilation. Parmi ceux ci :
-Lchemin : spécifie un chemin supplémentaire où chercher des bibliothèques (ex: -L/usr/X11R6/lib)
-lbibliothèque : spécifie une bibliothèque supplémentaire à utiliser lors de la dernière phase de compilation
Pas de panique, ça arrive à tout le monde. Parmi les causes les plus communes :
glloq.c:16: decl.h: No such file or directory Le compilateur n'a pas réussi à trouver le fichier d'en-tête correspondant. Et pourtant, la configuration du logiciel aurait dû anticiper cette erreur. Comment résoudre ce problème :
vérifiez que l'en-tête existe vraiment sur le disque dans un des répertoires parmi /usr/include, /usr/local/include, /usr/X11R6/include ou un sous-répertoire. Si ce n'est pas le cas, recherchez le sur tout le disque (find ou locate), et si vous ne le trouvez toujours pas, alors vérifiez à deux fois que vous avez installé la librairie correspondant à cet en-tête. Vous trouverez des exemples des commandes find et locate dans leurs pages man respectives.
vérifiez que l'en-tête est bien accessible en lecture (faites un more chemin/fichier.h pour le tester)
s'il se trouve dans un répertoire comme /usr/local/include ou /usr/X11R6/include, il est parfois nécessaire de passer un argument supplémentaire au compilateur. Ouvrez le fichier Makefile correspondant (attention à ouvrir le bon, celui qui se trouve dans le répertoire où la compilation échoue[1]) avec votre éditeur de textes favori (Emacs, vi, ...). Recherchez la ligne fautive, et rajoutez la chaîne de caractères "-I/chemin"(où chemin est le chemin où se trouve l'en-tête en question juste après l'appel du compilateur (gcc, ou parfois $(CC)). Si vous ne savez pas où rajouter cette option, rajoutez-la au début du fichier, à la fin de la ligne "CFLAGS = quelquechose" ou de la ligne "CC = quelquechose"
relancez make, et si ça ne marche toujours pas, vérifiez que cette option (cf point précédent) est bien rajoutée à la compilation sur la ligne fautive
si ça ne marche toujours pas, demandez à votre gourou local ou faites appel à la communauté du logiciel libre pour résoudre votre problème (voir la section Support technique)
glloq.c:28: `struct toto' undeclared (first use this function) Les structures sont des types de données spéciaux, que tous les programmes utilisent. Beaucoup sont définies par le système dans les fichiers d'en-tête. Ce qui signifie que le problème vient certainement d'un en-tête manquant ou mal utilisé. La marche à suivre pour résoudre le problème est :
de tenter de véfifier si la structure en question est une structure définie dans le programme ou par le système. Une solution est d'utiliser la commande grep afin de vérifier si la structure est définie dans un des fichiers d'en-tête.
Par exemple, après vous etre rendu dans la racine de la distribution :
$ find . -name '*.h'| xargs grep 'struct toto' | more
Il est possible que plusieurs dizaines de lignes apparaissent à l'écran (à chaque fois qu'une fonction utilisant ce type de structure est définie par exemple). Si elle existe, repérez la ligne où la structure est définie en regardant le fichier en-tête obtenu par l'utilisation de grep.
La définition d'une structure est :
struct toto { >contenu de la structure< };
Vérifiez si cela correspond avec ce que vous avez. Le cas échéant, c'est que ce fichier d'en-tête n'est pas inclus dans le fichier .c fautif. Deux solutions s'offrent à vous :
rajoutez la ligne #include "nomdufichier.h" au début du fichier .c fautif
ou copiez-collez la définition de la structure au début de ce fichier (ce qui n'est pas très propre, mais ça a le mérite de marcher généralement)
si ce n'est pas le cas, faites la même chose sur les fichiers d'en-tête du système (qui se trouvent sur /usr/include, /usr/X11R6/include, ou /usr/local/include généralement. Mais cette fois ci, utilisez la ligne #include <nomdufichier.h>
si cette structure n'existe toujours pas, essayez de trouver dans quelle bibliothèque (au sens ensemble de fonctions regroupées dans un seul package) elle devrait être définie (regardez dans le fichier INSTALL ou README quelles sont les bibliothèques utilisées par le programme et leur version nécessaire). Si la version dont le programme besoin n'est pas celle installée sur votre système, alors effectuez une mise à jour de cette bibliothèque.
si ça ne marche toujours pas, vérifiez que le programme fonctionne bien correctement sur votre architecture (certains programmes n'ont pas encore été portés sur tous les Unix). Vérifiez aussi que vous avez bien configuré le programme (au moment du configure par exemple) pour votre architecture.
parse error C'est un problème assez compliqué à résoudre, car généralement il s'agit d'une erreur que le compilateur rencontre plus haut, mais qui ne se manifeste qu'à une certaine ligne. Parfois, il s'agit simplement d'un type de donnée qui n'est pas défini. Si vous rencontrez un message d'erreur de type :
main.c:1: parse error before `glloq_t main.c:1: warning: data definition has no type or storage class
alors, le problème est que le type glloq_t n'est pas défini. La solution pour résoudre ce problème est à peu près la même que pour le problème précédent.
(Remarque: il peut y avoir un parse error dans les vieilles librairies curses si ma mémoire est bonne).
no space left on device Le problème est assez simple à régler : la place sur le disque est insuffisante pour générer un binaire à partir du fichier source. La solution consiste à libérer de la place dans la partition abritant le répertoire d'installation (supprimez les fichiers temporaires ou les sources, désinstallez les programmes dont vous ne vous servez pas). Si vous l'avez décompacté dans /tmp, faites-le plutôt dans /usr/local/src ce qui évite de saturer inutilement la partition /tmp. Vérifiez de plus que vous n'avez pas de fichiers core sur le disque. Si oui, effacez les ou faites les effacer s'ils appartiennent à un autre utilisateur.
/usr/bin/ld: cannot open -lglloq: No such file or directory
Clairement, le programme ld (utilisé par gcc lors de la dernière phase de la compilation) n'a pas réussi à trouver une bibliothèque. Il faut savoir que pour inclure une bibliothèque, ld va chercher un fichier dont le est passé par l'argument -lbibliothèque. Ce fichier est libbibliothèque.so. Si ld n'arrive pas à le trouver, alors il produit ce message d'erreur. Pour résoudre ce problème, procédons par étapes :
Vérifions que ce fichier existe bien sur le disque dur, en utilisant la commande locate. Généralement, les bibliothèques graphiques se trouvent dans /usr/X11R6/lib. Par exemple :
$ locate libglloqSi cela ne donne rien, vous pouvez faire une recherche avec find (ex: "find /usr -name libglloq.so*"). Si vous ne trouvez pas la bibliothèque, alors il vous reste à l'installer.
Une fois la bibliothèque localisée, vérifions que cette bibliothèque est bien accessible pour ld : le fichier /etc/ld.conf spécifie où trouver ces librairies. Rajoutez le répertoire incriminé à la fin (il est possible que vous ayez à rebooter la machine pour que cela soit pris en compte). Il est aussi possible de rajouter ce répertoire en modifiant le contenu de la variable d'environnement LD_LIBRARY_PATH. Par exemple, en imaginant que le répertoire à ajouter est /usr/X11R6/lib :
$ export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/X11R6/lib
Si celà ne fontionne toujours pas, vérifiez que la bibliothèque incriminée est bien au format ELF (avec la commande file). Si c'est un lien symbolique, vérifiez que ce lien est correct et ne pointe pas vers un fichier inexistant (par exemple, avec un nm libglloq.so). Les permissions peuvent de plus être incorrectes (si vous utilisez un compte autre que root et que la librairie est protégée en lecture par exemple).
glloq.c(.text+0x34): undefined reference to `glloq_init' Aïe ! Aïe ! Aïe ! Pourquoi cette noirceur ? Il s'agit d'un symbole non résolu lors de la dernière phase de la compilation. Généralement, il s'agit d'un problème de bibliothèque. A priori, plusieurs causes possibles :
la première chose à faire est de savoir si le symbole est censé être présent dans une bibliothèque. Par exemple, s'il s'agit d'un symbole commençant par gtk, il appartient très certainement à la bibliothèque gtk. Si le nom de la bibliothèque est difficilement identifiable (zorglub_gloubiboulga), il est possible de lister les symboles d'une bibliothèque avec la commande nm. Par exemple,
$ nm libglloq.so 0000000000109df0 d glloq_message_func 000000000010a984 b glloq_msg 0000000000008a58 t glloq_nearest_pow 0000000000109dd8 d glloq_free_list 0000000000109cf8 d glloq_mem_chunk
Rajouter l'option -o à nm permet de plus d'afficher le nom de la bibliothèque sur chaque ligne, ce qui simplifie les recherches. Imaginons que nous cherchions le symbole bulgroz_max, une solution de barbare est d'effectuer une recherche de ce genre :
$ nm /usr/lib/lib*.so | grep bulgroz_max $ nm /usr/X11R6/lib/lib*.so | grep bulgroz_max $ nm /usr/local/lib/lib*.so | grep bulgroz_max /usr/local/lib/libzorglub.so:000000000004d848 T bulgroz_max
Formidable ! Le symbole bulgroz_max est défini dans la bibliothèque zorglub (la lettre majuscule T se trouve devant son nom). Il suffit de rajouter la chaîne -lzorglub dans la ligne de compilation en éditant le fichier Makefile : rajoutez-la à la fin de la ligne où LDFLAGS ou LFGLAGS (ou au pire CC) sont définis, ou alors sur la ligne responsable de la création du fichier binaire final
la compilation se fait avec une version de la librairie qui n'est pas la même que celle prévue pour le logiciel. Lisez le fichier README ou INSTALL de la distribution pour savoir pour quelle version de la librairie doit être utilisée
tous les fichiers objets de la distribution ne sont pas correctement liés. Il manque le fichier dans lequel est définie cette fonction. Faites un "nm -o *.o" pour le savoir et rajoutez le fichier .o correspondant sur la ligne de compilation s'il est manquant.
la fonction ou variable incriminée est peut-être fantaisiste. Essayez de la supprimer : éditez le fichier source incriminé (son nom est spécifié au début du message d'erreur). C'est une solution désespérée, qui va avoir pour conséquence un fonctionnement très probablement anarchique du programme (segfault au démarrage, etc.)
Segmentation fault (core dumped) Parfois, le compilateur plante lamentablement, et produit ce message d'erreur. Je n'ai pas d'autre conseil que de vous demander d'installer une version plus récente de votre compilateur (il me semble que la version 2.8.x de gcc est particulièrement buggée)
plus de place sur /tmp La compilation, a besoin d'espace temporaire de travail lors de ses différentes étapes ; si elle ne l'a pas, elle échoue. Il faut donc faire du ménage, mais attention car certains fichiers risquent de planter des programmes qui s'exécutent (serveur X, pipes...) s'ils sont supprimés. Il faut donc bien savoir ce que l'on fait ! Si /tmp fait partie d'une partition qui ne contient pas que lui (par exemple la racine), recherchez et supprimez d'éventuels fichiers core.
make/configure en boucle
Il s'agit généralement d'un problème d'heure sur votre système. make a en effet besoin de connaître la date ainsi que celle des fichiers qu'il vérifie. Il compare les dates des fichiers et utilise le résultat pour savoir si la cible est plus récente que la dépendance.
Il se peut que des problèmes de date ammène make à se reconstruire sans fin (ou de construire et reconstruire un arborescence en boucle). Dans ce cas là, l'utilisation de la commande touch (qui a pour conséquence de mettre à l'heure courante les fichiers passés en argument) permet de résoudre le problème dans la plupart des cas.
Par exemple :
$ touch *
Ou encore plus barbare (mais efficace) :
$ find . | xargs touch
[1] | analysez le message d'erreur renvoyé par make. Normalement, les dernières lignes devraient contenir un répertoire (un message de la forme "make[1]: Leaving directory `/home/benj/Projet/Pouet'"). Repérez celle dont le numéro est le plus grand. Pour vérifier qu'il s'agit bien du bon, rendez vous dans ce répertoire, et exécutez make à nouveau pour obtenir la même erreur |