2010-05-10 28 views
4

J'essaye de trouver comment utiliser ocamlfind pour compiler une bibliothèque C et un exécutable OCaml en utilisant cette bibliothèque C.Compilation C lib et OCaml exe l'utilisant, tout en utilisant ocamlfind

J'ai mis en place un ensemble de fichiers d'exemple plutôt stupides.

% cat sillystubs.c 
#include <stdio.h> 

#include <caml/mlvalues.h> 
#include <caml/memory.h> 
#include <caml/alloc.h> 
#include <caml/custom.h> 

value 
caml_silly_silly(value unit) 
{ 
    CAMLparam1(unit); 
    printf("%s\n", __FILE__); 
    CAMLreturn(Val_unit); 
} 

% cat silly.mli 
external silly : unit -> unit = "silly_silly" 

% cat foo.ml 
open Silly 
open String 

let _ = 
    print_string "About to call into silly"; 
    silly(); 
    print_string "Called into silly" 

Je crois que ce qui suit est la façon de compiler la bibliothèque:

% ocamlfind ocamlc -c sillystubs.c 
% ar rc libsillystubs.a sillystubs.o 
% ocamlfind ocamlc -c silly.mli 
% ocamlfind ocamlc -a -o silly.cma -ccopt -L${PWD} -cclib -lsillystubs 

Maintenant, je ne semble pas être en mesure d'utiliser la bibliothèque créée si:

% ocamlfind ocamlc -custom -o foo foo.cmo silly.cma 
/usr/bin/ld: cannot find -lsillystubs 
collect2: ld returned 1 exit status 
File "_none_", line 1, characters 0-1: 
Error: Error while building custom runtime system 

Les outils OCaml sont quelque peu mystérieux pour moi, donc les pointeurs seraient les bienvenus.

+1

Pour que les utilisateurs puissent facilement copier-coller, corrigez une erreur en écrivant ocamlc comme ocmalc. –

Répondre

7

ocamlmklib à la rescousse. Etape par étape:

$ ocamlc -verbose -c sillystubs.c 
$ ocamlmklib -verbose sillystubs.o silly.mli -o silly 
$ ocamlc -verbose silly.cma foo.ml -o foo 
File "foo.ml", line 1, characters 0-1: 
Error: Error while linking foo.cmo: 
The external function `silly_silly' is not available 

Oups, vous défini dans caml_silly_silly sillystubs.c mais référence silly_silly dans silly.mli (tellement stupide :) Réparation:

$ cat silly.mli 
external silly : unit -> unit = "caml_silly_silly" 
$ ocamlmklib -verbose sillystubs.o silly.mli -o silly 
$ ocamlc -custom -verbose silly.cma foo.ml -o foo 
/usr/bin/ld: cannot find -lsilly 
collect2: ld returned 1 exit status 
File "foo.ml", line 1, characters 0-1: 
Error: Error while building custom runtime system 

Toujours pas de chance? Ajoutez -I. pour trouver les bibliothèques nécessaires.

$ ocamlc -I . -verbose silly.cma foo.ml -o foo.byte 
$ ocamlc -I . -verbose -custom silly.cma foo.ml -o foo.byte.custom 
$ ocamlopt -I . -verbose silly.cmxa foo.ml -o foo.native 

Mais dans la « vraie » la configuration que vous voulez bien installer la bibliothèque idiot avec ocamlfind puis la compilation en cours d'exécution par ocamlfind mettra les options en ligne de commande nécessaires en place et tout fonctionne automatiquement. Partant de zéro, toute la procédure se présente comme suit:

$ ocamlc -verbose -c sillystubs.c 
$ ocamlmklib -verbose sillystubs.o silly.mli -o silly 
$ cat META 
version="0" 
description="quite silly" 
archive(byte)="silly.cma" 
archive(native)="silly.cmxa" 
$ ocamlfind install silly META silly.cm* *.mli *.a *.so 
Installed /usr/local/lib/ocaml/3.11.2/silly/silly.a 
Installed /usr/local/lib/ocaml/3.11.2/silly/libsilly.a 
Installed /usr/local/lib/ocaml/3.11.2/silly/silly.mli 
Installed /usr/local/lib/ocaml/3.11.2/silly/silly.cmxa 
Installed /usr/local/lib/ocaml/3.11.2/silly/silly.cmi 
Installed /usr/local/lib/ocaml/3.11.2/silly/silly.cma 
Installed /usr/local/lib/ocaml/3.11.2/silly/META 
Installed /usr/local/lib/ocaml/3.11.2/stublibs/dllsilly.so 
Installed /usr/local/lib/ocaml/3.11.2/stublibs/dllsilly.so.owner 
$ rm *.cm* *.a *.so *.o 
$ ocamlfind ocamlopt -linkpkg -package silly foo.ml -o foo.native 
$ ocamlfind ocamlc -custom -linkpkg -package silly foo.ml -o foo.byte.custom 
$ ocamlfind ocamlc -linkpkg -package silly foo.ml -o foo.byte 

Les versions natives et octets sont prêtes. BTW ocamlc -custom est deprecated.

Mystère dévoilé J'espère.

1

Je suis une version en retard sur OCaml, mais il semble que silly.cma a sillystubs lié dynamiquement, vous devrez peut-être un

-ccopt -L${PWD} 

sur cette dernière ligne.

En outre, je ne vois rien que vous faites qui appelle la puissance supplémentaire de ocamlfind — vous pouvez aussi bien appeler ocamlc directement.

+0

J'ai essayé d'ajouter '-ccopt -L $ {PWD}'; le message d'erreur reste le même. Je ne pense pas non plus que le lien de 'silly.cma' sera lié dynamiquement dans' sillystubs', mais je ne suis pas sûr. Ceci est un exemple aussi simple que je pourrais construire pour illustrer mon problème avec la liaison en utilisant les outils OCaml. Dans le projet sur lequel je travaille, j'ai besoin de la puissance de 'ocamlfind'. – Magnus

+0

Vous étiez en effet correct, j'avais besoin d'un '-ccopt -L $ {PWD}', et il ne peut pas être n'importe où sur la ligne de commande! – Magnus