SkayaWiki

L2.2-02

JeromePetazzoni :: DerniersChangements :: DerniersCommentaires? :: ParametresUtilisateur :: http://www.enix.org/ :: Vous êtes ec2-3-149-26-176.us-east-2.compute.amazonaws.com

Préliminaires : find & xargs


Avant d'attaquer les choses sérieuses, voici deux outils très pratiques : find et xargs. Le premier (comme son nom l'indique!) permet de trouver des fichiers d'après divers critères (nom, taille, date d'accès...) ; le second, un peu plus subtil, permet d'utiliser la sortie d'une commande comme arguments d'une autre commande.

find


La syntaxe générale est la suivante :
find [chemins...] [critères de recherche...]
Les chemins sont les répertoires dans lesquels find va effectuer sa recherche. Il peut y en avoir plusieurs (ils seront alors tous inspectés dans l'ordre), ou même aucun (à ce moment là, find cherche dans le répertoire courant - c'est-à-dire que find . et find sont équivalents).
Les critères sont des options, comme -name *.o (pour chercher tous les fichiers dont le nom se termine par .o), ou encore -size +1500k (pour chercher les fichiers dont la taille est supérieure à 1500 kilo-octets). S'il y a plusieurs critères, ils doivent être tous remplis, sauf s'ils sont séparés par -or.
La liste complète des options disponibles est décrite dans la manpage de find.
Lorsque find trouve un fichier qui remplit les critères, il affiche son chemin sur la ligne de commande (ainsi, taper find tout seul affiche tous les fichiers et sous-répértoires compris dans le répertoire courant).

Avec find, effectuer les tâches suivantes :
- trouver tous les fichiers .o dans votre compte
- trouver tous les fichiers modifiés depuis ce matin
- trouver tous les fichiers de plus de 1 méga-octet qui n'ont pas été modifiés depuis 1 mois
- trouver tous les fichiers contenant "td" (en majuscules ou minuscules) dans leur nom, ou situés dans un répertoire qui contient "td" (en majuscules ou en minuscules)

xargs


xargs permet de lancer un programme, en lui donnant pour argument la sortie d'un autre programme. Par exemple, la commande seq 17 affiche tous les nombres de 1 à 17. La commande touch toto "touche" le fichier toto (le crée s'il n'existe pas). Dans un répertoire temporaire, exécutez seq 17 | xargs touch - cela va exécuter touch 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17, et donc créer ces 17 fichiers.

xargs accepte divers arguments ; par exemple -n qui indique le nombre de paramètres à donner par exécution (regardez ce qui se passe lorsque vous lancez seq 17 | xargs -n3 echo par exemple, et pour d'autres valeurs du paramètre -n). -P permet de lancer plusieurs programmes en parallèle.

En combinant find et xargs, effectuer les tâches suivantes :
- afficher les fichiers .o situés dans votre compte, avec leurs permissions, leur taille... (utiliser ls -l pour avoir toutes ces informations)
- trouver tous les fichiers de plus de 1 méga-octet dans votre compte, et les compresser avec bzip2, sauf s'ils ont déjà été compressés (indice : par défaut, bzip2 change le nom du fichier lorsqu'il le compresse)
- créer un fichier .tar contenant tous les fichiers .h et .c de votre compte
- copier tous les fichiers .jpg de votre compte dans un répertoire extérieur - par exemple, /tmp/images, créé pour l'occasion (indice : regardez dans les options de la commande cp)

Attention, question piège !
- pour chaque fichier se terminant par un tilde dans votre compte, demander à l'utilisateur s'il souhaite l'effacer ou le garder (indice : consultez la manpage de la commande rm) et l'effacer s'il le demande

Création d'une bibliothèque, Makefile, compilation séparée


Le but de ce TD est de montrer comment créer une bibliothèque (une "lib" ; de l'anglais library ; évitez d'employer le français "librairie", c'est un peu hors-sujet!). Une bibliothèque est un ensemble de fonctions utiles (ou du moins, de fonctions qu'on espère être utiles!) dans le but de pouvoir les ré-utiliser d'un projet à l'autre.

Par exemple, on peut faire une bibliothèque d'outils mathématiques, avec des fonctions pour manipuler des polynômes ; ou des matrices ; etc.

Quelques exemples de bibliothèques "fameuses" :
- la libc, qui contient les fonctions "de base" comme printf, malloc, fopen... Et des centaines d'autres
- gtk, une bibliothèque permettant de construire des interfaces graphiques (fenêtres, boutons...), utilisée dans la plupart des programmes gnome
- opengl, qui permet le rendu de scènes en 2D et 3D, et qui est capable de collaborer avec une carte graphique pour accélérer le dessin (utilisée dans de nombreux jeux)
- etc.

Nous verrons d'abord la "compilation séparée" (qui permet de diviser un projet en plusieurs fichiers compilables séparément), puis la simplification de la compilation à l'aide d'un Makefile, et enfin nous créerons notre propre bibliothèque.

Compilation séparée


Télécharger les fichiers doxy et dico. Éditer le fichier dico.c, ajouter la documentation à chaque fois que figure *** dans le code. Enfin, modifier le fichier afin que la recherche de mots dans le dictionnaire se fasse sans tenir compte de la case (indice: strcasecmp).

Séparer le code du TD1 en plusieurs fichiers :
- classe.h (avec juste la définition de la struct classe_s)
- liste.c (avec les fonctions concernant les listes chaînées)
- liste.h (avec les types et les en-têtes concernant les listes chaînées)
- table.c (fonctions concernant les tables de hachage)
- table.h (avec les types et les en-têtes concernant les tables de hachage)
- dicoliste.c (le programme dico utilisant les listes)
- dicotable.c (le programme dico utilisant les tables de hachage)

Compiler, pour chaque fichier .c, le fichier .o correspondant en utilisant la commande gcc -c toto.c (cela produit le fichier toto.o).

Puis, compiler les programmes dico et dicoh en utilisant gcc -o nomduprogramme listedesfichiers.o...

Makefile


Voici un petit fichier Makefile très simple, permettant de compiler les programmes précédents :

CFLAGS="-Wall -g"
all: dico dicoh
dico: dico.o liste.o table.o
dicoh: dicoh.o liste.o table.o


Il s'appuie sur les "règles implicites" de make, qui décrivent comment produire un fichier .o à partir d'un fichier .c. Plus précisément, lorsque make doit produire le fichier N.o à partir de N.c, il utilise la commande :
$(CC) -c $(CPPFLAGS) $(CFLAGS) -o N.o N.c

Notez que ces règles implicites sont disponibles même avec un Makefile vide (voire sans Makefile du tout).

Définissez dans votre fichier profil une variable d'environnement CFLAGS, afin de pouvoir compiler des programmes simples (se résumant à un seul fichier .c) avec make toto (si le source est toto.c), de façon à avoir les options -Wall -g.

Dans le fichier liste.c, ajouter un champs int inutile au début de la structure liste_s. Compiler avec make
et regarder ce qui ce passe. En utilisant la commande makedepend comme vu en cours, modifier
le Makefile afin qu'il gère les dépendances entre les fichiers sources.

Bibliothèque dynamique


Il est possible de compiler plusieurs fichiers .o ensemble pour en faire une bibliothèque qui pourra être partagée entre plusieurs programmes. Nous allons créer des bibliothèques pour le module liste et le module table.

Pour créer une bibliothèque :
gcc -shared -o libNOM.so FICHIERS...
- NOM est le nom qu'on veut donner à la bibliothèque (n'oubliez pas de mettre lib devant!)
- .so est l'extension des bibliothèques dynamiques (so veut dire "shared object")
- FICHIERS est la liste des fichiers .o que l'on veut inclure dans la bibliothèque

Pour lier une bibliothèque à un programme :
gcc -LCHEMIN1 -LCHEMIN2... -lNOM1 -lNOM2... FICHIERS...
- CHEMIN1, CHEMIN2... Sont des répertoires dans lesquels se trouvent les bibliothèques que l'on veut utiliser - les noms des bibliothèques doivent être indiqués sans leur préfixe "lib" ; ainsi, si on écrit -ltoto, l'éditeur de lien va chercher la bibliothèque dans un fichier nommé libtoto.so
- FICHIERS... indique l'ensemble des fichiers .o composant le programme (inutile de remettre dedans les bibliothèques : ce sont les options -L et -l qui s'en occupent!)

Pour exécuter un programme qui utilise des bibliothèques dynamiques :
export LD_LIBRARY_PATH=CHEMIN1:CHEMIN2:...
- les chemins indiqués sont ceux dans lesquels se trouvent les bibliothèques qu'on veut utiliser (séparés par des symboles "deux points", tout comme le PATH classique)

Comparez la taille des programmes dico et dicoh selon qu'ils sont compilés avec ou sans l'utilisation de bibliothèques dynamiques.

Notez aussi que l'ordre des options -l est important ...

Bibliothèque statique


Essayer de compiler un programme tout simple (par exemple int main() { return puts("Hello world!"); }) avec l'option -static. Utiliser les commandes file et ldd sur cet exécutable (compilé en -static, puis en mode normal). Comparer.

On souhaite maintenant produire une bibliothèque statique. La procédure ressemble beaucoup à celle utilisée pour les bibliothèques dynamiques, mais au lieu de gcc -shared il faut utiliser :

ar ruv libNOM.a FICHIERS...

Si un fichier est modifié, relancer ar ruv libNOM.a FICHIERS... (on peut mentionner tous les fichiers ou bien uniquement ceux qui ont été modifiés : ar est malin, et ne remplacera que les .o qui auront effectivement été modifiés).

Lorsqu'on compile en utilisant une bibliothèque statique, il faut utiliser -Lrépertoire et -lnom comme pour l'utilisation des bibliothèques dynamiques ; par contre il n'est pas nécessaire de positionner la variable LD_LIBRARY_PATH.

Comparer les différentes tailles (programme complètement statique, programme avec une bibliothèque statique, programme avec une bibliothèque dynamique).


TD suivant
Il n'y a pas de commentaire sur cette page. [Afficher commentaires/formulaire]