Cours CMP1 du jour

This commit is contained in:
Némunaire 2012-01-30 17:56:24 +01:00
parent 96e4f76a9c
commit 57289c0786

185
cmp/20120130.tex Normal file
View File

@ -0,0 +1,185 @@
\chapter{Development Tools}
\section{AutoTools}
On va écrire une description du makefile que l'on veut obtenir.
\subsection{AutoMake}
On crée la première règle bin_PROGRAMS, puis le/les noms des programmes que
l'on veut générer. Il s'agit d'une variable primaire.
hello-world sera installé dans bin/ avec make install. On peut changer le
prefix pour envoyer le fichier ailleurs.
Automake n'est cependant pas capable de compiler le programme, il a besoin
d'autoconf.
\subsection{AutoConf}
Le script configure se charge de regarder où sont les bibliothèques standard
ainsi que le compilateur et tout et tout.
On a la flemme d'écrire le script pour autotools ... donc : \texttt{autoscan} !
Première chose à faire : renommer le fichier en configure.ac
Il crée un fichier configure.scan. C'est un script shell mélangé avec du M4 (le
\og language d'AutoConf\fg).
\c Ca fonctionne sur le même principe que cpp, le préprocesseur.
M4 = Macro = M + 4 lettre
Les crochets bloquent l'extension des macros. Conseil : toujours mettre des
crochets autour des variables.
On retrouve des infos pour autoconf et automake.
AC_PREREQ vérifier la version requise.
AC_INIT : initialisation du package (nom, version, adresse de bug report)
AC_PROG_CXX : macro qui cherche un compilateur C++, on peut préciser le
compilateur obligatoire à utiliser (on lui passe en argument de
\texttt{./configure CXX=g++}) et il vérifie que le compilateur fonctionne (il
compile un petit code pour voir :p)
Si le compilateur fonctionne pas par exemple, il dira ce qui va pas, plus de
détails sont dispo dans le fichier config.log (énormément !)
AC_CONFIG_FILES : fichiers à générer, typiquement des Makefiles !
Il prend des fichiers en .in et il génére des fichiers dont le nom est écrit
dans la variable : Makefile.in => Makefile ; c'est donc le script configure qui
transforme le .in en véritable fichier.
C'est à ce moment là qu'il précise les variables genre CXX, ...
AC_OUTPUT déclenche la génération de tout ce qu'on a prévu jusque là.
Pour le moment, il nous manque donc les .in ; c'est automake qui va les générer
à partir des .am :)
Et puis, on va appeler autoconf pour générer le configure
Pour dire à autoconf qu'on veut utiliser automake, on va ajouter une macro :
AM_INIT_AUTOMAKE()
On va ajouter deux arguments : foreign pour dire qu'on veut pas les contraintes
d'un projet GNU et 1.11 pour la version minimale d'automake
Bon en fait on va utiliser \texttt{aclocal} :p
C'est pour préparer autoconf : pour récupérer les macros que l'on va utiliser
dans les fichiers.
Le but de M4 est de faciliter la maintenance, c'est plein de bouts de script
shell qui sont concaténé.
Allé hop, \texttt{automake} !
Hmmm ... il a besoin de certain script
\begin{itemize}
\item \textbf{depcomp~:} comment le compilateur gère les dépendances
(makedepend outdated : il regarde les fichiers dans tous les répertoires et
calcul les dépendances pour chaque fichier et il génère un bout de makefile
qui est à inclure. Mais c'est chiant, c'est pas automatisé, ...)~;\\
La première fois qu'on compile, le compilateur se balade et détecte les
dépendances entre les .h et les .c (avec des options louches -MT -MD) il
inscrit les dépendances dans un fichier et c'est automatisé ! depcomp teste
donc le compilateur pour déterminer les options à utiliser.
\end{itemize}
Pour avoir les scripts manquant on fait : \texttt{automake -ac}
Youpla, on lance \texttt{autoconf}. Il dit rien, mais il bosse dur !
C'est tout pour la partie mainteneur du paquet.
\subsection{Let's play !}
\texttt{./configure}
Il vérifie tout un tas de truc useless : faut lire il parle beaucoup trop vite.
Il prépare le mécanisme de dépendance et à la fin, il crée le Makefile.
Le Makefile est composé de régles classiques et d'une multitude de variables.
\texttt{make}
Bon ba voilà, ça compile donc ça marche !
Il y a plein de trucs sur la ligne de compilation : plein de \texttt{-D} qui
définissent des constantes (du style~: \texttt{HAVE_STRNCMP} qui dit si strncmp
a un comportement correct, quand c'est mélangé avec autoconf, ça s'utilise
comme une constante de préprocesseur).
Le problème de l'approche c'est qu'elle est limité : on a moins d'une dizaine
d'options. Dans un grand projet, le compilo ou le shell peuvent dire que la
ligne est trop longue.
Pour ça, on peut demander à autoconf de générer un fichier config.h
\section{Mooooaaaaarrree}
Tips Doxygen \a dit que c'est un attribut ce qui suit.
\subsection{Ajouter une bibliothèque}
Nouvelle variable primaire : LIBRARIES, préfixée par le nom du répertoire où se
sera installé.
Idem, on prend le nom de la lib à générer (libgreet.a) qui devient le
préfixe. Puis on ajoute les SOURCES...
Si on fait les choses bien, \texttt{make} devrait tout régénérer si on modifie
comme ça !
Arg, il a pas trouvé RANLIB pour faire des lib. M'enfin, il dit qu'il faut le
rajouter...
Tips \texttt{nm} : on peut utiliser c++filt pour retirer le mangling :
\texttt{nm libgreet.a | c++filt}
\subsection{Utiliser la bibliothèque}
Cette fois, on a une dépendance. Il ne faudra donc pas oublié de dire qu'on a
besoin de la libgreet !
On utilise pour ça le suffixe \texttt{LDADD}, on indique ensuite le nom de la
lib à utiliser.
\section{Suite de tests}
\texttt{TESTS} : appel un ou plusieurs programmes
Dans les machins, si on remplace le préfixe \texttt{bin} par \texttt{check}, le
programme ainsi listé ne sera compilé que si on lance un \texttt{make check}.
\subsection{make distcheck}
Tarball via dist + detar ailleurs + check
"Parallel build" : on peut se placer dans un dossier build par exemple et
appeler ../configure. Il va alors tout compiler dans ce dossier.
(genre, on se place dans le goinfre local pour éviter de compiler sur l'AFS)
Moment historique, faut verser une petite larme :( Le bocal avait l'air
compétent ... Lulz le boulot perdu car sauvé dans le goinfre effacé à 3h42 :p
Tips pour débugger : \texttt{../configure CXXFLAGS="-O0 -g"} à faire dans un
répertoire \texttt{build_debug}, avoir un autre répertoire \texttt{build_fast}
avec \texttt{-O3 -DNDEBUG}, \ldots un build par architecture, \ldots
\paragraph{C'est parti~!}
Il trouve pas un fichier : hop on l'ajoute dans le Makefile.am :
\texttt{EXTRA_DIST}.
Maintenant, il ne trouve pas un fichier qui a une adresse relative ! Vu que
distcheck est dans un répertoire \texttt{build/}.
Il faut changer le script~: le générer (il sera donc généré dans le builddir).
On crée donc \texttt{test-cat.in}~:
On ajoute la variable \texttt{@srcdir@} à l'endroit où l'on veut que se soit
remplacé.
Dans le \texttt{configure.ac}, on ajoute un fichier à générer aux côtés du
Makefile. Arf, mais il est pas exécutable dans ce cas. Donc, on lui dit que
c'est exécutable en ajoute un second argument qui est une commande qui est
exécuté après~: \texttt{[chmod +x mon-test]}