Guide de démarrage
Pré-requis

Nous utiliserons oug pour lancer les opérations en ligne de commande. On suppose donc que Oug est installé et que oug est dans un répertoire de la variable d'environnement PATH.

Le code à analyser doit être compilé, car Oug refait certaines analyses du compilateur OCaml (jusq'au typage) et a donc besoin des interfaces compilées des modules utilisés.

Introduction

Oug analyse les fichiers sources OCaml donnés et construit un graphe "à trous" pour chacun. Ensuite, ces graphes sont rassemblés dans un graphe global. Cela permet de ne réanalyser que les fichiers qui n'ont pas changé depuis la dernière analyse. Il n'est plus nécessaire de passer les fichiers dans leur ordre de dépendance.

Par ailleurs, il faut également indiquer à Oug les mêmes options nécessaires à la compilation des fichiers sources, notamment les options -I et -pp (voir cette section).

On peut indiquer à l'outil les fichiers d'interface (.mli), ce qui créera des arcs de type export dans le graphe, indiquant explicitement que les éléments des interfaces sont utiles.

Plutôt qu'analyser les fichiers sources à chaque fois que l'on veut faire une recherche dans le graphe global, il est préférable (car plus rapide) de créer un dump du graphe une fois construit et de recharger ce graphe pour faire les recherches voulues. C'est la méthode expliquée ci-dessous.

Création et stockage dump du graphe global

L'option --dump permet de stocker le graphe global ainsi que l'environnement d'analyse. Cela est utile pour effectuer des analyses incrémentales, par exemple lorsqu'il faut analyser des fichiers sources nécessitant des options -pp différentes. On procède alors de la façon suivante:

# oug --dump tmp.oug -pp command1 file1.ml
# oug --load tmp.oug --dump tmp.oug -pp command2 file2.ml
# ...

Le graphe obtenu dans le fichier tmp.oug par cette commande est par défaut réduit, c'est-à-dire qu'il ne contient plus les noeuds correspondant aux expressions, à part les identifiants. sont conservés. Pour ne pas faire cette réduction et garder tous les éléments, on utilisera l'option --no-reduce pour stocker avec la commande ci-dessous le graphe non réduit dans le fichier graph.oug:

# oug --no-reduce --dump graph.oug -I foo -I +bar file1.ml file2.ml ...

Bien sûr, toutes ces commandes peuvent être mises dans un Makefile, par exemple en faisant dépendre des fichiers sources le graphe stocké.

Recherche des éléments inutiles

L'analyse du graphe pour lister les éléments inutiles est lancée par l'option --useless de oug, en indiquant un fichier où stocker cette liste, sous forme textuelle:

# oug --load graph.oug --no-reduce --useless useless.txt

L'option --no-reduce indique de ne pas réduire le graphe chargé avant l'analyse. Cette analyse pouvant durer plusieurs minutes lorsqu'il y a plusieurs milliers d'éléments, on utilisera l'option --progress pour afficher la progression.

Un exemple de résultat est donné ici:

...
File "oug_data.ml", line 505, char 56:
in_mod_id [p]
File "oug_data.ml", line 583, char 25:
functor_env [v]
File "oug_data.ml", line 583, char 38:
functor_args [v]
File "oug_data.ml", line 808, char 4:
Oug_data.orig_mod_list [v]
File "oug_data.ml", line 880, char 24:
modname [p]
...

Le caractère entre crochets à côté de chaque nom d'élément est le type de l'élément en question: (v)aleur, (M)odule, (t)ype, (C)lasse, champ de type (type (f)ield), (m)éthode, variable d'(i)nstance, identifiant de filtre ((p)attern ident), (e)xpression.

Filtrage

Les filtres permettent de sélectionner des éléments du graphe, afin d'effectuer certaines recherches. Le langage de filtres et des exemples sont décrits dans la section filtres.

Il existe deux options de oug pour utiliser un filtre:

  • --filter <f>: applique le filtre f au graphe et affiche sur la sortie standard les éléments correspondants à ce filtre,
  • --keep <f>: applique le filtre f au graphe et ne conserve que ces éléments et les arcs entre ces éléments. Le nouveau graphe obtenu est utilisé dans les actions suivantes.

Il est alors possible d'enchaîner plusieurs actions (cf. la section actions) en utilisant ces options:

# oug --load graph.oug --filter "<Foo.*>" --keep "v:<*>" \
  --dump tmp.oug --filter "<Foo.a*>"

Cette commande effectue les actions suivantes, dans cet ordre:

  • chargement du graphe du fichier graph.oug,
  • affichage des éléments correspondant au filtre "<Foo.*>",
  • conservation seulement des éléments qui sont des valeurs,
  • stockage de ce nouveau graphe dans le fichier tmp.oug,
  • dans le nouveau graphe, affichage des éléments correspondant au filtre "<Foo.a*>".

Il est possible d'appliquer des filtres sur le graphe réduit ou sur le graphe non réduit.

Voici deux exemples de filtres utiles que l'on peut utiliser sur le graphe global. Le premier permet d'avoir la liste des constructeurs de type somme non utilisés pour créer une valeur:

oug --load graph.oug --filter "f:<*> & ! (<*> -create->)" 

Le second permet de lister les champs de records non lus:

oug --load graph.oug --filter "f:<*> & ! (<*> -use->)" 

Ces deux filtres donnent les résultats attendus sous deux hypothèses:

  • tous les constructeurs de type somme sont explictement filtrés dans le code (pour éviter que l'un d'eux apparaisse "non lu"),
  • on ne teste pas de valeur d'un type somme en appliquant une fonction de comparaison sur une valeur de ce type construite exprès pour ce test, comme dans if x = None then ....
Toplevel
A compléter...
Toplevel graphique
A compléter...
A suivre

Il est également possible d'utiliser Oug dans votre IDE favori.