-
Notifications
You must be signed in to change notification settings - Fork 1.2k
Some dependencies cannot be detected by ocamldep #5624
Description
Original bug ID: 5624
Reporter: @alainfrisch
Status: acknowledged (set by @damiendoligez on 2013-06-28T15:27:08Z)
Resolution: open
Priority: normal
Severity: minor
Target version: later
Category: tools (ocaml{lex,yacc,dep,debug,...})
Related to: #7080 #7470
Monitored by: @nojb @ygrek @glondu "Julien Signoles"
Bug description
ocamldep, because it operates purely syntactically on the source files, misses some dependencies need to unroll type abbreviations. Example: c.ml refers to a type B.t, which is defined in b.mli by "type t = A.t"; if c.ml does not otherwise refer to module A, there is no possibility for ocamldep to detect a dependency from c.cmo to a.cmi. Nevertheless, the compiler will indeed need a.cmi when compiling c.cmo.
Usually, this is not problematic, but it can be with non-trivial build rules which copy files around.
Example:
foo/a.mli: type t = int
foo/b.mli: type t = A.t
c.ml: let x : B.t = 2
and the following Makefile
## Implicit compilation rules
.SUFFIXES: .ml .mli .cmi .cmo
.mli.cmi:
ocamlc -c -I $(shell dirname $<) $<
.ml.cmo:
ocamlc -c -I $(shell dirname $<) $<
## Installation rules
a.cmi: foo/a.cmi
cp $< $@
b.cmi: foo/b.cmi
cp $< $@
## Dependencies (as understood by ocamldep)
c.cmo: b.cmi
foo/b.cmi: foo/a.cmi
Dependencies have been obtained with ocamldep -modules, and then translated to file dependencies according to the corresponding -I flags used for compilation (this is how ocamldep, and -- I assume -- ocamlbuild work). The inferred dependencies are:
foo/a.mli:
foo/b.mli: A
c.ml: B
Then make c.cmo fails because of a missing dependency from c.cmo to a.cmi.
Several approaches are possible to "fix" this:
-
Prevent the compiler from looking for a file
a.cmiunlessocamldep -modulesfinds a dependency to moduleA(i.e. run the dependency analysis before type-checking). This is not very nice, since some type abbreviations are interpreted as abstract types, and this can break type-checking in ways which are not straightforward to understand (the fix is to add a dummy reference toAif the abbreviation is needed). This is the approach we follow at LexiFi. -
Include dependent
.cmi. In the example above,b.cmiwould contain a copy ofa.cmi. Of course, this can lead to very large.cmifiles. -
An optimization is to inline only the required external type abbreviations in the
.cmifiles (in the example above,b.cmiwould be extended to include the fact thatA.t=int). Note that this solution can also improve compilation time, because the compiler doesn't need to search and open.cmifiles only to expand abbreviations.