France IOI
Développements Avancés en Caml sous Windows

Développements Avancés en OCaml
sous Windows avec Crimson Editor

- Arthur Charguéraud -

Ce document fait suite à "Développements Caml sous Windows". Il s'adresse à tous ceux qui programment régulièrement en Ocaml.

Table des matières :
  1. Capturer la sortie des programmes.
  2. Installation de Mingw.
  3. Compilation en code natif.
  4. Installation de MSys.
  5. Compiler et exécuter en un seul raccourci.
  6. Travailler avec des Makefile.

Certains passages du tutoriel sont spécifique à Windows XP, et devrait s'adapter sans problème à Windows 2000 ou Me. Pour Windows 98, voyez la remarque à la fin.

Capturer la sortie des programmes

Lorsqu'on écrit un programme qui ne demande pas d'entrée interactive, le plus simple est de mettre les données d'entrée dans un fichier input.txt, et d'utiliser le raccourci CTRL+3. Ce paragraphe décrit comment associer au raccourci CTRL+4 une commande qui permet que le résultat de l'exécution du programme s'affiche directement dans Crimson, au même endroit que là où s'affiche les messages du compilateurs.

Voici les paramètres à indiquer pour le raccourci CTRL+4

  • Menu Text : Execute sur input.txt avec capture
  • Command : output.exe
  • Argument : < input.txt
  • Initial Dir : $(FileDir)
  • Close on exit : décoché
  • Capture output : coché
  • Save before execute : coché

C'est très efficace, mais il faut faire attention aux programmes qui attendent des données. Prenons un petit exemple : on met dans le fichier input.txt un unique nombre 35. Et puis on écrit le programme suivant :

let x = read_int () in
let y = read_int () in
print_string "c'est fini";

Que va-t-il se passer lorsque le programme va essayer de lire le deuxième nombre sur l'entrée standard alors qu'il n'y a plus rien dans le fichier input.txt une fois que le 35 a été lu ? Eh bien il attend... jusqu'à ce que vous interrompiez le programme.

Il y a une solution apparement simple, mais qui ne fonctionne malheureusement qu'avec les programmes compilés en mode natif. La solution dans ce cas est simple : clickez avec le bouton droit dans la fenêtre où les messages s'affichent, puis clickez sur "Kill Process". Le programme est alors interrompu.

Pour des raisons compliquées, la fonctionnalité "Kill Process" ne fonctionne pas avec les programmes compilés avec ocamlc. Pour ceux là, il faut utiliser le gestionnaire des tâches de Windows. Appuyez simultanément sur les touches Alt, Ctrl, et Suppr. Vous obtenez une fenêtre avec une liste de programme. Trouvez celui qui s'appelle ocamlrun. Sélectionnez-le, et appuyez alors sur le bouton "Terminer le processus", et confirmez votre action.

Cette dernière solution est assez fastidieuse si on doit la faire souvent. Il y a moyen d'installer des petits outils pour associer un raccourci clavier à la commande "kill ocamlrun". Mais ce ne sera pas utile, car on propose une autre solution beaucoup plus propre utilisant les outils MSys un peu après.

Evidement, si on fait bien attention, ce genre ne problème ne devraient jamais se poser : il suffit de mettre tout ce qu'il faut dans le fichier input.txt avant d'exécuter le programme. Mais bon un accident est si vite arrivé...

Installation de Mingw

Mingw permet de compiler des programmes Ocaml en code natif, ce qui permet d'obtenir des programmes beaucoup plus efficaces.

Mais qu'est-ce que c'est que le code natif ? Eh bien lorsqu'on compile un programme avec ocamlc.exe, le résultat n'est pas la fabrication d'un véritable programme, mais plutôt d'une liste d'instructions, appelé bytecode. Lorsqu'on lance ce "faux" programme, un programme appelé interpreteur (ocamlrun.exe) va prendre la liste d'instructions et les exécuter une par une, en faisant exactement ce que disent de faire les instructions de cette liste. Compiler un programme en code natif, c'est générer un "vrai" programme, qui réalise directement les instructions qu'il souhaite faire. Il n'y a alors plus de bytecode.

Alors ça sert à quoi le bytecode ? C'est pratique parceque ça permet de compiler plus vite, et que le bytecode ne dépend pas de la machine sur lequel il est compilé, tandis qu'un programme en code natif dépend beaucoup de la machine sur laquelle on va l'utiliser. De plus, pour pouvoir compiler en code natif, il faut un compilateur assembleur et un linker C, et il faut donc installer un ensemble de logiciels en plus, appeler MinGW. C'est exactement ce qu'on va faire maintenant.

Pour cela on va sur la page www.mingw.org, on click sur "download" dans le menu, et on trouve dans le tableau avec tous les noms de fichiers celui qui est dans la section "Current" et qui s'appelle "MinGW", et qui a un nom du type "MinGW-4.1.0.exe". On télécharge ce fichier (voici un lien direct).

Et puis on l'installe; mais pas n'importe où. Si vous voulez évitez des millions d'ennuis, choisissez un chemin d'accès sans espaces dedans. NE PAS PRENDRE "c:\program files\mingw". Prennez plutôt un chemin du genre "c:\programs\mingw". Dans la suite, on supposera que vous avez pris ce dossier, mais vous pouvez facilement adapter.

L'installation est guidée, il faut choisir : "installation complète", et puis sur la page d'après, laissez tout sélectionné sauf : "gcc-g77", "gcc-ada", "gcc-java", "gcc-objc".

Pour que vous puissiez utiliser MinGW, il faut mettre son chemin d'accès dans le PATH.

Sous Windows XP, il faut aller dans :

  • Panneau de configuration,
  • Performances et maintenance,
  • Système,
  • (Onglet) Avancé,
  • (Bouton) Variables d'environnement,
  • Dans la moitié supérieur (ou inférieur si vous voulez que ça marche sur tous les comptes),
  • Sélectionnez la variable PATH,
  • Clickez sur le bouton "Modifier",
  • N'effacez surtout pas ce qui est déjà écrit,
  • Rajoutez au bout de la ligne de "Valeur de la variable" le texte : ";C:\programs\mingw\bin",
  • N'oubliez pas le point-virgule pour séparer de ce qui précède,
  • Validez le tout.

Compilation en code natif

On va créer un raccourci CTRL+5 pour réaliser la compilation en code natif, avec ocamlopt.exe. Voici les options à utiliser :

  • Menu Text : Compile
  • Command : C:\Program Files\Objective Caml\bin\ocamlopt.exe
  • Argument : -o output.exe $(FileName)
  • Initial Dir : $(FileDir)
  • Capture output : coché
  • Save before execute : coché

Le programme généré par ocamlopt s'appelle output.exe et s'exécute avec les mêmes raccourcis clavier que les programmes générés par ocamlc.

Installation de MSys

MSys est un ensemble de programme émulant ceux qu'on trouve dans une console linux de base. Pour ceux qui connaissent, il y a un "shell" et toutes ses commandes usuelles (cp, ls, mkdir, diff, ...), et le programme "make" permettant de faire des Makefile, ce qui nous intéresse particulièrement.

Lorsqu'on développe des programmes compliqués, les lignes de commandes de compilation sont compliquées, et pour éviter de les retaper à chaque fois, on écrit un petit "script" (un mini-programme), capable de calculer les lignes de compilations à lancer et de exécuter effectivement.

Pour télécharger MSys, on retourne sur la page www.mingw.org, on click sur "download" dans le menu, et on trouve dans le tableau avec tous les noms de fichiers celui qui est dans la section "Current" et qui s'appelle "MSys".

Ensuite on l'installe, toujours dans un dossier sans espace, que l'on supposera être C:\programs\msys\. A la fin de la phase d'installation, l'installer de MSys vous demande le chemin d'accès de MinGW. Il est important de fournir le bon si vous voulez que tout marche correctement, par exemple C:\programs\mingw.

Pour que vous puissiez utiliser MSys de manière pratique, il faut mettre son chemin d'accès dans le PATH. Faîtes exactement comme pour MinGW, en ajoutant à la variable PATH le contenu ;C:\programs\msys\bin (avec le point-virgule pour séparer de ce qui précède).

Pour tester que MSys fonctionne, ouvrez une fenêtre ligne de commande (menu démarrer, exécuter, tapez "cmd", validez), puis tapez la commande "ls" et validez. Normalement vous devez voir s'afficher la liste des fichiers contenus dans le dossier courant.

MSys vous créera également une icône sur le bureau, raccourci vers une fenêtre de ligne de commande "shell", (si vous n'avez pas l'icône, trouvez le raccourci c:\programs\msys\msys.bat). Dans cette fenêtre vérifiez que la commande "pwd" vous affiche le chemin courant (du genre /home/user).

Compiler et exécuter en un seul raccourci

Voyons maintenant l'intérêt d'avoir installé un "shell". Le shell comprend des commandes bien plus évoluées que la ligne de commande MS-DOS, et on va en tirer parti, avec la commande suivante :

ocamlc -o output.exe test.ml && ./output.exe < input.txt

Le symbol && au milieu veut dire qu'on essaie d'effectuer la commande à gauche (qui compile le fichier test.ml vers output.exe), et que si le compilateur indique que la compilation a réussi, on effectue la commande de droite (qui exécute le programme sur l'entrée input.txt). Si jamais il y a des erreurs de programmation, alors l'exécution n'est pas réalisée. A quoi ça sert ? A gagner du temps !

Associons cette ligne de commande à un raccourci clavier de Crimson Editor, en lui demandant d'appeler le shell en lui donnant en paramètre une commande entre guillemet (le "-c" sert à dire qu'on spécifie la commande qui doit être exécutée).

  • Menu Text : Compile et Exécute
  • Command : C:\Programs\Msys\bin\sh.exe
  • Argument : -c "ocamlopt -o output.exe $(FileName) && ./output.exe < input.txt"
  • Initial Dir : $(FileDir)
  • Capture output : coché
  • Save before execute : coché

Remarques : avec les boutons flèche vers le haut et flèche vers le bas, il vous est possible de réorganiser les raccourcis claviers, pour associer à CTRL+1 et CTRL+2 les tâches que vous utilisez le plus souvent par exemple.

Pour tester si ça marche, prennez un source Caml, un fichier test.ml par exemple dans lequel vous mettez print_string "super". Lancez le raccourci, et normalement la compilation marche et juste en dessous s'affiche le texte super. Si vous modifiez le source n'importe comment pour qu'il ne compile plus, la chaîne super ne devrait pas s'afficher, et vous devriez avoir les messages d'erreurs du compilateur à la place.

Et encore mieux, maintenant, s'il n'y a pas assez de données dans le fichier input.txt, le programme s'arrête tout seul, car il détecte intelligement la fin du fichier. Prennons un exemple, mettez juste "5" dans le fichier input.txt et tapez le programme suivant dans test.ml.

let x = read_int() in 
let y = read_int() in
print_int y;

L'exécution vous dit qu'un End_of_file s'est produit, ce qui veut dire que vous avez atteint la fin du fichier d'entrée :

Fatal error: exception End_of_file

Compilation avec un Makefile

Les Makefile servent à effectuer des compilations plus avancées. Par exemple, si vous utilisez la librairie "Str" permettant d'utiliser des expressions régulières, vous aurez besoin de rajouter str.cma sur la ligne de compilation :

ocamlc -o output.exe str.cma test.ml

Plutôt que de créer un raccourci différent dans Crimson à chaque fois que vous avez besoin d'une petite variante comme cela, on va mettre cette ligne de commande dans un fichier, et ensuite exécuter les commandes qui se trouvent dans ce fichier. On ne va pas expliquer ici tout le fonctionnement des Makefiles, car c'est assez compliqué, mais on va juste donner un exemple qui marche, pour montrer un peu ce qu'on peut faire.

Configurons les trois outils suivants :

  • Menu Text : Make
  • Command : C:\Programs\Msys\bin\sh.exe
  • Argument : -c "make"
  • Initial Dir : $(FileDir)
  • Capture output : coché
  • Save before execute : coché

  • Menu Text : Make Opt
  • Command : C:\Programs\Msys\bin\sh.exe
  • Argument : -c "make opt"
  • Initial Dir : $(FileDir)
  • Capture output : coché
  • Save before execute : coché

  • Menu Text : Make Clean
  • Command : C:\Programs\Msys\bin\sh.exe
  • Argument : -c "make clean"
  • Initial Dir : $(FileDir)
  • Capture output : coché
  • Save before execute : coché

Dans le même dossier que là où se trouve les fichiers sources Caml du programme que l'on développe, on va créer un fichier nommée Makefile (Attention, avec un "M" majuscule conventionnellement, et sans aucune extension). Dedans, on va tapez tout ce qui suit. Attention, il est rigoureusement nécessaire d'utiliser une et une seule tabulation avant les lignes de commandes, et de ne pas mettre des espaces.

.PHONY: all opt clean

all:
	ocamlc -o output.exe str.cma test.ml

opt:
	ocamlopt -o output.exe str.cmxa test.ml

clean:
	rm -f *.{cmo,cmi,cmx,o,exe}

Expliquons un peu comment ça marche. La première ligne indique qu'il y a trois modes possibles. Le mode "all" (par défaut), le mode "opt" et le mode "clean". Pour chaque mode, on définit ensuite ce qu'il faut faire.

  • Ainsi dans le mode "all", on compile le fichier test.ml avec ocamlc.
  • Dans le mode "opt", on le compile avec ocamlopt.
  • Le mode "clean" est différent, il permet d'effacer (commande shell "rm") tous les fichiers générés au cours de la compilation. Ce sont les fichiers dont l'extension est ".cmo", ".cmi", ".cmx", ou encore ".o" et ".exe".

Pour lancer ces différents modes, il suffit d'utiliser les raccourcis claviers que l'on a créé juste avant.

Les Makefile permettent de faire des centaines de tâches bien plus complexes, et vous pourrez trouver de la documentation en tapant dans Google : "GNU make" ou "makefile tutorial", ou encore "GNU makefile reference".

Annexe : Résolution des problèmes

  • A la compilation, vous obtenez : "AS" n'est pas trouvé. L'installation de MinGW est incomplète ou alors MinGW n'est pas dans le PATH.
  • A la compilation, vous obtenez : "GCC" n'est pas trouvé pour le "link". L'installation de MinGW est incomplète ou alors MinGW n'est pas dans le PATH.

Annexe : Windows 98

En théorie, tout marche de la même manière, sauf la configuration du PATH, qui se fait dans le fichier c:\autoexec.bat. Rajoutez tout en bas du fichier la ligne:

PATH=%PATH%;c:\programs\mingw\bin;c:\programs\msys\bin