No, you will not have separate compilation without .mli
file : this is a problem of dependency graph. Instead of drawing a graph, I’ll write it in a Makefile
.
With .mli
file:
all: hello.byte hello.native
hello.byte: a.cmo b.cmo
ocamlc -o $@ $^
hello.native: a.cmx b.cmx
ocamlopt -o $@ $^
%.cmi: %.mli
ocamlc -c -opaque $<
%.cmo: %.ml
ocamlc -c $<
%.cmx: %.ml
ocamlopt -c $<
# objects files depend only on a.cmi
a.cmo a.cmx b.cmo b.cmx: a.cmi
Then the compilation is fully separated, if I touch a.ml
I will not have to recompile b.ml
:
% make
ocamlc -c -opaque a.mli
ocamlc -c a.ml
ocamlc -c b.ml
ocamlc -o hello.byte a.cmo b.cmo
ocamlopt -c a.ml
ocamlopt -c b.ml
ocamlopt -o hello.native a.cmx b.cmx
% touch a.ml
% make #no need to recompile b.ml
ocamlc -c a.ml
ocamlc -o hello.byte a.cmo b.cmo
ocamlopt -c a.ml
ocamlopt -o hello.native a.cmx b.cmx
Without .mli
, the dependency graph in the Makefile
will be:
all: hello.byte hello.native
hello.byte: a.cmo b.cmo
ocamlc -o $@ $^
hello.native: a.cmx b.cmx
ocamlopt -o $@ $^
%.cmo: %.ml
ocamlc -c $<
%.cmx: %.ml
ocamlopt -c $<
# objects files from b.ml depends on objects files from a.ml
b.cmo: a.cmo
b.cmx: a.cmx
Hence, if I touch a.ml
I have to recompile b.ml
, the compilation is not separated:
% make
ocamlc -c a.ml
ocamlc -c b.ml
ocamlc -o hello.byte a.cmo b.cmo
ocamlopt -c a.ml
ocamlopt -c b.ml
ocamlopt -o hello.native a.cmx b.cmx
% touch a.ml
% make #must recompile b.ml
ocamlc -c a.ml
ocamlc -c b.ml
ocamlc -o hello.byte a.cmo b.cmo
ocamlopt -c a.ml
ocamlopt -c b.ml
ocamlopt -o hello.native a.cmx b.cmx
Summary: with separate compilation, once you have a stable interface, you can modify its implementation without having to recompile every module which depends on it. 