I am using Ocaml in the Bachelor introduction to programming class at ENS Rennes. I am encouraging my students to use an Abstract Data Types (ADT) approach with compiled modules and opaque data-types.
Each module is thus made of two parts: a signature adt.mli
part and an implementation part adt.ml
. The documentation at https://caml.inria.fr/pub/docs/manual-ocaml/moduleexamples.html is quite clear when those two files are located in the same directory.
However, they are now working on a project with several modules, respectively developed by separate groups. The groups share the interfaces adt.mli
in a Interfaces
repository, but not the implementation codes.
The question is then the procedure for one group to make adt.cma
. I first instructed them to do
$ ocamlc -c ../Interfaces/adt.mli
$ ocamlc -c adt.ml
Unfortunately, it does not work, as the adt.cmi
file is left in the Interfaces
repository, and it is not found on compiling adt.ml
. Instead, the default adt.cmi
file is rebuilt in the current directory.
I then tried
$ ocamlc -c ../Interfaces/adt.mli adt.ml
Surprisingly enough, it works!
Could somebody provide me with an explanation, so that I can tell my students?
Also, is it possible to tell ocamlc -c adt.ml
to look for the adt.cmi
file in another directory instead of rebuilding a local one?
Regards,
Luc.
I think you want to use -I:
ocamlc -c -I ../Interfaces adt.ml
Detailed information from the man page :
-I directory
Add the given directory to the list of directories searched for compiled interface files (.cmi), compiled object code files (.cmo), libraries (.cma), and C libraries specified with -cclib -l xxx . By default, the current directory is searched first, then the standard library directory. Directories added with -I are searched after the current directory, in the order in which they were given on the command line, but before the standard library directory. See also option -nostdlib .
If the given directory starts with + , it is taken relative to the standard library directory. For instance, -I +compiler-libs adds the subdirectory compiler-libs of the standard library to the search path.
3 Likes
I am not sure to understand your answer. Let me introduce the following example.
- Directory
Interface
: file test.mli
declares function f
and not function g
.
- Directory
Test
: file test.ml
defines f
and g
Experiment
$ more ../Interfaces/test.mli
val f : unit -> int
$ more test.ml
let f() = 0;;
let g() = 1;;
$ cd Interfaces/
$ ocamlc -c test.mli -o test.cmi
$ cd ../Test/
$ rm *.cm*
$ ocamlc -c -I ../Interfaces test.ml
$ ocaml -I ../Interfaces/ test.cmo
OCaml version 4.07.1
# Test.f();;
- : int = 0
# Test.g();;
- : int = 1
g
is defined, whereas it should not!
Did I miss something? Why is file ../Interfaces/test.cmi
missed by the compiler?