Skip to content

Some dependencies cannot be detected by ocamldep #5624

@vicuna

Description

@vicuna

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.cmi unless ocamldep -modules finds a dependency to module A (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 to A if the abbreviation is needed). This is the approach we follow at LexiFi.

  • Include dependent .cmi. In the example above, b.cmi would contain a copy of a.cmi. Of course, this can lead to very large .cmi files.

  • An optimization is to inline only the required external type abbreviations in the .cmi files (in the example above, b.cmi would be extended to include the fact that A.t = int). Note that this solution can also improve compilation time, because the compiler doesn't need to search and open .cmi files only to expand abbreviations.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions